Merge m-c to fx-team.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 12 Feb 2014 15:59:34 -0500
changeset 168875 dca327ac440729ed0e85f5b38e5665164f01de9a
parent 168874 5add27ecfcb3589edd04dc85ec40cafa59641659 (current diff)
parent 168777 18e7634d4094be875342aae1426d619e0c6ea0bb (diff)
child 168876 d7f2934f2f29259ff04ef47d0c2ec44eeb7b8ef7
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone30.0a1
Merge m-c to fx-team.
js/src/jit-test/tests/TypedObject/gcunattachedhandle.js
js/src/tests/ecma_6/TypedObject/handle.js
js/src/tests/ecma_6/TypedObject/handle_get_set.js
js/src/tests/ecma_6/TypedObject/handle_move.js
js/src/tests/ecma_6/TypedObject/handle_unattached.js
mobile/android/base/AndroidManifest.xml.in
mobile/android/base/GeckoApp.java
mobile/android/base/WebApp.java.in
mobile/android/base/WebAppAllocator.java
mobile/android/base/WebAppFragmentRepeater.inc
mobile/android/base/WebAppImpl.java
mobile/android/base/WebAppManifestFragment.xml.frag.in
mobile/android/base/WebAppsFragment.java.frag
mobile/android/base/webapp/WebAppImpl.java
mobile/android/chrome/content/WebAppRT.js
mobile/android/chrome/content/browser.js
mobile/android/chrome/jar.mn
--- a/accessible/src/atk/AccessibleWrap.cpp
+++ b/accessible/src/atk/AccessibleWrap.cpp
@@ -686,16 +686,18 @@ getRoleCB(AtkObject *aAtkObj)
     default:
       MOZ_CRASH("Unknown role.");
   };
 
 #undef ROLE
 
   if (aAtkObj->role == ATK_ROLE_LIST_BOX && !IsAtkVersionAtLeast(2, 1))
     aAtkObj->role = ATK_ROLE_LIST;
+  else if (aAtkObj->role == ATK_ROLE_TABLE_ROW && !IsAtkVersionAtLeast(2, 1))
+    aAtkObj->role = ATK_ROLE_LIST_ITEM;
 
   return aAtkObj->role;
 }
 
 static AtkAttributeSet*
 ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes)
 {
     if (!aAttributes)
--- a/accessible/src/atk/nsMai.h
+++ b/accessible/src/atk/nsMai.h
@@ -34,12 +34,13 @@ extern int atkMajorVersion, atkMinorVers
 
 /**
  * Return true if the loaded version of libatk-1.0.so is at least
  * aMajor.aMinor.0.
  */
 static inline bool
 IsAtkVersionAtLeast(int aMajor, int aMinor)
 {
-  return aMajor < atkMajorVersion && aMinor < atkMinorVersion;
+  return aMajor < atkMajorVersion ||
+         (aMajor == atkMajorVersion && aMinor <= atkMinorVersion);
 }
 
 #endif /* __NS_MAI_H__ */
--- a/accessible/src/base/RoleMap.h
+++ b/accessible/src/base/RoleMap.h
@@ -237,17 +237,17 @@ ROLE(COLUMN,
      ATK_ROLE_UNKNOWN,
      NSAccessibilityColumnRole,
      ROLE_SYSTEM_COLUMN,
      ROLE_SYSTEM_COLUMN,
      eNameFromSubtreeRule)
 
 ROLE(ROW,
      "row",
-     ATK_ROLE_LIST_ITEM,
+     ATK_ROLE_TABLE_ROW,
      NSAccessibilityRowRole,
      ROLE_SYSTEM_ROW,
      ROLE_SYSTEM_ROW,
      eNameFromSubtreeRule)
 
 ROLE(CELL,
      "cell",
      ATK_ROLE_TABLE_CELL,
--- a/b2g/chrome/content/devtools.js
+++ b/b2g/chrome/content/devtools.js
@@ -198,28 +198,51 @@ App.prototype = {
     // FIXME(after bug 963239 lands) return event.isDefaultPrevented();
     return false;
   }
 
 };
 
 
 /**
- * The Console Watcher tracks the following metrics in apps: errors, warnings,
- * and reflows.
+ * The Console Watcher tracks the following metrics in apps: reflows, warnings,
+ * and errors.
  */
 let consoleWatcher = {
 
   _apps: new Map(),
+  _watching: {
+    reflows: false,
+    warnings: false,
+    errors: false
+  },
   _client: null,
 
   init: function cw_init(client) {
     this._client = client;
     this.consoleListener = this.consoleListener.bind(this);
 
+    let watching = this._watching;
+
+    for (let key in watching) {
+      let metric = key;
+      SettingsListener.observe('devtools.hud.' + metric, false, value => {
+        // Watch or unwatch the metric.
+        if (watching[metric] = value) {
+          return;
+        }
+
+        // If unwatched, remove any existing widgets for that metric.
+        for (let app of this._apps.values()) {
+          app.metrics.set(metric, 0);
+          app.display();
+        }
+      });
+    }
+
     client.addListener('logMessage', this.consoleListener);
     client.addListener('pageError', this.consoleListener);
     client.addListener('consoleAPICall', this.consoleListener);
     client.addListener('reflowActivity', this.consoleListener);
   },
 
   trackApp: function cw_trackApp(app) {
     app.metrics.set('reflows', 0);
@@ -241,57 +264,78 @@ let consoleWatcher = {
       type: 'stopListeners',
       listeners: ['LogMessage', 'PageError', 'ConsoleAPI', 'ReflowActivity']
     }, (res) => { });
 
     this._apps.delete(app.actor.consoleActor);
   },
 
   bump: function cw_bump(app, metric) {
+    if (!this._watching[metric]) {
+      return false;
+    }
+
     let metrics = app.metrics;
     metrics.set(metric, metrics.get(metric) + 1);
+    return true;
   },
 
   consoleListener: function cw_consoleListener(type, packet) {
     let app = this._apps.get(packet.from);
     let output = '';
 
     switch (packet.type) {
 
       case 'pageError':
         let pageError = packet.pageError;
+
         if (pageError.warning || pageError.strict) {
-          this.bump(app, 'warnings');
+          if (!this.bump(app, 'warnings')) {
+            return;
+          }
           output = 'warning (';
         } else {
-          this.bump(app, 'errors');
+          if (!this.bump(app, 'errors')) {
+            return;
+          }
           output += 'error (';
         }
+
         let {errorMessage, sourceName, category, lineNumber, columnNumber} = pageError;
         output += category + '): "' + (errorMessage.initial || errorMessage) +
           '" in ' + sourceName + ':' + lineNumber + ':' + columnNumber;
         break;
 
       case 'consoleAPICall':
         switch (packet.message.level) {
+
           case 'error':
-            this.bump(app, 'errors');
+            if (!this.bump(app, 'errors')) {
+              return;
+            }
             output = 'error (console)';
             break;
+
           case 'warn':
-            this.bump(app, 'warnings');
+            if (!this.bump(app, 'warnings')) {
+              return;
+            }
             output = 'warning (console)';
             break;
+
           default:
             return;
         }
         break;
 
       case 'reflowActivity':
-        this.bump(app, 'reflows');
+        if (!this.bump(app, 'reflows')) {
+          return;
+        }
+
         let {start, end, sourceURL} = packet;
         let duration = Math.round((end - start) * 100) / 100;
         output = 'reflow: ' + duration + 'ms';
         if (sourceURL) {
           output += ' ' + this.formatSourceURL(packet);
         }
         break;
     }
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -1,22 +1,22 @@
 <?xml version="1.0" ?><manifest>
   <remote fetch="https://git.mozilla.org/external/aosp" name="aosp"/>
   <remote fetch="https://git.mozilla.org/b2g" name="b2g"/>
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="317f25e0a4cb3e8e86e2b76c37a14081372f0307">
+  <project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
     <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="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- 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"/>
@@ -113,18 +113,18 @@
   <project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
   <project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
   <project name="platform/system/media" path="system/media" revision="d90b836f66bf1d9627886c96f3a2d9c3007fbb80"/>
   <project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
   <project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
   <project name="platform/system/vold" path="system/vold" revision="8de05d4a52b5a91e7336e6baa4592f945a6ddbea"/>
   <default remote="caf" revision="refs/tags/android-4.3_r2.1" sync-j="4"/>
   <!-- Emulator specific things -->
+  <project name="android-development" path="development" remote="b2g" revision="dab55669da8f48b6e57df95d5af9f16b4a87b0b1"/>
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="09485b73629856b21b2ed6073e327ab0e69a1189"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8f7c9ac889ae2c778197b4a4c0529d60530f480b"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="2838a77ce4b8c09fa6a46fe25410bb3a4474cbd4"/>
   <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="a962b2ed2195038cd566493c3f7968bea9d20189"/>
-  <project name="platform/development" path="development" revision="1f18cfe031ce23b7fb838fe3d4379dd802b49e71"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
 </manifest>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "9da6724d2e1af0c60e5fd64c8a79c9c9c0106c9f", 
+    "revision": "179466c0aa4fd4d937a6d04d9cd136e687fa2993", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -5,17 +5,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <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/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <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/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -1,22 +1,22 @@
 <?xml version="1.0" ?><manifest>
   <remote fetch="https://git.mozilla.org/external/aosp" name="aosp"/>
   <remote fetch="https://git.mozilla.org/b2g" name="b2g"/>
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="317f25e0a4cb3e8e86e2b76c37a14081372f0307">
+  <project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
     <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="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- 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/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="2e546129dd7860ee3e62b3f86ab222647dfcaae4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a403bdf3cf2a09b5ed0ed5aee362d8b7b31810b3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/build/autoconf/icu.m4
+++ b/build/autoconf/icu.m4
@@ -163,17 +163,17 @@ if test -z "$BUILDING_JS" -o -n "$JS_STA
     		ICU_TARGET=MacOSX
     		;;
     	    Linux)
     		ICU_TARGET=Linux
     		;;
     	    WINNT)
     		ICU_TARGET=MSYS/MSVC
     		;;
-    	    *bsd*|dragonfly*)
+            DragonFly|FreeBSD|NetBSD|OpenBSD|GNU_kFreeBSD)
     		ICU_TARGET=BSD
     		;;
     	esac
     	# Remove _DEPEND_CFLAGS from HOST_FLAGS to avoid configure error
     	HOST_ICU_CFLAGS="$HOST_CFLAGS"
     	HOST_ICU_CXXFLAGS="$HOST_CXXFLAGS"
 
     	HOST_ICU_CFLAGS=`echo $HOST_ICU_CFLAGS | sed "s|$_DEPEND_CFLAGS||g"`
--- a/configure.in
+++ b/configure.in
@@ -1018,16 +1018,34 @@ mingw*)
     HOST_OS_ARCH=WINNT
     ;;
 darwin*)
     HOST_OS_ARCH=Darwin
     ;;
 linux*)
     HOST_OS_ARCH=Linux
     ;;
+kfreebsd*-gnu)
+    HOST_OS_ARCH=GNU_kFreeBSD
+    ;;
+gnu*)
+    HOST_OS_ARCH=GNU
+    ;;
+dragonfly*)
+    HOST_OS_ARCH=DragonFly
+    ;;
+freebsd*)
+    HOST_OS_ARCH=FreeBSD
+    ;;
+netbsd*)
+    HOST_OS_ARCH=NetBSD
+    ;;
+openbsd*)
+    HOST_OS_ARCH=OpenBSD
+    ;;
 solaris*)
     HOST_OS_ARCH=SunOS
     SOLARIS_SUNPRO_CC=
     SOLARIS_SUNPRO_CXX=
     if test -z "$GNU_CC"; then
         if test "`$CC -V 2>&1 | egrep -c 'Sun.*C '`" != "0"; then
             SOLARIS_SUNPRO_CC=1
        fi
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -452,29 +452,30 @@ nsFrameMessageManager::GetDelayedFrameSc
   // Frame message managers may return an incomplete list because scripts
   // that were loaded after it was connected are not added to the list.
   if (!IsGlobal() && !IsWindowLevel()) {
     NS_WARNING("Cannot retrieve list of pending frame scripts for frame"
                "message managers as it may be incomplete");
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
-  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, mPendingScripts.Length(), nullptr));
+  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, mPendingScripts.Length()));
   NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
 
   JS::Rooted<JSString*> url(aCx);
   JS::Rooted<JSObject*> pair(aCx);
   for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
     url = JS_NewUCStringCopyN(aCx, mPendingScripts[i].get(), mPendingScripts[i].Length());
     NS_ENSURE_TRUE(url, NS_ERROR_OUT_OF_MEMORY);
 
-    JS::Value pairElts[] = { JS::StringValue(url),
-                             JS::BooleanValue(mPendingScriptsGlobalStates[i]) };
+    JS::AutoValueArray<2> pairElts(aCx);
+    pairElts[0].setString(url);
+    pairElts[1].setBoolean(mPendingScriptsGlobalStates[i]);
 
-    pair = JS_NewArrayObject(aCx, 2, pairElts);
+    pair = JS_NewArrayObject(aCx, pairElts);
     NS_ENSURE_TRUE(pair, NS_ERROR_OUT_OF_MEMORY);
 
     NS_ENSURE_TRUE(JS_SetElement(aCx, array, i, pair),
                    NS_ERROR_OUT_OF_MEMORY);
   }
 
   aList.setObject(*array);
   return NS_OK;
@@ -593,17 +594,17 @@ nsFrameMessageManager::SendMessage(const
     sSendingSyncMessage = false;
   }
 
   if (!rv) {
     return NS_OK;
   }
 
   uint32_t len = retval.Length();
-  JS::Rooted<JSObject*> dataArray(aCx, JS_NewArrayObject(aCx, len, nullptr));
+  JS::Rooted<JSObject*> dataArray(aCx, JS_NewArrayObject(aCx, len));
   NS_ENSURE_TRUE(dataArray, NS_ERROR_OUT_OF_MEMORY);
 
   for (uint32_t i = 0; i < len; ++i) {
     if (retval[i].IsEmpty()) {
       continue;
     }
 
     JS::Rooted<JS::Value> ret(aCx);
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -1240,24 +1240,23 @@ CanvasRenderingContext2D::SetTransform(d
 
   Matrix matrix(m11, m12, m21, m22, dx, dy);
   mTarget->SetTransform(matrix);
 }
 
 JSObject*
 MatrixToJSObject(JSContext* cx, const Matrix& matrix, ErrorResult& error)
 {
-  JS::Value elts[] = {
-    DOUBLE_TO_JSVAL(matrix._11), DOUBLE_TO_JSVAL(matrix._12),
-    DOUBLE_TO_JSVAL(matrix._21), DOUBLE_TO_JSVAL(matrix._22),
-    DOUBLE_TO_JSVAL(matrix._31), DOUBLE_TO_JSVAL(matrix._32)
-  };
+  JS::AutoValueArray<6> elts(cx);
+  elts[0].setDouble(matrix._11); elts[1].setDouble(matrix._12);
+  elts[2].setDouble(matrix._21); elts[3].setDouble(matrix._22);
+  elts[4].setDouble(matrix._31); elts[5].setDouble(matrix._32);
 
   // XXX Should we enter GetWrapper()'s compartment?
-  JSObject* obj = JS_NewArrayObject(cx, 6, elts);
+  JSObject* obj = JS_NewArrayObject(cx, elts);
   if  (!obj) {
     error.Throw(NS_ERROR_OUT_OF_MEMORY);
   }
   return obj;
 }
 
 static bool
 ObjectToMatrix(JSContext* cx, JS::Handle<JSObject*> obj, Matrix& matrix,
--- a/content/canvas/src/CanvasUtils.h
+++ b/content/canvas/src/CanvasUtils.h
@@ -153,17 +153,17 @@ template<typename T>
 JS::Value
 DashArrayToJSVal(FallibleTArray<T>& dashes,
                  JSContext* cx, mozilla::ErrorResult& rv)
 {
     if (dashes.IsEmpty()) {
         return JSVAL_NULL;
     }
     JS::Rooted<JSObject*> obj(cx,
-        JS_NewArrayObject(cx, dashes.Length(), nullptr));
+        JS_NewArrayObject(cx, dashes.Length()));
     if (!obj) {
         rv.Throw(NS_ERROR_OUT_OF_MEMORY);
         return JSVAL_NULL;
     }
     for (uint32_t i = 0; i < dashes.Length(); ++i) {
         double d = dashes[i];
         JS::Value elt = DOUBLE_TO_JSVAL(d);
         if (!JS_DefineElement(cx, obj, i, elt, nullptr, nullptr, 0)) {
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -1902,20 +1902,20 @@ WebGLContext::GetUniform(JSContext* cx, 
             return JS::ObjectOrNullValue(obj);
         }
     } else if (baseType == LOCAL_GL_BOOL) {
         GLint iv[16] = { 0 };
         gl->fGetUniformiv(progname, location->Location(), iv);
         if (unitSize == 1) {
             return JS::BooleanValue(iv[0] ? true : false);
         } else {
-            JS::Value uv[16];
+            JS::AutoValueArray<16> uv(cx);
             for (int k = 0; k < unitSize; k++)
-                uv[k] = JS::BooleanValue(iv[k] ? true : false);
-            JSObject* obj = JS_NewArrayObject(cx, unitSize, uv);
+                uv[k].setBoolean(iv[k]);
+            JSObject* obj = JS_NewArrayObject(cx, JS::HandleValueArray::subarray(uv, 0, unitSize));
             if (!obj) {
                 ErrorOutOfMemory("getUniform: out of memory");
                 return JS::NullValue();
             }
             return JS::ObjectOrNullValue(obj);
         }
     }
 
--- a/content/canvas/src/WebGLContextState.cpp
+++ b/content/canvas/src/WebGLContextState.cpp
@@ -418,21 +418,22 @@ WebGLContext::GetParameter(JSContext* cx
             }
             return JS::ObjectOrNullValue(obj);
         }
 
         case LOCAL_GL_COLOR_WRITEMASK: // 4 bools
         {
             realGLboolean gl_bv[4] = { 0 };
             gl->fGetBooleanv(pname, gl_bv);
-            JS::Value vals[4] = { JS::BooleanValue(bool(gl_bv[0])),
-                JS::BooleanValue(bool(gl_bv[1])),
-                JS::BooleanValue(bool(gl_bv[2])),
-                JS::BooleanValue(bool(gl_bv[3])) };
-            JSObject* obj = JS_NewArrayObject(cx, 4, vals);
+            JS::AutoValueArray<4> vals(cx);
+            vals[0].setBoolean(gl_bv[0]);
+            vals[1].setBoolean(gl_bv[1]);
+            vals[2].setBoolean(gl_bv[2]);
+            vals[3].setBoolean(gl_bv[3]);
+            JSObject* obj = JS_NewArrayObject(cx, vals);
             if (!obj) {
                 rv = NS_ERROR_OUT_OF_MEMORY;
             }
             return JS::ObjectOrNullValue(obj);
         }
 
         case LOCAL_GL_ARRAY_BUFFER_BINDING:
         {
--- a/content/media/directshow/AudioSinkInputPin.cpp
+++ b/content/media/directshow/AudioSinkInputPin.cpp
@@ -4,17 +4,16 @@
  * 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 "AudioSinkInputPin.h"
 #include "AudioSinkFilter.h"
 #include "SampleSink.h"
 #include "prlog.h"
 
-#include <initguid.h>
 #include <wmsdkidl.h>
 
 using namespace mozilla::media;
 
 namespace mozilla {
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* GetDirectShowLog();
--- a/content/media/directshow/moz.build
+++ b/content/media/directshow/moz.build
@@ -8,25 +8,28 @@ EXPORTS += [
     'AudioSinkFilter.h',
     'AudioSinkInputPin.h',
     'DirectShowDecoder.h',
     'DirectShowReader.h',
     'DirectShowUtils.h',
 ]
 
 UNIFIED_SOURCES += [
-    'AudioSinkFilter.cpp',
     'AudioSinkInputPin.cpp',
     'DirectShowDecoder.cpp',
     'DirectShowReader.cpp',
     'DirectShowUtils.cpp',
     'SampleSink.cpp',
     'SourceFilter.cpp',
 ]
 
+SOURCES += [
+    'AudioSinkFilter.cpp',
+]
+
 # If WebRTC isn't being built, we need to compile the DirectShow base classes so that
 # they're available at link time.
 if not CONFIG['MOZ_WEBRTC']:
     SOURCES += [ '%s/%s' % (TOPSRCDIR, p) for p in [
         'media/webrtc/trunk/webrtc/modules/video_capture/windows/BaseFilter.cpp',
         'media/webrtc/trunk/webrtc/modules/video_capture/windows/BaseInputPin.cpp',
         'media/webrtc/trunk/webrtc/modules/video_capture/windows/BasePin.cpp',
         'media/webrtc/trunk/webrtc/modules/video_capture/windows/MediaType.cpp',
--- a/content/media/encoder/fmp4_muxer/ISOControl.cpp
+++ b/content/media/encoder/fmp4_muxer/ISOControl.cpp
@@ -250,39 +250,39 @@ ISOControl::GetFragment(uint32_t aType)
 }
 
 nsresult
 ISOControl::GetBufs(nsTArray<nsTArray<uint8_t>>* aOutputBufs)
 {
   uint32_t len = mOutBuffers.Length();
   for (uint32_t i = 0; i < len; i++) {
     mOutBuffers[i].SwapElements(*aOutputBufs->AppendElement());
-    mOutputSize += mOutBuffers[i].Length();
   }
   return FlushBuf();
 }
 
 nsresult
 ISOControl::FlushBuf()
 {
   mOutBuffers.SetLength(1);
-  mLastWrittenBoxPos = 0;
   return NS_OK;
 }
 
 uint32_t
 ISOControl::WriteAVData(nsTArray<uint8_t>& aArray)
 {
   MOZ_ASSERT(!mBitCount);
 
   uint32_t len = aArray.Length();
   if (!len) {
     return 0;
   }
 
+  mOutputSize += len;
+
   // The last element already has data, allocated a new element for pointer
   // swapping.
   if (mOutBuffers.LastElement().Length()) {
     mOutBuffers.AppendElement();
   }
   // Swap the video/audio data pointer.
   mOutBuffers.LastElement().SwapElements(aArray);
   // Following data could be boxes, so appending a new uint8_t array here.
@@ -309,16 +309,17 @@ ISOControl::WriteBits(uint64_t aBits, si
   }
   return output_byte;
 }
 
 uint32_t
 ISOControl::Write(uint8_t* aBuf, uint32_t aSize)
 {
   mOutBuffers.LastElement().AppendElements(aBuf, aSize);
+  mOutputSize += aSize;
   return aSize;
 }
 
 uint32_t
 ISOControl::Write(uint8_t aData)
 {
   MOZ_ASSERT(!mBitCount);
   Write((uint8_t*)&aData, sizeof(uint8_t));
@@ -378,17 +379,17 @@ ISOControl::GenerateMoov()
 
 nsresult
 ISOControl::GenerateMoof(uint32_t aTrackType)
 {
   mFragNum++;
 
   nsresult rv;
   uint32_t size;
-  uint64_t first_sample_offset = mOutputSize + mLastWrittenBoxPos;
+  uint64_t first_sample_offset = mOutputSize;
   nsAutoPtr<MovieFragmentBox> moof_box(new MovieFragmentBox(aTrackType, this));
   nsAutoPtr<MediaDataBox> mdat_box(new MediaDataBox(aTrackType, this));
 
   rv = moof_box->Generate(&size);
   NS_ENSURE_SUCCESS(rv, rv);
   first_sample_offset += size;
   rv = mdat_box->Generate(&size);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/content/media/encoder/fmp4_muxer/ISOControl.h
+++ b/content/media/encoder/fmp4_muxer/ISOControl.h
@@ -224,21 +224,17 @@ private:
   //   mOutBuffers[2] --> video raw data (allocated by encoder)
   //   mOutBuffers[3] --> video raw data (allocated by encoder)
   //   mOutBuffers[4] --> boxes (allocated by muxer)
   //   mOutBuffers[5] --> audio raw data (allocated by encoder)
   //   ...etc.
   //
   nsTArray<nsTArray<uint8_t>> mOutBuffers;
 
-  // Last written position of current box, it is for box checking purpose and
-  // calculating the sample offset in moof.
-  uint32_t mLastWrittenBoxPos;
-
-  // Accumulate size of output fragments.
+  // Accumulate output size from Write().
   uint64_t mOutputSize;
 
   // Bit writing operation. Note: the mBitCount should be 0 before any
   // byte-boundary writing method be called (Write(uint32_t), Write(uint16_t)...etc);
   // otherwise, there will be assertion on these functions.
   uint8_t mBitCount;
   uint8_t mBit;
 };
--- a/content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp
+++ b/content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp
@@ -37,19 +37,16 @@ Box::BoxSizeChecker::BoxSizeChecker(ISOC
 
 Box::BoxSizeChecker::~BoxSizeChecker()
 {
   uint32_t cur_size = mControl->GetBufPos();
   if ((cur_size - ori_size) != box_size) {
     MOZ_ASSERT(false);
   }
 
-  // Keeps the last box size position, it is for counting the sample offset when
-  // generating moof.
-  mControl->mLastWrittenBoxPos += box_size;
   MOZ_COUNT_DTOR(BoxSizeChecker);
 }
 
 nsresult
 MediaDataBox::Generate(uint32_t* aBoxSize)
 {
   mFirstSampleOffset = size;
   mAllSampleSize = 0;
--- a/content/media/test/test_mediarecorder_record_no_timeslice.html
+++ b/content/media/test/test_mediarecorder_record_no_timeslice.html
@@ -80,16 +80,17 @@ function startTest(test, token) {
       if (onStopFired) {
         ok(false, 'ondataavailable unexpectedly fired later than onstop');
         manager.finished(token);
       }
     }
   };
 
   element.oncanplaythrough = function () {
+    element.oncanplaythrough = null;
     // If content has ended, skip the test
     if (element.ended) {
       ok(true, 'ended fired before canplaythrough, skipping test');
       manager.finished(token);
     } else {
       // If content hasn't ended, start recording
       mediaRecorder.start();
       is(mediaRecorder.state, 'recording',
--- a/content/media/test/test_mediarecorder_record_session.html
+++ b/content/media/test/test_mediarecorder_record_session.html
@@ -50,16 +50,17 @@ function startTest(test, token) {
     ok(false, 'Unexpected error fired with:' + err);
   }
 
   mediaRecorder.onwarning = function() {
     ok(false, 'Unexpected warning fired');
   }
 
   element.oncanplaythrough = function () {
+    element.oncanplaythrough = null;
     for (var i = 0; i < mExpectStopCount; i++) {
       mediaRecorder.start(1000);
       mediaRecorder.stop();
     }
   }
 
   element.play();
 }
--- a/content/media/test/test_mediarecorder_record_timeslice.html
+++ b/content/media/test/test_mediarecorder_record_timeslice.html
@@ -81,16 +81,17 @@ function startTest(test, token) {
     } else if (dataAvailableCount === 2) {
       // Ensure we've received at least two ondataavailable events before onstop
       onDataAvailableFirst = true;
     }
   };
 
   // Start recording once canplaythrough fires
   element.oncanplaythrough = function() {
+    element.oncanplaythrough = null;
     mediaRecorder.start(250);
     is(mediaRecorder.state, 'recording', 'Media recorder should be recording');
     is(mediaRecorder.stream, element.stream,
        'Media recorder stream = element stream at the start of recording');
   };
 
   element.play();
 }
--- a/content/media/test/test_mediarecorder_state_transition.html
+++ b/content/media/test/test_mediarecorder_state_transition.html
@@ -151,16 +151,17 @@ function startTest(test, token) {
   element.token = token;
   manager.started(token);
 
   element.src = test.name;
   element.test = test;
   element.stream = element.mozCaptureStream();
 
   element.oncanplaythrough = function () {
+    element.oncanplaythrough = null;
     runStateTransitionTests(element.stream);
     manager.finished(token);
   };
 
   element.play();
 }
 
 manager.runTests(gMediaRecorderTests, startTest);
--- a/content/media/webspeech/recognition/test/mochitest.ini
+++ b/content/media/webspeech/recognition/test/mochitest.ini
@@ -7,8 +7,9 @@ support-files =
 [test_abort.html]
 [test_audio_capture_error.html]
 [test_call_start_from_end_handler.html]
 [test_nested_eventloop.html]
 [test_preference_enable.html]
 [test_recognition_service_error.html]
 [test_success_without_recognition_service.html]
 [test_timeout.html]
+skip-if = os == "win"
--- a/content/media/wmf/WMF.h
+++ b/content/media/wmf/WMF.h
@@ -24,17 +24,16 @@ which makes Windows Media Foundation una
 #include <mfidl.h>
 #include <mfreadwrite.h>
 #include <mfobjects.h>
 #include <ks.h>
 #include <stdio.h>
 #include <mferror.h>
 #include <propvarutil.h>
 #include <wmcodecdsp.h>
-#include <initguid.h>
 #include <d3d9.h>
 #include <dxva2api.h>
 #include <wmcodecdsp.h>
 #include <codecapi.h>
 
 // Some SDK versions don't define the AAC decoder CLSID.
 #ifndef CLSID_CMSAACDecMFT
 extern "C" const CLSID CLSID_CMSAACDecMFT;
--- a/content/media/wmf/WMFUtils.cpp
+++ b/content/media/wmf/WMFUtils.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/WindowsVersion.h"
 #include "prlog.h"
 #include "nsThreadUtils.h"
 #include "nsWindowsHelpers.h"
 #include "mozilla/CheckedInt.h"
 #include "VideoUtils.h"
+#include <initguid.h>
 
 #ifdef WMF_MUST_DEFINE_AAC_MFT_CLSID
 // Some SDK versions don't define the AAC decoder CLSID.
 // {32D186A7-218F-4C75-8876-DD77273A8999}
 DEFINE_GUID(CLSID_CMSAACDecMFT, 0x32D186A7, 0x218F, 0x4C75, 0x88, 0x76, 0xDD, 0x77, 0x27, 0x3A, 0x89, 0x99);
 #endif
 
 namespace mozilla {
--- a/content/media/wmf/moz.build
+++ b/content/media/wmf/moz.build
@@ -13,14 +13,17 @@ EXPORTS += [
 ]
 
 UNIFIED_SOURCES += [
     'DXVA2Manager.cpp',
     'WMFByteStream.cpp',
     'WMFDecoder.cpp',
     'WMFReader.cpp',
     'WMFSourceReaderCallback.cpp',
+]
+
+SOURCES += [
     'WMFUtils.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'gklayout'
--- a/dom/base/MessagePort.cpp
+++ b/dom/base/MessagePort.cpp
@@ -367,19 +367,25 @@ MessagePort::PostMessageMoz(JSContext* a
   JSAutoStructuredCloneBuffer buffer;
   StructuredCloneInfo scInfo;
   scInfo.mEvent = event;
   scInfo.mPort = this;
 
   JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
   if (aTransferable.WasPassed()) {
     const Sequence<JS::Value>& realTransferable = aTransferable.Value();
+
+    // The input sequence only comes from the generated bindings code, which
+    // ensures it is rooted.
+    JS::HandleValueArray elements =
+      JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(),
+                                               realTransferable.Elements());
+
     JSObject* array =
-      JS_NewArrayObject(aCx, realTransferable.Length(),
-                        const_cast<JS::Value*>(realTransferable.Elements()));
+      JS_NewArrayObject(aCx, elements);
     if (!array) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     transferable.setObject(*array);
   }
 
   if (!buffer.write(aCx, aMessage, transferable, &kPostMessageCallbacks,
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7935,19 +7935,23 @@ void
 nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                                const nsAString& aTargetOrigin,
                                const Optional<Sequence<JS::Value > >& aTransfer,
                                ErrorResult& aError)
 {
   JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
   if (aTransfer.WasPassed()) {
     const Sequence<JS::Value >& values = aTransfer.Value();
-    transferArray = JS::ObjectOrNullValue(JS_NewArrayObject(aCx,
-                                                            values.Length(),
-                                                            const_cast<JS::Value*>(values.Elements())));
+
+    // The input sequence only comes from the generated bindings code, which
+    // ensures it is rooted.
+    JS::HandleValueArray elements =
+      JS::HandleValueArray::fromMarkedLocation(values.Length(), values.Elements());
+
+    transferArray = JS::ObjectOrNullValue(JS_NewArrayObject(aCx, elements));
     if (transferArray.isNull()) {
       aError.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
   }
 
   PostMessageMoz(aCx, aMessage, aTargetOrigin, transferArray, aError);
 }
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1164,17 +1164,17 @@ nsJSContext::SetProperty(JS::Handle<JSOb
   // got the arguments, now attach them.
 
   for (uint32_t i = 0; i < args.length(); ++i) {
     if (!JS_WrapValue(mContext, args.handleAt(i))) {
       return NS_ERROR_FAILURE;
     }
   }
 
-  JSObject* array = ::JS_NewArrayObject(mContext, args.length(), args.begin());
+  JSObject* array = ::JS_NewArrayObject(mContext, args);
   if (!array) {
     return NS_ERROR_FAILURE;
   }
   JS::Rooted<JS::Value> arrayVal(mContext, JS::ObjectValue(*array));
 
   return JS_DefineProperty(mContext, aTarget, aPropName, arrayVal,
                            nullptr, nullptr, 0) ? NS_OK : NS_ERROR_FAILURE;
 }
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -4423,17 +4423,17 @@ if (%s.IsNull()) {
                 'exceptionCode': exceptionCode,
                 'obj': "returnArray"
                 }
             )
         sequenceWrapLevel -= 1
         innerTemplate = CGIndenter(CGGeneric(innerTemplate), 6).define()
         return (("""
 uint32_t length = %s.Length();
-JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length, nullptr));
+JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
 if (!returnArray) {
 %s
 }
 // Scope for 'tmp'
 {
   JS::Rooted<JS::Value> tmp(cx);
   for (uint32_t %s = 0; %s < length; ++%s) {
     // Control block to let us common up the JS_DefineElement calls when there
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -753,27 +753,31 @@ BrowserElementChild.prototype = {
     // but once we've waited maxDelayMS milliseconds, go ahead and take it
     // anyway.
     Cc['@mozilla.org/message-loop;1'].getService(Ci.nsIMessageLoop).postIdleTask(
       takeScreenshotClosure, maxDelayMS);
   },
 
   /**
    * Actually take a screenshot and foward the result up to our parent, given
-   * the desired maxWidth and maxHeight, and given the DOMRequest ID associated
-   * with the request from the parent.
+   * the desired maxWidth and maxHeight (in CSS pixels), and given the
+   * DOMRequest ID associated with the request from the parent.
    */
   _takeScreenshot: function(maxWidth, maxHeight, mimeType, domRequestID) {
     // You can think of the screenshotting algorithm as carrying out the
     // following steps:
     //
+    // - Calculate maxWidth, maxHeight, and viewport's width and height in the
+    //   dimension of device pixels by multiply the numbers with
+    //   window.devicePixelRatio.
+    //
     // - Let scaleWidth be the factor by which we'd need to downscale the
-    //   viewport so it would fit within maxWidth.  (If the viewport's width
-    //   is less than maxWidth, let scaleWidth be 1.) Compute scaleHeight
-    //   the same way.
+    //   viewport pixel width so it would fit within maxPixelWidth.
+    //   (If the viewport's pixel width is less than maxPixelWidth, let
+    //   scaleWidth be 1.) Compute scaleHeight the same way.
     //
     // - Scale the viewport by max(scaleWidth, scaleHeight).  Now either the
     //   viewport's width is no larger than maxWidth, the viewport's height is
     //   no larger than maxHeight, or both.
     //
     // - Crop the viewport so its width is no larger than maxWidth and its
     //   height is no larger than maxHeight.
     //
@@ -789,35 +793,45 @@ BrowserElementChild.prototype = {
 
     if (!content) {
       // If content is not loaded yet, bail out since even sendAsyncMessage
       // fails...
       debug("No content yet!");
       return;
     }
 
-    let scaleWidth = Math.min(1, maxWidth / content.innerWidth);
-    let scaleHeight = Math.min(1, maxHeight / content.innerHeight);
+    let devicePixelRatio = content.devicePixelRatio;
+
+    let maxPixelWidth = Math.round(maxWidth * devicePixelRatio);
+    let maxPixelHeight = Math.round(maxHeight * devicePixelRatio);
+
+    let contentPixelWidth = content.innerWidth * devicePixelRatio;
+    let contentPixelHeight = content.innerHeight * devicePixelRatio;
+
+    let scaleWidth = Math.min(1, maxPixelWidth / contentPixelWidth);
+    let scaleHeight = Math.min(1, maxPixelHeight / contentPixelHeight);
 
     let scale = Math.max(scaleWidth, scaleHeight);
 
-    let canvasWidth = Math.min(maxWidth, Math.round(content.innerWidth * scale));
-    let canvasHeight = Math.min(maxHeight, Math.round(content.innerHeight * scale));
+    let canvasWidth =
+      Math.min(maxPixelWidth, Math.round(contentPixelWidth * scale));
+    let canvasHeight =
+      Math.min(maxPixelHeight, Math.round(contentPixelHeight * scale));
 
     let transparent = (mimeType !== 'image/jpeg');
 
     var canvas = content.document
       .createElementNS("http://www.w3.org/1999/xhtml", "canvas");
     if (!transparent)
       canvas.mozOpaque = true;
     canvas.width = canvasWidth;
     canvas.height = canvasHeight;
 
     var ctx = canvas.getContext("2d", { willReadFrequently: true });
-    ctx.scale(scale, scale);
+    ctx.scale(scale * devicePixelRatio, scale * devicePixelRatio);
     ctx.drawWindow(content, 0, 0, content.innerWidth, content.innerHeight,
                    transparent ? "rgba(255,255,255,0)" : "rgb(255,255,255)");
 
     // Take a JPEG screenshot by default instead of PNG with alpha channel.
     // This requires us to unpremultiply the alpha channel, which
     // is expensive on ARM processors because they lack a hardware integer
     // division instruction.
     canvas.toBlob(function(blob) {
--- a/dom/browser-element/mochitest/Makefile.in
+++ b/dom/browser-element/mochitest/Makefile.in
@@ -36,17 +36,19 @@ MOCHITEST_FILES = \
 		browserElement_Iconchange.js \
 		browserElement_Metachange.js \
 		file_browserElement_Metachange.sjs \
 		browserElement_Opensearch.js \
 		test_browserElement_inproc_Iconchange.html \
 		test_browserElement_inproc_Metachange.html \
 		test_browserElement_inproc_Opensearch.html \
 		browserElement_GetScreenshot.js \
+		browserElement_GetScreenshotDppx.js \
 		test_browserElement_inproc_GetScreenshot.html \
+		test_browserElement_inproc_GetScreenshotDppx.html \
 		browserElement_BadScreenshot.js \
 		test_browserElement_inproc_BadScreenshot.html \
 		browserElement_SetVisible.js \
 		test_browserElement_inproc_SetVisible.html \
 		browserElement_SetVisibleFrames.js \
 		test_browserElement_inproc_SetVisibleFrames.html \
 		file_browserElement_SetVisibleFrames_Outer.html \
 		file_browserElement_SetVisibleFrames_Inner.html \
@@ -207,16 +209,17 @@ MOCHITEST_FILES += \
 		test_browserElement_oop_Titlechange.html \
 		test_browserElement_oop_AppWindowNamespace.html \
 		test_browserElement_oop_BrowserWindowNamespace.html \
 		test_browserElement_oop_TopBarrier.html \
 		test_browserElement_oop_Iconchange.html \
 		test_browserElement_oop_Metachange.html \
 		test_browserElement_oop_Opensearch.html \
 		test_browserElement_oop_GetScreenshot.html \
+		test_browserElement_oop_GetScreenshotDppx.html \
 		test_browserElement_oop_BadScreenshot.html \
 		test_browserElement_oop_XFrameOptions.html \
 		test_browserElement_oop_XFrameOptionsDeny.html \
 		test_browserElement_oop_XFrameOptionsSameOrigin.html \
 		test_browserElement_oop_XFrameOptionsAllowFrom.html \
 		test_browserElement_oop_SendEvent.html \
 		test_browserElement_oop_SetVisible.html \
 		test_browserElement_oop_SetVisibleFrames.html \
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/browserElement_GetScreenshotDppx.js
@@ -0,0 +1,108 @@
+/* Any copyright is dedicated to the public domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test the getScreenshot property for mozbrowser
+"use strict";
+
+SimpleTest.waitForExplicitFinish();
+browserElementTestHelpers.setEnabledPref(true);
+browserElementTestHelpers.addPermission();
+
+function runTest() {
+  var dppxPref = 'layout.css.devPixelsPerPx';
+  var cssPixelWidth = 600;
+  var cssPixelHeight = 400;
+
+  var iframe1 = document.createElement('iframe');
+  iframe1.setAttribute('width', cssPixelWidth);
+  iframe1.setAttribute('height', cssPixelHeight);
+  SpecialPowers.wrap(iframe1).mozbrowser = true;
+
+  iframe1.src = 'data:text/html,<html><body>hello</body></html>';
+  document.body.appendChild(iframe1);
+
+  var images = [];
+
+  function screenshotTaken(image) {
+    images.push(image);
+    if (images.length === 1) {
+      ok(true, 'Got initial non blank screenshot');
+
+      if (image.width !== cssPixelWidth || image.height !== cssPixelHeight) {
+        ok(false, 'The pixel width of the image received is not correct');
+        SimpleTest.finish();
+        return;
+      }
+      ok(true, 'The pixel width of the image received is correct');
+
+      SpecialPowers.pushPrefEnv(
+        {'set': [['layout.css.devPixelsPerPx', 2]]}, takeScreenshot);
+    }
+    else if (images.length === 2) {
+      ok(true, 'Got updated screenshot after source page changed');
+
+      if (image.width !== cssPixelWidth * 2 ||
+          image.height !== cssPixelHeight * 2) {
+        ok(false, 'The pixel width of the 2dppx image received is not correct');
+        SimpleTest.finish();
+        return;
+      }
+      ok(true, 'The pixel width of the 2dppx image received is correct');
+      SimpleTest.finish();
+    }
+  }
+
+  function takeScreenshot() {
+    function gotImage(e) {
+      // |this| is the Image.
+
+      URL.revokeObjectURL(this.src);
+
+      if (e.type === 'error' || !this.width || !this.height) {
+        tryAgain();
+
+        return;
+      }
+
+      screenshotTaken(this);
+    }
+
+    function tryAgain() {
+      if (--attempts === 0) {
+        ok(false, 'Timed out waiting for correct screenshot');
+        SimpleTest.finish();
+      } else {
+        setTimeout(function() {
+          iframe1.getScreenshot(cssPixelWidth, cssPixelHeight).onsuccess =
+            getScreenshotImageData;
+        }, 200);
+      }
+    }
+
+    function getScreenshotImageData(e) {
+      var blob = e.target.result;
+      if (blob.size === 0) {
+        tryAgain();
+
+        return;
+      }
+
+      var img = new Image();
+      img.src = URL.createObjectURL(blob);
+      img.onload = img.onerror = gotImage;
+    }
+
+    var attempts = 10;
+    iframe1.getScreenshot(cssPixelWidth, cssPixelHeight).onsuccess =
+      getScreenshotImageData;
+  }
+
+  function iframeLoadedHandler() {
+    SpecialPowers.pushPrefEnv(
+      {'set': [['layout.css.devPixelsPerPx', 1]]}, takeScreenshot);
+  }
+
+  iframe1.addEventListener('mozbrowserloadend', iframeLoadedHandler);
+}
+
+addEventListener('testready', runTest);
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/test_browserElement_inproc_GetScreenshotDppx.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=959066
+-->
+<head>
+  <title>Test for Bug 959066</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="browserElementTestHelpers.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=959066">Mozilla Bug 959066</a>
+
+<script type="application/javascript;version=1.7" src='browserElement_GetScreenshotDppx.js'>
+</script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/test_browserElement_oop_GetScreenshotDppx.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=959066
+-->
+<head>
+  <title>Test for Bug 959066</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="browserElementTestHelpers.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=959066">Mozilla Bug 959066</a>
+
+<script type="application/javascript;version=1.7" src='browserElement_GetScreenshotDppx.js'>
+</script>
+
+</body>
+</html>
--- a/dom/camera/CameraControlImpl.cpp
+++ b/dom/camera/CameraControlImpl.cpp
@@ -141,17 +141,17 @@ CameraControlImpl::Set(JSContext* aCx, u
 
 nsresult
 CameraControlImpl::Get(JSContext* aCx, uint32_t aKey, JS::Value* aValue)
 {
   nsTArray<CameraRegion> regionArray;
 
   GetParameter(aKey, regionArray);
 
-  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
+  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
   if (!array) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   uint32_t length = regionArray.Length();
   DOM_CAMERA_LOGI("%s:%d : got %d regions\n", __func__, __LINE__, length);
 
   for (uint32_t i = 0; i < length; ++i) {
--- a/dom/camera/DOMCameraCapabilities.cpp
+++ b/dom/camera/DOMCameraCapabilities.cpp
@@ -116,17 +116,17 @@ DOMCameraCapabilities::ParameterListToNe
 
   const char* value = mCamera->GetParameterConstChar(aKey);
   if (!value) {
     // in case we get nonsense data back
     aArray.set(nullptr);
     return NS_OK;
   }
 
-  aArray.set(JS_NewArrayObject(aCx, 0, nullptr));
+  aArray.set(JS_NewArrayObject(aCx, 0));
   if (!aArray) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   const char* p = value;
   uint32_t index = 0;
   nsresult rv;
   char* q;
@@ -373,17 +373,17 @@ DOMCameraCapabilities::GetVideoSizes(JSC
   nsresult rv = mCamera->GetVideoSizes(sizes);
   NS_ENSURE_SUCCESS(rv, rv);
   if (sizes.Length() == 0) {
     // video recording not supported, return null
     aVideoSizes.setNull();
     return NS_OK;
   }
 
-  JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, 0, nullptr));
+  JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, 0));
   if (!array) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   for (uint32_t i = 0; i < sizes.Length(); ++i) {
     JS::Rooted<JSObject*> o(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
     JS::Rooted<JS::Value> v(cx, INT_TO_JSVAL(sizes[i].width));
     if (!JS_SetProperty(cx, o, "width", v)) {
--- a/dom/events/TextComposition.cpp
+++ b/dom/events/TextComposition.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TextComposition.h"
 #include "nsContentEventHandler.h"
 #include "nsContentUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsIContent.h"
+#include "nsIEditor.h"
 #include "nsIMEStateManager.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "mozilla/MiscEvents.h"
 #include "mozilla/TextEvents.h"
 
 namespace mozilla {
 
@@ -22,17 +23,18 @@ namespace mozilla {
  ******************************************************************************/
 
 TextComposition::TextComposition(nsPresContext* aPresContext,
                                  nsINode* aNode,
                                  WidgetGUIEvent* aEvent) :
   mPresContext(aPresContext), mNode(aNode),
   mNativeContext(aEvent->widget->GetInputContext().mNativeIMEContext),
   mCompositionStartOffset(0), mCompositionTargetOffset(0),
-  mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests)
+  mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests),
+  mIsComposing(false)
 {
 }
 
 bool
 TextComposition::MatchesNativeContext(nsIWidget* aWidget) const
 {
   return mNativeContext == aWidget->GetInputContext().mNativeIMEContext;
 }
@@ -44,16 +46,30 @@ TextComposition::DispatchEvent(WidgetGUI
 {
   if (aEvent->message == NS_COMPOSITION_UPDATE) {
     mLastData = aEvent->AsCompositionEvent()->data;
   }
 
   nsEventDispatcher::Dispatch(mNode, mPresContext,
                               aEvent, nullptr, aStatus, aCallBack);
 
+  // Emulate editor behavior of text event handler if no editor handles
+  // composition/text events.
+  if (aEvent->message == NS_TEXT_TEXT && !HasEditor()) {
+    EditorWillHandleTextEvent(aEvent->AsTextEvent());
+    EditorDidHandleTextEvent();
+  }
+
+#ifdef DEBUG
+  else if (aEvent->message == NS_COMPOSITION_END) {
+    MOZ_ASSERT(!mIsComposing, "Why is the editor still composing?");
+    MOZ_ASSERT(!HasEditor(), "Why does the editor still keep to hold this?");
+  }
+#endif // #ifdef DEBUG
+
   // Notify composition update to widget if possible
   NotityUpdateComposition(aEvent);
 }
 
 void
 TextComposition::NotityUpdateComposition(WidgetGUIEvent* aEvent)
 {
   nsEventStatus status;
@@ -118,16 +134,63 @@ TextComposition::SynthesizeCommit(bool a
 
 nsresult
 TextComposition::NotifyIME(widget::NotificationToIME aNotification)
 {
   NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE);
   return nsIMEStateManager::NotifyIME(aNotification, mPresContext);
 }
 
+void
+TextComposition::EditorWillHandleTextEvent(const WidgetTextEvent* aTextEvent)
+{
+  mIsComposing = aTextEvent->IsComposing();
+
+  MOZ_ASSERT(mLastData == aTextEvent->theText,
+    "The text of a text event must be same as previous data attribute value "
+    "of the latest compositionupdate event");
+}
+
+void
+TextComposition::EditorDidHandleTextEvent()
+{
+  mString = mLastData;
+}
+
+void
+TextComposition::StartHandlingComposition(nsIEditor* aEditor)
+{
+  MOZ_ASSERT(!HasEditor(), "There is a handling editor already");
+  mEditorWeak = do_GetWeakReference(aEditor);
+}
+
+void
+TextComposition::EndHandlingComposition(nsIEditor* aEditor)
+{
+#ifdef DEBUG
+  nsCOMPtr<nsIEditor> editor = GetEditor();
+  MOZ_ASSERT(editor == aEditor, "Another editor handled the composition?");
+#endif // #ifdef DEBUG
+  mEditorWeak = nullptr;
+}
+
+already_AddRefed<nsIEditor>
+TextComposition::GetEditor() const
+{
+  nsCOMPtr<nsIEditor> editor = do_QueryReferent(mEditorWeak);
+  return editor.forget();
+}
+
+bool
+TextComposition::HasEditor() const
+{
+  nsCOMPtr<nsIEditor> editor = GetEditor();
+  return !!editor;
+}
+
 /******************************************************************************
  * TextComposition::CompositionEventDispatcher
  ******************************************************************************/
 
 TextComposition::CompositionEventDispatcher::CompositionEventDispatcher(
                                                nsPresContext* aPresContext,
                                                nsINode* aEventTarget,
                                                uint32_t aEventMessage,
--- a/dom/events/TextComposition.h
+++ b/dom/events/TextComposition.h
@@ -4,26 +4,27 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_TextComposition_h
 #define mozilla_TextComposition_h
 
 #include "nsCOMPtr.h"
 #include "nsINode.h"
+#include "nsIWeakReference.h"
 #include "nsIWidget.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 #include "nsPresContext.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/EventForwards.h"
 
 class nsDispatchingCallback;
+class nsIEditor;
 class nsIMEStateManager;
-class nsIWidget;
 
 namespace mozilla {
 
 /**
  * TextComposition represents a text composition.  This class stores the
  * composition event target and its presContext.  At dispatching the event via
  * this class, the instances use the stored event target.
  */
@@ -42,17 +43,24 @@ public:
   ~TextComposition()
   {
     // WARNING: mPresContext may be destroying, so, be careful if you touch it.
   }
 
   nsPresContext* GetPresContext() const { return mPresContext; }
   nsINode* GetEventTargetNode() const { return mNode; }
   // The latest CompositionEvent.data value except compositionstart event.
-  const nsString& GetLastData() const { return mLastData; }
+  // This value is modified at dispatching compositionupdate.
+  const nsString& LastData() const { return mLastData; }
+  // The composition string which is already handled by the focused editor.
+  // I.e., this value must be same as the composition string on the focused
+  // editor.  This value is modified at a call of EditorDidHandleTextEvent().
+  // Note that mString and mLastData are different between dispatcing
+  // compositionupdate and text event handled by focused editor.
+  const nsString& String() const { return mString; }
   // Returns true if the composition is started with synthesized event which
   // came from nsDOMWindowUtils.
   bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }
 
   bool MatchesNativeContext(nsIWidget* aWidget) const;
 
   /**
    * SynthesizeCommit() dispatches compositionupdate, text and compositionend
@@ -68,45 +76,116 @@ public:
    */
   nsresult NotifyIME(widget::NotificationToIME aNotification);
 
   /**
    * the offset of first selected clause or start of of compositon
    */
   uint32_t OffsetOfTargetClause() const { return mCompositionTargetOffset; }
 
+  /**
+   * Returns true if there is non-empty composition string and it's not fixed.
+   * Otherwise, false.
+   */
+  bool IsComposing() const { return mIsComposing; }
+
+  /**
+   * StartHandlingComposition() and EndHandlingComposition() are called by
+   * editor when it holds a TextComposition instance and release it.
+   */
+  void StartHandlingComposition(nsIEditor* aEditor);
+  void EndHandlingComposition(nsIEditor* aEditor);
+
+  /**
+   * TextEventHandlingMarker class should be created at starting to handle text
+   * event in focused editor.  This calls EditorWillHandleTextEvent() and
+   * EditorDidHandleTextEvent() automatically.
+   */
+  class MOZ_STACK_CLASS TextEventHandlingMarker
+  {
+  public:
+    TextEventHandlingMarker(TextComposition* aComposition,
+                            const WidgetTextEvent* aTextEvent)
+      : mComposition(aComposition)
+    {
+      mComposition->EditorWillHandleTextEvent(aTextEvent);
+    }
+
+    ~TextEventHandlingMarker()
+    {
+      mComposition->EditorDidHandleTextEvent();
+    }
+
+  private:
+    nsRefPtr<TextComposition> mComposition;
+    TextEventHandlingMarker();
+    TextEventHandlingMarker(const TextEventHandlingMarker& aOther);
+  };
+
 private:
   // This class holds nsPresContext weak.  This instance shouldn't block
   // destroying it.  When the presContext is being destroyed, it's notified to
   // nsIMEStateManager::OnDestroyPresContext(), and then, it destroy
   // this instance.
   nsPresContext* mPresContext;
   nsCOMPtr<nsINode> mNode;
 
   // mNativeContext stores a opaque pointer.  This works as the "ID" for this
   // composition.  Don't access the instance, it may not be available.
   void* mNativeContext;
 
+  // mEditorWeak is a weak reference to the focused editor handling composition.
+  nsWeakPtr mEditorWeak;
+
   // mLastData stores the data attribute of the latest composition event (except
   // the compositionstart event).
   nsString mLastData;
 
+  // mString stores the composition text which has been handled by the focused
+  // editor.
+  nsString mString;
+
   // Offset of the composition string from start of the editor
   uint32_t mCompositionStartOffset;
   // Offset of the selected clause of the composition string from start of the
   // editor
   uint32_t mCompositionTargetOffset;
 
   // See the comment for IsSynthesizedForTests().
   bool mIsSynthesizedForTests;
 
+  // See the comment for IsComposing().
+  bool mIsComposing;
+
   // Hide the default constructor and copy constructor.
   TextComposition() {}
   TextComposition(const TextComposition& aOther);
 
+  /**
+   * GetEditor() returns nsIEditor pointer of mEditorWeak.
+   */
+  already_AddRefed<nsIEditor> GetEditor() const;
+
+  /**
+   * HasEditor() returns true if mEditorWeak holds nsIEditor instance which is
+   * alive.  Otherwise, false.
+   */
+  bool HasEditor() const;
+
+  /**
+   * EditorWillHandleTextEvent() must be called before the focused editor
+   * handles the text event.
+   */
+  void EditorWillHandleTextEvent(const WidgetTextEvent* aTextEvent);
+
+  /**
+   * EditorDidHandleTextEvent() must be called after the focused editor handles
+   * a text event.
+   */
+  void EditorDidHandleTextEvent();
 
   /**
    * DispatchEvent() dispatches the aEvent to the mContent synchronously.
    * The caller must ensure that it's safe to dispatch the event.
    */
   void DispatchEvent(WidgetGUIEvent* aEvent,
                      nsEventStatus* aStatus,
                      nsDispatchingCallback* aCallBack);
--- a/dom/events/nsIMEStateManager.cpp
+++ b/dom/events/nsIMEStateManager.cpp
@@ -612,59 +612,59 @@ nsIMEStateManager::NotifyIME(Notificatio
 
   // If the composition is synthesized events for automated tests, we should
   // dispatch composition events for emulating the native composition behavior.
   // NOTE: The dispatched events are discarded if it's not safe to run script.
   switch (aNotification) {
     case REQUEST_TO_COMMIT_COMPOSITION: {
       nsCOMPtr<nsIWidget> widget(aWidget);
       nsEventStatus status = nsEventStatus_eIgnore;
-      if (!composition->GetLastData().IsEmpty()) {
+      if (!composition->LastData().IsEmpty()) {
         WidgetTextEvent textEvent(true, NS_TEXT_TEXT, widget);
-        textEvent.theText = composition->GetLastData();
+        textEvent.theText = composition->LastData();
         textEvent.mFlags.mIsSynthesizedForTests = true;
         widget->DispatchEvent(&textEvent, status);
         if (widget->Destroyed()) {
           return NS_OK;
         }
       }
 
       status = nsEventStatus_eIgnore;
       WidgetCompositionEvent endEvent(true, NS_COMPOSITION_END, widget);
-      endEvent.data = composition->GetLastData();
+      endEvent.data = composition->LastData();
       endEvent.mFlags.mIsSynthesizedForTests = true;
       widget->DispatchEvent(&endEvent, status);
 
       return NS_OK;
     }
     case REQUEST_TO_CANCEL_COMPOSITION: {
       nsCOMPtr<nsIWidget> widget(aWidget);
       nsEventStatus status = nsEventStatus_eIgnore;
-      if (!composition->GetLastData().IsEmpty()) {
+      if (!composition->LastData().IsEmpty()) {
         WidgetCompositionEvent updateEvent(true, NS_COMPOSITION_UPDATE, widget);
-        updateEvent.data = composition->GetLastData();
+        updateEvent.data = composition->LastData();
         updateEvent.mFlags.mIsSynthesizedForTests = true;
         widget->DispatchEvent(&updateEvent, status);
         if (widget->Destroyed()) {
           return NS_OK;
         }
 
         status = nsEventStatus_eIgnore;
         WidgetTextEvent textEvent(true, NS_TEXT_TEXT, widget);
-        textEvent.theText = composition->GetLastData();
+        textEvent.theText = composition->LastData();
         textEvent.mFlags.mIsSynthesizedForTests = true;
         widget->DispatchEvent(&textEvent, status);
         if (widget->Destroyed()) {
           return NS_OK;
         }
       }
 
       status = nsEventStatus_eIgnore;
       WidgetCompositionEvent endEvent(true, NS_COMPOSITION_END, widget);
-      endEvent.data = composition->GetLastData();
+      endEvent.data = composition->LastData();
       endEvent.mFlags.mIsSynthesizedForTests = true;
       widget->DispatchEvent(&endEvent, status);
 
       return NS_OK;
     }
     default:
       return NS_OK;
   }
@@ -1121,14 +1121,28 @@ nsIMEStateManager::GetFocusSelectionAndR
 
   NS_ASSERTION(sTextStateObserver->mSel && sTextStateObserver->mRootContent,
                "uninitialized text state observer");
   NS_ADDREF(*aSel = sTextStateObserver->mSel);
   NS_ADDREF(*aRoot = sTextStateObserver->mRootContent);
   return NS_OK;
 }
 
-TextComposition*
+// static
+already_AddRefed<TextComposition>
 nsIMEStateManager::GetTextCompositionFor(nsIWidget* aWidget)
 {
-  return sTextCompositions ?
-    sTextCompositions->GetCompositionFor(aWidget) : nullptr;
+  if (!sTextCompositions) {
+    return nullptr;
+  }
+  nsRefPtr<TextComposition> textComposition =
+    sTextCompositions->GetCompositionFor(aWidget);
+  return textComposition.forget();
 }
+
+// static
+already_AddRefed<TextComposition>
+nsIMEStateManager::GetTextCompositionFor(WidgetGUIEvent* aEvent)
+{
+  MOZ_ASSERT(aEvent->AsCompositionEvent() || aEvent->AsTextEvent(),
+             "aEvent has to be WidgetCompositionEvent or WidgetTextEvent");
+  return GetTextCompositionFor(aEvent->widget);
+}
--- a/dom/events/nsIMEStateManager.h
+++ b/dom/events/nsIMEStateManager.h
@@ -93,17 +93,27 @@ public:
                                        nsPresContext* aPresContext,
                                        mozilla::WidgetEvent* aEvent,
                                        nsEventStatus* aStatus,
                                        nsDispatchingCallback* aCallBack);
 
   /**
    * Get TextComposition from widget.
    */
-  static mozilla::TextComposition* GetTextCompositionFor(nsIWidget* aWidget);
+  static already_AddRefed<mozilla::TextComposition>
+    GetTextCompositionFor(nsIWidget* aWidget);
+
+  /**
+   * Returns TextComposition instance for the event.
+   *
+   * @param aEvent      Should be a composition event or a text event which is
+   *                    being dispatched.
+   */
+  static already_AddRefed<mozilla::TextComposition>
+    GetTextCompositionFor(mozilla::WidgetGUIEvent* aEvent);
 
   /**
    * Send a notification to IME.  It depends on the IME or platform spec what
    * will occur (or not occur).
    */
   static nsresult NotifyIME(mozilla::widget::NotificationToIME aNotification,
                             nsIWidget* aWidget);
   static nsresult NotifyIME(mozilla::widget::NotificationToIME aNotification,
--- a/dom/file/ArchiveRequest.cpp
+++ b/dom/file/ArchiveRequest.cpp
@@ -169,17 +169,17 @@ ArchiveRequest::ReaderReady(nsTArray<nsC
   return NS_OK;
 }
 
 nsresult
 ArchiveRequest::GetFilenamesResult(JSContext* aCx,
                                    JS::Value* aValue,
                                    nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList)
 {
-  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aFileList.Length(), nullptr));
+  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aFileList.Length()));
   nsresult rv;
 
   if (!array) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   JS::Rooted<JSString*> str(aCx);
   for (uint32_t i = 0; i < aFileList.Length(); ++i) {
@@ -227,17 +227,17 @@ ArchiveRequest::GetFileResult(JSContext*
   return NS_ERROR_FAILURE;
 }
 
 nsresult
 ArchiveRequest::GetFilesResult(JSContext* aCx,
                                JS::MutableHandle<JS::Value> aValue,
                                nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList)
 {
-  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aFileList.Length(), nullptr));
+  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aFileList.Length()));
   if (!array) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   for (uint32_t i = 0; i < aFileList.Length(); ++i) {
     nsCOMPtr<nsIDOMFile> file = aFileList[i];
 
     JS::Rooted<JS::Value> value(aCx);
--- a/dom/indexedDB/AsyncConnectionHelper.cpp
+++ b/dom/indexedDB/AsyncConnectionHelper.cpp
@@ -53,17 +53,17 @@ private:
 // something fails.
 inline
 nsresult
 ConvertCloneReadInfosToArrayInternal(
                                 JSContext* aCx,
                                 nsTArray<StructuredCloneReadInfo>& aReadInfos,
                                 JS::MutableHandle<JS::Value> aResult)
 {
-  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
+  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
   if (!array) {
     IDB_WARNING("Failed to make array!");
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   if (!aReadInfos.IsEmpty()) {
     if (!JS_SetArrayLength(aCx, array, uint32_t(aReadInfos.Length()))) {
       IDB_WARNING("Failed to set array length!");
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -1442,17 +1442,17 @@ GetAllKeysHelper::GetSuccessResult(JSCon
 
   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
                              "GetAllKeysHelper::GetSuccessResult "
                              "[IDBIndex.cpp]");
 
   nsTArray<Key> keys;
   mKeys.SwapElements(keys);
 
-  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
+  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
   if (!array) {
     IDB_WARNING("Failed to make array!");
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   if (!keys.IsEmpty()) {
     if (!JS_SetArrayLength(aCx, array, uint32_t(keys.Length()))) {
       IDB_WARNING("Failed to set array length!");
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -4926,17 +4926,17 @@ GetAllKeysHelper::GetSuccessResult(JSCon
 
   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
                              "GetAllKeysHelper::GetSuccessResult "
                              "[IDBObjectStore.cpp]");
 
   nsTArray<Key> keys;
   mKeys.SwapElements(keys);
 
-  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
+  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
   if (!array) {
     IDB_WARNING("Failed to make array!");
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   if (!keys.IsEmpty()) {
     if (!JS_SetArrayLength(aCx, array, keys.Length())) {
       IDB_WARNING("Failed to set array length!");
--- a/dom/indexedDB/Key.cpp
+++ b/dom/indexedDB/Key.cpp
@@ -186,17 +186,17 @@ Key::EncodeJSValInternal(JSContext* aCx,
 nsresult
 Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
                          JSContext* aCx, uint8_t aTypeOffset, JS::MutableHandle<JS::Value> aVal,
                          uint16_t aRecursionDepth)
 {
   NS_ENSURE_TRUE(aRecursionDepth < MaxRecursionDepth, NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
 
   if (*aPos - aTypeOffset >= eArray) {
-    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
+    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
     if (!array) {
       NS_WARNING("Failed to make array!");
       IDB_REPORT_INTERNAL_ERR();
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     aTypeOffset += eMaxType;
 
--- a/dom/indexedDB/KeyPath.cpp
+++ b/dom/indexedDB/KeyPath.cpp
@@ -384,17 +384,17 @@ KeyPath::ExtractKeyAsJSVal(JSContext* aC
   NS_ASSERTION(IsValid(), "This doesn't make sense!");
 
   if (IsString()) {
     return GetJSValFromKeyPathString(aCx, aValue, mStrings[0], aOutVal,
                                      DoNotCreateProperties, nullptr, nullptr);
   }
 
   const uint32_t len = mStrings.Length();
-  JS::Rooted<JSObject*> arrayObj(aCx, JS_NewArrayObject(aCx, len, nullptr));
+  JS::Rooted<JSObject*> arrayObj(aCx, JS_NewArrayObject(aCx, len));
   if (!arrayObj) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   JS::Rooted<JS::Value> value(aCx);
   for (uint32_t i = 0; i < len; ++i) {
     nsresult rv = GetJSValFromKeyPathString(aCx, aValue, mStrings[i],
                                             value.address(),
@@ -496,17 +496,17 @@ KeyPath::DeserializeFromString(const nsA
   return keyPath;
 }
 
 nsresult
 KeyPath::ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aValue) const
 {
   if (IsArray()) {
     uint32_t len = mStrings.Length();
-    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, len, nullptr));
+    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, len));
     if (!array) {
       IDB_WARNING("Failed to make array!");
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     for (uint32_t i = 0; i < len; ++i) {
       JS::Rooted<JS::Value> val(aCx);
       nsString tmp(mStrings[i]);
--- a/dom/mobilemessage/src/MmsMessage.cpp
+++ b/dom/mobilemessage/src/MmsMessage.cpp
@@ -478,17 +478,17 @@ MmsMessage::GetDeliveryInfo(JSContext* a
   // also make .deliveryInfo = null, since the .deliveryInfo is useless.
   uint32_t length = mDeliveryInfo.Length();
   if (length == 0) {
     aDeliveryInfo.setNull();
     return NS_OK;
   }
 
   JS::Rooted<JSObject*> deliveryInfo(
-    aCx, JS_NewArrayObject(aCx, length, nullptr));
+    aCx, JS_NewArrayObject(aCx, length));
   NS_ENSURE_TRUE(deliveryInfo, NS_ERROR_OUT_OF_MEMORY);
 
   for (uint32_t i = 0; i < length; ++i) {
     const MmsDeliveryInfo &info = mDeliveryInfo[i];
 
     JS::Rooted<JSObject*> infoJsObj(
       aCx, JS_NewObject(aCx, nullptr, JS::NullPtr(), JS::NullPtr()));
     NS_ENSURE_TRUE(infoJsObj, NS_ERROR_OUT_OF_MEMORY);
@@ -609,17 +609,17 @@ MmsMessage::GetSmil(nsAString& aSmil)
 }
 
 NS_IMETHODIMP
 MmsMessage::GetAttachments(JSContext* aCx, JS::MutableHandle<JS::Value> aAttachments)
 {
   uint32_t length = mAttachments.Length();
 
   JS::Rooted<JSObject*> attachments(
-    aCx, JS_NewArrayObject(aCx, length, nullptr));
+    aCx, JS_NewArrayObject(aCx, length));
   NS_ENSURE_TRUE(attachments, NS_ERROR_OUT_OF_MEMORY);
 
   for (uint32_t i = 0; i < length; ++i) {
     const MmsAttachment &attachment = mAttachments[i];
 
     JS::Rooted<JSObject*> attachmentObj(
       aCx, JS_NewObject(aCx, nullptr, JS::NullPtr(), JS::NullPtr()));
     NS_ENSURE_TRUE(attachmentObj, NS_ERROR_OUT_OF_MEMORY);
--- a/dom/mobilemessage/src/MobileMessageCallback.cpp
+++ b/dom/mobilemessage/src/MobileMessageCallback.cpp
@@ -162,17 +162,17 @@ MobileMessageCallback::NotifyMessageDele
   nsIScriptContext* sc = mDOMRequest->GetContextForEventHandlers(&rv);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(sc, NS_ERROR_FAILURE);
 
   AutoPushJSContext cx(sc->GetNativeContext());
   NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
 
   JS::Rooted<JSObject*> deleteArrayObj(cx,
-                                       JS_NewArrayObject(cx, aSize, nullptr));
+                                       JS_NewArrayObject(cx, aSize));
   for (uint32_t i = 0; i < aSize; i++) {
     JS_SetElement(cx, deleteArrayObj, i, aDeleted[i]);
   }
 
   JS::Rooted<JS::Value> deleteArrayVal(cx, JS::ObjectValue(*deleteArrayObj));
   return NotifySuccess(deleteArrayVal);
 }
 
--- a/dom/mobilemessage/src/MobileMessageManager.cpp
+++ b/dom/mobilemessage/src/MobileMessageManager.cpp
@@ -236,17 +236,17 @@ MobileMessageManager::Send(JS::Handle<JS
       return NS_ERROR_FAILURE;
     }
 
     nsresult rv = Send(aCx, global, serviceId, str, aMessage, &requests[i]);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   JS::Rooted<JSObject*> obj(aCx);
-  obj = JS_NewArrayObject(aCx, requests.length(), requests.begin());
+  obj = JS_NewArrayObject(aCx, requests);
   if (!obj) {
     return NS_ERROR_FAILURE;
   }
 
   aReturn.setObject(*obj);
   return NS_OK;
 }
 
--- a/dom/mobilemessage/src/SmsFilter.cpp
+++ b/dom/mobilemessage/src/SmsFilter.cpp
@@ -140,17 +140,17 @@ SmsFilter::GetNumbers(JSContext* aCx, JS
                                         mData.numbers()[i].Length());
     if (!str) {
       return NS_ERROR_FAILURE;
     }
 
     numbers[i].setString(str);
   }
 
-  JSObject* obj = JS_NewArrayObject(aCx, numbers.length(), numbers.begin());
+  JSObject* obj = JS_NewArrayObject(aCx, numbers);
   if (!obj) {
     return NS_ERROR_FAILURE;
   }
 
   aNumbers.setObject(*obj);
   return NS_OK;
 }
 
--- a/dom/mobilemessage/src/ipc/SmsParent.cpp
+++ b/dom/mobilemessage/src/ipc/SmsParent.cpp
@@ -110,18 +110,17 @@ GetParamsFromSendMmsMessageRequest(JSCon
   }
   if (!JS_DefineProperty(aCx, paramsObj, "receivers",
                          JS::ObjectValue(*receiverArray), nullptr, nullptr, 0)) {
     return false;
   }
 
   // attachments
   JS::Rooted<JSObject*> attachmentArray(aCx, JS_NewArrayObject(aCx,
-                                                               aRequest.attachments().Length(),
-                                                               nullptr));
+                                                               aRequest.attachments().Length()));
   for (uint32_t i = 0; i < aRequest.attachments().Length(); i++) {
     JS::Rooted<JSObject*> obj(aCx,
       MmsAttachmentDataToJSObject(aCx, aRequest.attachments().ElementAt(i)));
     NS_ENSURE_TRUE(obj, false);
     if (!JS_SetElement(aCx, attachmentArray, i, obj)) {
       return false;
     }
   }
--- a/dom/network/src/NetworkStatsDB.jsm
+++ b/dom/network/src/NetworkStatsDB.jsm
@@ -571,17 +571,17 @@ NetworkStatsDB.prototype = {
           lastSample.txBytes = 0;
           self._saveStats(aTxn, aStore, lastSample);
         }
       };
     };
   },
 
   clearInterfaceStats: function clearInterfaceStats(aNetwork, aResultCb) {
-    let network = [aNetwork.id, aNetwork.type];
+    let network = [aNetwork.network.id, aNetwork.network.type];
     let self = this;
 
     // Clear and save an empty sample to keep sync with system counters
     this.dbNewTxn(STATS_STORE_NAME, "readwrite", function(aTxn, aStore) {
       let sample = null;
       let request = aStore.index("network").openCursor(network, "prev");
       request.onsuccess = function onsuccess(event) {
         let cursor = event.target.result;
@@ -604,17 +604,17 @@ NetworkStatsDB.prototype = {
           sample.rxBytes = 0;
           sample.txBytes = 0;
           sample.rxTotalBytes = 0;
           sample.txTotalBytes = 0;
 
           self._saveStats(aTxn, aStore, sample);
         }
       };
-    }, aResultCb);
+    }, this._resetAlarms.bind(this, aNetwork.networkId, aResultCb));
   },
 
   clearStats: function clearStats(aNetworks, aResultCb) {
     let index = 0;
     let stats = [];
     let self = this;
 
     let callback = function(aError, aResult) {
@@ -858,31 +858,33 @@ NetworkStatsDB.prototype = {
       };
     }, aResultCb);
   },
 
   alarmToRecord: function alarmToRecord(aAlarm) {
     let record = { networkId: aAlarm.networkId,
                    absoluteThreshold: aAlarm.absoluteThreshold,
                    relativeThreshold: aAlarm.relativeThreshold,
+                   startTime: aAlarm.startTime,
                    data: aAlarm.data,
                    manifestURL: aAlarm.manifestURL,
                    pageURL: aAlarm.pageURL };
 
     if (aAlarm.id) {
       record.id = aAlarm.id;
     }
 
     return record;
   },
 
   recordToAlarm: function recordToalarm(aRecord) {
     let alarm = { networkId: aRecord.networkId,
                   absoluteThreshold: aRecord.absoluteThreshold,
                   relativeThreshold: aRecord.relativeThreshold,
+                  startTime: aRecord.startTime,
                   data: aRecord.data,
                   manifestURL: aRecord.manifestURL,
                   pageURL: aRecord.pageURL };
 
     if (aRecord.id) {
       alarm.id = aRecord.id;
     }
 
@@ -999,10 +1001,34 @@ NetworkStatsDB.prototype = {
 
         if (!aNetworkId || cursor.value.networkId == aNetworkId) {
           txn.result.push(self.recordToAlarm(cursor.value));
         }
 
         cursor.continue();
       }
     }, aResultCb);
+  },
+
+  _resetAlarms: function _resetAlarms(aNetworkId, aResultCb) {
+    this.dbNewTxn(ALARMS_STORE_NAME, "readwrite", function(txn, store) {
+      if (DEBUG) {
+        debug("Reset alarms for network " + aNetworkId);
+      }
+
+      let lowerFilter = [aNetworkId, 0];
+      let upperFilter = [aNetworkId, ""];
+      let range = IDBKeyRange.bound(lowerFilter, upperFilter);
+
+      store.index("alarm").openCursor(range).onsuccess = function onsuccess(event) {
+        let cursor = event.target.result;
+        if (cursor) {
+          if (cursor.value.startTime) {
+            cursor.value.relativeThreshold = cursor.value.threshold;
+            cursor.update(cursor.value);
+          }
+          cursor.continue();
+          return;
+        }
+      };
+    }, aResultCb);
   }
 };
--- a/dom/network/src/NetworkStatsService.jsm
+++ b/dom/network/src/NetworkStatsService.jsm
@@ -460,34 +460,43 @@ this.NetworkStatsService = {
 
     this.validateNetwork(network, function onValidateNetwork(aNetId) {
       if (!aNetId) {
         mm.sendAsyncMessage("NetworkStats:Clear:Return",
                             { id: msg.id, error: "Invalid connectionType", result: null });
         return;
       }
 
+      network = {network: network, networkId: aNetId};
       self._db.clearInterfaceStats(network, function onDBCleared(aError, aResult) {
+          self._updateCurrentAlarm(aNetId);
           mm.sendAsyncMessage("NetworkStats:Clear:Return",
                               { id: msg.id, error: aError, result: aResult });
       });
     });
   },
 
   clearDB: function clearDB(mm, msg) {
     let self = this;
     this._db.getAvailableNetworks(function onGetNetworks(aError, aResult) {
       if (aError) {
         mm.sendAsyncMessage("NetworkStats:ClearAll:Return",
                             { id: msg.id, error: aError, result: aResult });
         return;
       }
 
       let networks = aResult;
+      networks.forEach(function(network, index) {
+        networks[index] = {network: network, networkId: self.getNetworkId(network.id, network.type)};
+      }, self);
+
       self._db.clearStats(networks, function onDBCleared(aError, aResult) {
+        networks.forEach(function(network, index) {
+          self._updateCurrentAlarm(network.networkId);
+        }, self);
         mm.sendAsyncMessage("NetworkStats:ClearAll:Return",
                             { id: msg.id, error: aError, result: aResult });
       });
     });
   },
 
   updateAllStats: function updateAllStats(aCallback) {
     // Update |cachedStats|.
--- a/dom/network/tests/unit_stats/test_networkstats_db.js
+++ b/dom/network/tests/unit_stats/test_networkstats_db.js
@@ -14,16 +14,20 @@ function clearStore(store, callback) {
       if (cursor){
         cursor.delete();
         cursor.continue();
       }
     };
   }, callback);
 }
 
+function getNetworkId(aIccId, aNetworkType) {
+  return aIccId + '' + aNetworkType;
+}
+
 add_test(function prepareDatabase() {
   // Clear whole database to avoid starting tests with unknown state
   // due to the previous tests.
   clearStore('net_stats_store', function() {
     clearStore('net_alarm', function() {
       run_next_test();
     });
   });
@@ -116,24 +120,32 @@ add_test(function test_fillResultSamples
   }
   do_check_true(success);
 
   run_next_test();
 });
 
 add_test(function test_clear() {
   var networks = getNetworks();
+  networks.forEach(function(network, index) {
+    networks[index] = {network: network, networkId: getNetworkId(network.id, network.type)};
+  }, this);
+
   netStatsDb.clearStats(networks, function (error, result) {
     do_check_eq(error, null);
     run_next_test();
   });
 });
 
 add_test(function test_clear_interface() {
   var networks = getNetworks();
+  networks.forEach(function(network, index) {
+    networks[index] = {network: network, networkId: getNetworkId(network.id, network.type)};
+  }, this);
+
   netStatsDb.clearInterfaceStats(networks[0], function (error, result) {
     do_check_eq(error, null);
     run_next_test();
   });
 });
 
 add_test(function test_internalSaveStats_singleSample() {
   var networks = getNetworks();
--- a/dom/network/tests/unit_stats/test_networkstats_service.js
+++ b/dom/network/tests/unit_stats/test_networkstats_service.js
@@ -14,18 +14,22 @@ function getNetworks(callback) {
     callback(aError, aResult);
   });
 }
 
 add_test(function test_clearDB() {
   getNetworks(function onGetNetworks(error, result) {
     do_check_eq(error, null);
     var networks = result;
+    networks.forEach(function(network, index) {
+      networks[index] = {network: network, networkId: NetworkStatsService.getNetworkId(network.id, network.type)};
+    }, this);
+
     NetworkStatsService._db.clearStats(networks, function onDBCleared(error, result) {
-      do_check_eq(result, null);
+      do_check_eq(error, null);
       run_next_test();
     });
   });
 });
 
 function getNetworkId(callback) {
   getNetworks(function onGetNetworks(error, result) {
     do_check_eq(error, null);
--- a/dom/nfc/moz.build
+++ b/dom/nfc/moz.build
@@ -12,11 +12,13 @@ if CONFIG['MOZ_NFC']:
     SOURCES += [
         'MozNDEFRecord.cpp',
     ]
     EXTRA_COMPONENTS += [
       'nsNfc.js',
       'nsNfc.manifest',
     ]
 
+TEST_DIRS += ['tests']
+
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'gklayout'
new file mode 100644
--- /dev/null
+++ b/dom/nfc/tests/marionette/head.js
@@ -0,0 +1,64 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let pendingEmulatorCmdCount = 0;
+
+function toggleNFC(enabled, callback) {
+  isnot(callback, null);
+  var settings = window.navigator.mozSettings;
+  isnot(settings, null);
+  ok(settings instanceof SettingsManager,
+     'settings instanceof ' + settings.constructor +
+     ', expected SettingsManager');
+
+  let req = settings.createLock().get('nfc.enabled');
+  req.onsuccess = function() {
+    if (req.result['nfc.enabled'] === enabled) {
+      callback();
+    } else {
+      let req = settings.createLock().set({'nfc.enabled': enabled});
+      req.onsuccess = function() {
+        window.setTimeout(callback, 5000); // give emulator time to toggle NFC
+      };
+      req.onerror = function() {
+        ok(false,
+           'Setting \'nfc.enabled\' to \'' + enabled +
+           '\' failed, error ' + req.error.name);
+        finish();
+      };
+    }
+  };
+  req.onerror = function() {
+    ok(false, 'Getting \'nfc.enabled\' failed, error ' + req.error.name);
+    finish();
+  };
+}
+
+function cleanUp() {
+  log('Cleaning up');
+  waitFor(finish(),
+          function() {
+            return pendingEmulatorCmdCount === 0;
+          });
+}
+
+function runNextTest() {
+  let test = tests.shift();
+  if (!test) {
+    cleanUp();
+    return;
+  }
+  test();
+}
+
+// run this function to start tests
+function runTests() {
+  if ('mozNfc' in window.navigator) {
+    runNextTest();
+  } else {
+    // succeed immediately on systems without NFC
+    log('Skipping test on system without NFC');
+    ok(true, 'Skipping test on system without NFC');
+    finish();
+  }
+}
new file mode 100644
--- /dev/null
+++ b/dom/nfc/tests/marionette/manifest.ini
@@ -0,0 +1,7 @@
+[DEFAULT]
+b2g=true
+browser=false
+qemu=true
+
+[test_nfc_enabled.js]
+[test_nfc_manager_tech_discovered.js]
new file mode 100644
--- /dev/null
+++ b/dom/nfc/tests/marionette/test_nfc_enabled.js
@@ -0,0 +1,23 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 30000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+function testEnableNFC() {
+  log('Running \'testEnableNFC\'');
+  toggleNFC(true, runNextTest);
+}
+
+function testDisableNFC() {
+  log('Running \'testDisableNFC\'');
+  toggleNFC(false, runNextTest);
+}
+
+let tests = [
+  testEnableNFC,
+  testDisableNFC
+];
+
+SpecialPowers.pushPermissions(
+  [{'type': 'settings', 'allow': true, 'context': document}], runTests);
new file mode 100644
--- /dev/null
+++ b/dom/nfc/tests/marionette/test_nfc_manager_tech_discovered.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 30000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+function handleTechnologyDiscoveredRE0(msg) {
+  log('Received \'nfc-manager-tech-discovered\'');
+  is(msg.type, 'techDiscovered', 'check for correct message type');
+  is(msg.techList[0], 'P2P', 'check for correct tech type');
+  toggleNFC(false, runNextTest);
+}
+
+function activateRE0() {
+  var cmd = 'nfc ntf rf_intf_activated 0';
+  log('Executing \'' + cmd + '\'');
+  ++pendingEmulatorCmdCount;
+  runEmulatorCmd(cmd, function(result) {
+    --pendingEmulatorCmdCount;
+    is(result.pop(), 'OK', 'check activation of RE0');
+  });
+}
+
+function testActivateRE0() {
+  log('Running \'testActivateRE0\'');
+  window.navigator.mozSetMessageHandler(
+    'nfc-manager-tech-discovered', handleTechnologyDiscoveredRE0);
+  toggleNFC(true, activateRE0);
+}
+
+let tests = [
+  testActivateRE0
+];
+
+SpecialPowers.pushPermissions(
+  [{'type': 'nfc-manager', 'allow': true, context: document},
+   {'type': 'settings', 'allow': true, context: document}], runTests);
new file mode 100644
--- /dev/null
+++ b/dom/nfc/tests/moz.build
@@ -0,0 +1,5 @@
+# -*- 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/.
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -603,17 +603,17 @@ public:
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CountdownHolder)
 
   CountdownHolder(const GlobalObject& aGlobal, Promise* aPromise, uint32_t aCountdown)
     : mPromise(aPromise), mCountdown(aCountdown)
   {
     MOZ_ASSERT(aCountdown != 0);
     JSContext* cx = aGlobal.GetContext();
     JSAutoCompartment ac(cx, aGlobal.Get());
-    mValues = JS_NewArrayObject(cx, aCountdown, nullptr);
+    mValues = JS_NewArrayObject(cx, aCountdown);
     mozilla::HoldJSObjects(this);
   }
 
   ~CountdownHolder()
   {
     mozilla::DropJSObjects(this);
   }
 
@@ -726,17 +726,17 @@ Promise::All(const GlobalObject& aGlobal
     window = do_QueryInterface(aGlobal.GetAsSupports());
     if (!window) {
       aRv.Throw(NS_ERROR_UNEXPECTED);
       return nullptr;
     }
   }
 
   if (aIterable.Length() == 0) {
-    JS::Rooted<JSObject*> empty(aCx, JS_NewArrayObject(aCx, 0, nullptr));
+    JS::Rooted<JSObject*> empty(aCx, JS_NewArrayObject(aCx, 0));
     if (!empty) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return nullptr;
     }
     Optional<JS::Handle<JS::Value>> optValue(aCx, JS::ObjectValue(*empty));
     return Promise::Resolve(aGlobal, aCx, optValue, aRv);
   }
 
--- a/dom/src/notification/Notification.cpp
+++ b/dom/src/notification/Notification.cpp
@@ -43,17 +43,17 @@ public:
       mGlobal(aGlobal.Get()),
       mWindow(aWindow),
       mPromise(aPromise)
   {
     MOZ_ASSERT(aWindow);
     MOZ_ASSERT(aPromise);
     JSContext* cx = aGlobal.GetContext();
     JSAutoCompartment ac(cx, mGlobal);
-    mNotifications = JS_NewArrayObject(cx, 0, nullptr);
+    mNotifications = JS_NewArrayObject(cx, 0);
     HoldData();
   }
 
   NS_IMETHOD Handle(const nsAString& aID,
                     const nsAString& aTitle,
                     const nsAString& aDir,
                     const nsAString& aLang,
                     const nsAString& aBody,
--- a/dom/workers/Console.cpp
+++ b/dom/workers/Console.cpp
@@ -287,17 +287,17 @@ private:
     JS::Rooted<JS::Value> argumentsValue(cx);
     if (!mArguments.read(cx, &argumentsValue, &gConsoleCallbacks, &mStrings)) {
       return;
     }
 
     JS::Rooted<JS::Value> stackValue(cx);
     {
       JS::Rooted<JSObject*> stackObj(cx,
-        JS_NewArrayObject(cx, mStackData.Length(), nullptr));
+        JS_NewArrayObject(cx, mStackData.Length()));
       if (!stackObj) {
         return;
       }
 
       for (uint32_t i = 0; i < mStackData.Length(); ++i) {
         WorkerConsoleStack stack;
 
         CopyUTF8toUTF16(mStackData[i].mFilename, stack.mFilename);
@@ -442,18 +442,17 @@ WorkerConsole::Method(JSContext* aCx, co
     nsCOMPtr<nsIStackFrame> caller;
     if (NS_FAILED(stack->GetCaller(getter_AddRefs(caller)))) {
       return;
     }
 
     stack.swap(caller);
   }
 
-  JS::Rooted<JSObject*> arguments(aCx,
-    JS_NewArrayObject(aCx, aData.Length(), nullptr));
+  JS::Rooted<JSObject*> arguments(aCx, JS_NewArrayObject(aCx, aData.Length()));
   if (!arguments) {
     return;
   }
 
   for (uint32_t i = 0; i < aData.Length(); ++i) {
     if (!JS_DefineElement(aCx, arguments, i, aData[i], nullptr, nullptr,
                           JSPROP_ENUMERATE)) {
       return;
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -2702,19 +2702,25 @@ WorkerPrivateParent<Derived>::PostMessag
     else {
       callbacks = &gMainThreadWorkerStructuredCloneCallbacks;
     }
   }
 
   JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
   if (aTransferable.WasPassed()) {
     const Sequence<JS::Value>& realTransferable = aTransferable.Value();
+
+    // The input sequence only comes from the generated bindings code, which
+    // ensures it is rooted.
+    JS::HandleValueArray elements =
+      JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(),
+                                               realTransferable.Elements());
+
     JSObject* array =
-      JS_NewArrayObject(aCx, realTransferable.Length(),
-                        const_cast<JS::Value*>(realTransferable.Elements()));
+      JS_NewArrayObject(aCx, elements);
     if (!array) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     transferable.setObject(*array);
   }
 
   nsTArray<nsCOMPtr<nsISupports> > clonedObjects;
@@ -4918,19 +4924,24 @@ WorkerPrivate::PostMessageToParentIntern
                             uint64_t aMessagePortSerial,
                             ErrorResult& aRv)
 {
   AssertIsOnWorkerThread();
 
   JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
   if (aTransferable.WasPassed()) {
     const Sequence<JS::Value>& realTransferable = aTransferable.Value();
-    JSObject* array =
-      JS_NewArrayObject(aCx, realTransferable.Length(),
-                        const_cast<jsval*>(realTransferable.Elements()));
+
+    // The input sequence only comes from the generated bindings code, which
+    // ensures it is rooted.
+    JS::HandleValueArray elements =
+      JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(),
+                                               realTransferable.Elements());
+
+    JSObject* array = JS_NewArrayObject(aCx, elements);
     if (!array) {
       aRv = NS_ERROR_OUT_OF_MEMORY;
       return;
     }
     transferable.setObject(*array);
   }
 
   JSStructuredCloneCallbacks* callbacks =
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -16,16 +16,17 @@
 #include "EditAggregateTxn.h"           // for EditAggregateTxn
 #include "EditTxn.h"                    // for EditTxn
 #include "IMETextTxn.h"                 // for IMETextTxn
 #include "InsertElementTxn.h"           // for InsertElementTxn
 #include "InsertTextTxn.h"              // for InsertTextTxn
 #include "JoinElementTxn.h"             // for JoinElementTxn
 #include "PlaceholderTxn.h"             // for PlaceholderTxn
 #include "SplitElementTxn.h"            // for SplitElementTxn
+#include "TextComposition.h"            // for TextComposition
 #include "mozFlushType.h"               // for mozFlushType::Flush_Frames
 #include "mozISpellCheckingEngine.h"
 #include "mozInlineSpellChecker.h"      // for mozInlineSpellChecker
 #include "mozilla/Preferences.h"        // for Preferences
 #include "mozilla/Selection.h"          // for Selection, etc
 #include "mozilla/Services.h"           // for GetObserverService
 #include "mozilla/TextEvents.h"
 #include "mozilla/dom/Element.h"        // for Element, nsINode::AsElement
@@ -134,22 +135,19 @@ nsEditor::nsEditor()
 ,  mSelState(nullptr)
 ,  mPhonetic(nullptr)
 ,  mModCount(0)
 ,  mFlags(0)
 ,  mUpdateCount(0)
 ,  mPlaceHolderBatch(0)
 ,  mAction(EditAction::none)
 ,  mIMETextOffset(0)
-,  mIMEBufferLength(0)
 ,  mDirection(eNone)
 ,  mDocDirtyState(-1)
 ,  mSpellcheckCheckboxState(eTriUnset)
-,  mInIMEMode(false)
-,  mIsIMEComposing(false)
 ,  mShouldTxnSetSelection(true)
 ,  mDidPreDestroy(false)
 ,  mDidPostCreate(false)
 ,  mDispatchInputEvent(true)
 {
 }
 
 nsEditor::~nsEditor()
@@ -243,18 +241,16 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsI
   if (aRoot)
     mRootElement = do_QueryInterface(aRoot);
 
   mUpdateCount=0;
 
   /* initialize IME stuff */
   mIMETextNode = nullptr;
   mIMETextOffset = 0;
-  mIMEBufferLength = 0;
-  
   /* Show the caret */
   selCon->SetCaretReadOnly(false);
   selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
 
   selCon->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);//we want to see all the selection reflected to user
 
   NS_POSTCONDITION(mDocWeak, "bad state");
 
@@ -356,16 +352,20 @@ nsEditor::InstallEventListeners()
 
 void
 nsEditor::RemoveEventListeners()
 {
   if (!mDocWeak || !mEventListener) {
     return;
   }
   reinterpret_cast<nsEditorEventListener*>(mEventListener.get())->Disconnect();
+  if (mComposition) {
+    mComposition->EndHandlingComposition(this);
+    mComposition = nullptr;
+  }
   mEventTarget = nullptr;
 }
 
 bool
 nsEditor::GetDesiredSpellCheckState()
 {
   // Check user override on this element
   if (mSpellcheckCheckboxState != eTriUnset) {
@@ -961,17 +961,19 @@ nsEditor::EndPlaceHolderTransaction()
       else  
       {
         // in the future we will check to make sure undo is off here,
         // since that is the only known case where the placeholdertxn would disappear on us.
         // For now just removing the assert.
       }
       // notify editor observers of action but if composing, it's done by
       // text event handler.
-      if (!mInIMEMode) NotifyEditorObservers();
+      if (!mComposition) {
+        NotifyEditorObservers();
+      }
     }
   }
   mPlaceHolderBatch--;
   
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -2005,50 +2007,64 @@ nsEditor::RestorePreservedSelection(nsIS
 
 void     
 nsEditor::StopPreservingSelection()
 {
   mRangeUpdater.DropSelectionState(mSavedSel);
   mSavedSel.MakeEmpty();
 }
 
+void
+nsEditor::EnsureComposition(mozilla::WidgetGUIEvent* aEvent)
+{
+  if (mComposition) {
+    return;
+  }
+  // The compositionstart event must cause creating new TextComposition
+  // instance at being dispatched by nsIMEStateManager.
+  mComposition = nsIMEStateManager::GetTextCompositionFor(aEvent);
+  if (!mComposition) {
+    MOZ_CRASH("nsIMEStateManager doesn't return proper composition");
+  }
+  mComposition->StartHandlingComposition(this);
+}
 
 nsresult
-nsEditor::BeginIMEComposition()
-{
-  mInIMEMode = true;
+nsEditor::BeginIMEComposition(WidgetCompositionEvent* aCompositionEvent)
+{
+  MOZ_ASSERT(!mComposition, "There is composition already");
+  EnsureComposition(aCompositionEvent);
   if (mPhonetic) {
     mPhonetic->Truncate(0);
   }
   return NS_OK;
 }
 
 void
 nsEditor::EndIMEComposition()
 {
-  NS_ENSURE_TRUE_VOID(mInIMEMode); // nothing to do
+  NS_ENSURE_TRUE_VOID(mComposition); // nothing to do
 
   // commit the IME transaction..we can get at it via the transaction mgr.
   // Note that this means IME won't work without an undo stack!
   if (mTxnMgr) {
     nsCOMPtr<nsITransaction> txn = mTxnMgr->PeekUndoStack();
     nsCOMPtr<nsIAbsorbingTransaction> plcTxn = do_QueryInterface(txn);
     if (plcTxn) {
       DebugOnly<nsresult> rv = plcTxn->Commit();
       NS_ASSERTION(NS_SUCCEEDED(rv),
                    "nsIAbsorbingTransaction::Commit() failed");
     }
   }
 
   /* reset the data we need to construct a transaction */
   mIMETextNode = nullptr;
   mIMETextOffset = 0;
-  mIMEBufferLength = 0;
-  mInIMEMode = false;
-  mIsIMEComposing = false;
+  mComposition->EndHandlingComposition(this);
+  mComposition = nullptr;
 
   // notify editor observers of action
   NotifyEditorObservers();
 }
 
 
 NS_IMETHODIMP
 nsEditor::GetPhonetic(nsAString& aPhonetic)
@@ -2068,17 +2084,17 @@ nsEditor::ForceCompositionEnd()
   if (!ps) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   nsPresContext* pc = ps->GetPresContext();
   if (!pc) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  if (!mInIMEMode) {
+  if (!mComposition) {
     // XXXmnakano see bug 558976, ResetInputState() has two meaning which are
     // "commit the composition" and "cursor is moved".  This method name is
     // "ForceCompositionEnd", so, ResetInputState() should be used only for the
     // former here.  However, ResetInputState() is also used for the latter here
     // because even if we don't have composition, we call ResetInputState() on
     // Linux.  Currently, nsGtkIMModule can know the timing of the cursor move,
     // so, the latter meaning should be gone.
     // XXX This may commit a composition in another editor.
@@ -2307,17 +2323,17 @@ nsEditor::InsertTextImpl(const nsAString
                          nsIDOMDocument* aDoc)
 {
   // NOTE: caller *must* have already used nsAutoTxnsConserveSelection
   // stack-based class to turn off txn selection updating.  Caller also turned
   // on rules sniffing if desired.
 
   NS_ENSURE_TRUE(aInOutNode && *aInOutNode && aInOutOffset && aDoc,
                  NS_ERROR_NULL_POINTER);
-  if (!mInIMEMode && aStringToInsert.IsEmpty()) {
+  if (!mComposition && aStringToInsert.IsEmpty()) {
     return NS_OK;
   }
 
   nsCOMPtr<nsINode> node = do_QueryInterface(*aInOutNode);
   NS_ENSURE_STATE(node);
   uint32_t offset = static_cast<uint32_t>(*aInOutOffset);
 
   if (!node->IsNodeOfType(nsINode::eTEXT) && IsPlaintextEditor()) {
@@ -2347,17 +2363,17 @@ nsEditor::InsertTextImpl(const nsAString
         offset = node->Length();
       } else if (node->GetParentNode() && node->GetParentNode() == root) {
         node = node->GetParentNode();
       }
     }
   }
 
   nsresult res;
-  if (mInIMEMode) {
+  if (mComposition) {
     if (!node->IsNodeOfType(nsINode::eTEXT)) {
       // create a text node
       nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
       NS_ENSURE_STATE(doc);
       nsRefPtr<nsTextNode> newNode = doc->CreateTextNode(EmptyString());
       // then we insert it into the dom tree
       res = InsertNode(newNode->AsDOMNode(), node->AsDOMNode(), offset);
       NS_ENSURE_SUCCESS(res, res);
@@ -2402,17 +2418,17 @@ nsresult nsEditor::InsertTextIntoTextNod
                                               int32_t aOffset,
                                               bool aSuppressIME)
 {
   nsRefPtr<EditTxn> txn;
   nsresult result = NS_OK;
   bool isIMETransaction = false;
   // aSuppressIME is used when editor must insert text, yet this text is not
   // part of current ime operation.  example: adjusting whitespace around an ime insertion.
-  if (mIMETextRangeList && mInIMEMode && !aSuppressIME)
+  if (mIMETextRangeList && mComposition && !aSuppressIME)
   {
     if (!mIMETextNode)
     {
       mIMETextNode = aTextNode;
       mIMETextOffset = aOffset;
     }
     uint16_t len ;
     len = mIMETextRangeList->GetLength();
@@ -4174,55 +4190,26 @@ nsEditor::DeleteSelectionAndCreateNode(c
 
   // we want the selection to be just after the new node
   return selection->Collapse(node, offset + 1);
 }
 
 
 /* Non-interface, protected methods */
 
-int32_t
-nsEditor::GetIMEBufferLength()
-{
-  return mIMEBufferLength;
-}
-
-void
-nsEditor::SetIsIMEComposing(){  
-  // We set mIsIMEComposing according to mIMETextRangeList.
-  nsCOMPtr<nsIPrivateTextRange> rangePtr;
-  uint16_t listlen, type;
-
-  mIsIMEComposing = false;
-  listlen = mIMETextRangeList->GetLength();
-
-  for (uint16_t i = 0; i < listlen; i++)
-  {
-      rangePtr = mIMETextRangeList->Item(i);
-      if (!rangePtr) continue;
-      nsresult result = rangePtr->GetRangeType(&type);
-      if (NS_FAILED(result)) continue;
-      if ( type == nsIPrivateTextRange::TEXTRANGE_RAWINPUT ||
-           type == nsIPrivateTextRange::TEXTRANGE_CONVERTEDTEXT ||
-           type == nsIPrivateTextRange::TEXTRANGE_SELECTEDRAWTEXT ||
-           type == nsIPrivateTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT )
-      {
-        mIsIMEComposing = true;
-#ifdef DEBUG_IME
-        printf("nsEditor::mIsIMEComposing = true\n");
-#endif
-        break;
-      }
-  }
-  return;
+TextComposition*
+nsEditor::GetComposition() const
+{
+  return mComposition;
 }
 
 bool
-nsEditor::IsIMEComposing() {
-  return mIsIMEComposing;
+nsEditor::IsIMEComposing() const
+{
+  return mComposition && mComposition->IsComposing();
 }
 
 nsresult
 nsEditor::DeleteSelectionAndPrepareToCreateNode()
 {
   nsresult res;
   nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
@@ -4409,17 +4396,19 @@ nsEditor::CreateTxnForDeleteNode(nsINode
 NS_IMETHODIMP 
 nsEditor::CreateTxnForIMEText(const nsAString& aStringToInsert,
                               IMETextTxn ** aTxn)
 {
   NS_ASSERTION(aTxn, "illegal value- null ptr- aTxn");
      
   nsRefPtr<IMETextTxn> txn = new IMETextTxn();
 
-  nsresult rv = txn->Init(mIMETextNode, mIMETextOffset, mIMEBufferLength,
+  // During handling IME composition, mComposition must have been initialized.
+  nsresult rv = txn->Init(mIMETextNode, mIMETextOffset,
+                          mComposition->String().Length(),
                           mIMETextRangeList, aStringToInsert, this);
   if (NS_SUCCEEDED(rv))
   {
     txn.forget(aTxn);
   }
 
   return rv;
 }
@@ -5220,16 +5209,33 @@ nsEditor::IsAcceptableInputEvent(nsIDOME
   // If this is mouse event but this editor doesn't have focus, we shouldn't
   // handle it.
   nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent);
   if (mouseEvent) {
     nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
     if (!focusedContent) {
       return false;
     }
+  } else {
+    nsAutoString eventType;
+    aEvent->GetType(eventType);
+    // If composition event or text event isn't dispatched via widget,
+    // we need to ignore them since they cannot be managed by TextComposition.
+    // E.g., the event was created by chrome JS.
+    // Note that if we allow to handle such events, editor may be confused by
+    // strange event order.
+    if (eventType.EqualsLiteral("text") ||
+        eventType.EqualsLiteral("compositionstart") ||
+        eventType.EqualsLiteral("compositionend")) {
+      WidgetGUIEvent* widgetGUIEvent =
+        aEvent->GetInternalNSEvent()->AsGUIEvent();
+      if (!widgetGUIEvent || !widgetGUIEvent->widget) {
+        return false;
+      }
+    }
   }
 
   bool isTrusted;
   nsresult rv = aEvent->GetIsTrusted(&isTrusted);
   NS_ENSURE_SUCCESS(rv, false);
   if (isTrusted) {
     return true;
   }
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -64,16 +64,17 @@ class nsISupports;
 class nsITransaction;
 class nsIWidget;
 class nsRange;
 class nsString;
 class nsTransactionManager;
 
 namespace mozilla {
 class Selection;
+class TextComposition;
 
 namespace dom {
 class Element;
 class EventTarget;
 }  // namespace dom
 }  // namespace mozilla
 
 namespace mozilla {
@@ -237,19 +238,18 @@ public:
      Arguments:
       nsString& aTag          - tag you want
       nsIContent** aContent   - returned Content that was created with above namespace.
   */
   nsresult CreateHTMLContent(const nsAString& aTag,
                              mozilla::dom::Element** aContent);
 
   // IME event handlers
-  virtual nsresult BeginIMEComposition();
-  virtual nsresult UpdateIMEComposition(const nsAString &aCompositionString,
-                                        nsIPrivateTextRangeList *aTextRange)=0;
+  virtual nsresult BeginIMEComposition(mozilla::WidgetCompositionEvent* aEvent);
+  virtual nsresult UpdateIMEComposition(nsIDOMEvent* aDOMTextEvent) = 0;
   void EndIMEComposition();
 
   void SwitchTextDirectionTo(uint32_t aDirection);
 
 protected:
   nsresult DetermineCurrentDirection();
   void FireInputEvent();
 
@@ -408,16 +408,23 @@ protected:
 
   bool CanEnableSpellCheck()
   {
     // Check for password/readonly/disabled, which are not spellchecked
     // regardless of DOM. Also, check to see if spell check should be skipped or not.
     return !IsPasswordEditor() && !IsReadonly() && !IsDisabled() && !ShouldSkipSpellCheck();
   }
 
+  /**
+   * EnsureComposition() should be composition event handlers or text event
+   * handler.  This tries to get the composition for the event and set it to
+   * mComposition.
+   */
+  void EnsureComposition(mozilla::WidgetGUIEvent* aEvent);
+
 public:
 
   /** All editor operations which alter the doc should be prefaced
    *  with a call to StartOperation, naming the action and direction */
   NS_IMETHOD StartOperation(EditAction opID,
                             nsIEditor::EDirection aDirection);
 
   /** All editor operations which alter the doc should be followed
@@ -587,19 +594,24 @@ public:
   bool IsMozEditorBogusNode(nsIContent *aNode);
 
   /** counts number of editable child nodes */
   uint32_t CountEditableChildren(nsINode* aNode);
   
   /** Find the deep first and last children. */
   nsINode* GetFirstEditableNode(nsINode* aRoot);
 
-  int32_t GetIMEBufferLength();
-  bool IsIMEComposing();    /* test if IME is in composition state */
-  void SetIsIMEComposing(); /* call this before |IsIMEComposing()| */
+  /**
+   * Returns current composition.
+   */
+  mozilla::TextComposition* GetComposition() const;
+  /**
+   * Returns true if there is composition string and not fixed.
+   */
+  bool IsIMEComposing() const;
 
   /** from html rules code - migration in progress */
   static nsresult GetTagString(nsIDOMNode *aNode, nsAString& outString);
   static nsIAtom *GetTag(nsIDOMNode *aNode);
 
   bool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
   virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2);
 
@@ -825,16 +837,19 @@ protected:
   nsCOMPtr<mozilla::dom::EventTarget> mEventTarget; // The form field as an event receiver
   nsCOMPtr<nsIDOMEventListener> mEventListener;
   nsWeakPtr        mSelConWeak;          // weak reference to the nsISelectionController
   nsWeakPtr        mPlaceHolderTxn;      // weak reference to placeholder for begin/end batch purposes
   nsWeakPtr        mDocWeak;             // weak reference to the nsIDOMDocument
   nsIAtom          *mPlaceHolderName;    // name of placeholder transaction
   nsSelectionState *mSelState;           // saved selection state for placeholder txn batching
   nsString         *mPhonetic;
+  // IME composition this is not null between compositionstart and
+  // compositionend.
+  nsRefPtr<mozilla::TextComposition> mComposition;
 
   // various listeners
   nsCOMArray<nsIEditActionListener> mActionListeners;  // listens to all low level actions on the doc
   nsCOMArray<nsIEditorObserver> mEditorObservers;  // just notify once per high level change
   nsCOMArray<nsIDocumentStateListener> mDocStateListeners;// listen to overall doc state (dirty or not, just created, etc)
 
   nsSelectionState  mSavedSel;           // cached selection for nsAutoSelectionReset
   nsRangeUpdater    mRangeUpdater;       // utility class object for maintaining preserved ranges
@@ -843,26 +858,21 @@ protected:
   uint32_t          mFlags;        // behavior flags. See nsIPlaintextEditor.idl for the flags we use.
 
   int32_t           mUpdateCount;
 
   int32_t           mPlaceHolderBatch;   // nesting count for batching
   EditAction        mAction;             // the current editor action
 
   uint32_t          mIMETextOffset;    // offset in text node where IME comp string begins
-  uint32_t          mIMEBufferLength;  // current length of IME comp string
 
   EDirection        mDirection;          // the current direction of editor action
   int8_t            mDocDirtyState;      // -1 = not initialized
   uint8_t           mSpellcheckCheckboxState; // a Tristate value
 
-  bool mInIMEMode;        // are we inside an IME composition?
-  bool mIsIMEComposing;   // is IME in composition state?
-                                                       // This is different from mInIMEMode. see Bug 98434.
-
   bool mShouldTxnSetSelection;  // turn off for conservative selection adjustment by txns
   bool mDidPreDestroy;    // whether PreDestroy has been called
   bool mDidPostCreate;    // whether PostCreate has been called
   bool mDispatchInputEvent;
 
   friend bool NSCanUnload(nsISupports* serviceMgr);
   friend class nsAutoTxnsConserveSelection;
   friend class nsAutoSelectionReset;
--- a/editor/libeditor/base/nsEditorEventListener.cpp
+++ b/editor/libeditor/base/nsEditorEventListener.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=4 sw=2 et tw=78: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Preferences.h"        // for Preferences
+#include "mozilla/TextEvents.h"         // for WidgetCompositionEvent
 #include "mozilla/dom/Element.h"        // for Element
 #include "mozilla/dom/EventTarget.h"    // for EventTarget
 #include "nsAString.h"
 #include "nsCaret.h"                    // for nsCaret
 #include "nsDebug.h"                    // for NS_ENSURE_TRUE, etc
 #include "nsEditor.h"                   // for nsEditor, etc
 #include "nsEditorEventListener.h"
 #include "nsEventListenerManager.h"     // for nsEventListenerManager
@@ -37,18 +38,16 @@
 #include "nsIFocusManager.h"            // for nsIFocusManager
 #include "nsIFormControl.h"             // for nsIFormControl, etc
 #include "nsIHTMLEditor.h"              // for nsIHTMLEditor
 #include "nsIMEStateManager.h"          // for nsIMEStateManager
 #include "nsINativeKeyBindings.h"       // for nsINativeKeyBindings
 #include "nsINode.h"                    // for nsINode, ::NODE_IS_EDITABLE, etc
 #include "nsIPlaintextEditor.h"         // for nsIPlaintextEditor, etc
 #include "nsIPresShell.h"               // for nsIPresShell
-#include "nsIPrivateTextEvent.h"        // for nsIPrivateTextEvent
-#include "nsIPrivateTextRange.h"        // for nsIPrivateTextRangeList
 #include "nsISelection.h"               // for nsISelection
 #include "nsISelectionController.h"     // for nsISelectionController, etc
 #include "nsISelectionPrivate.h"        // for nsISelectionPrivate
 #include "nsITransferable.h"            // for kFileMime, kHTMLMime, etc
 #include "nsLiteralString.h"            // for NS_LITERAL_STRING
 #include "nsPIWindowRoot.h"             // for nsPIWindowRoot
 #include "nsServiceManagerUtils.h"      // for do_GetService
 #include "nsString.h"                   // for nsAutoString
@@ -656,34 +655,22 @@ NS_IMETHODIMP
 nsEditorEventListener::HandleText(nsIDOMEvent* aTextEvent)
 {
   NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
 
   if (!mEditor->IsAcceptableInputEvent(aTextEvent)) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIPrivateTextEvent> textEvent = do_QueryInterface(aTextEvent);
-  if (!textEvent) {
-     //non-ui event passed in.  bad things.
-     return NS_OK;
-  }
-
-  nsAutoString                      composedText;
-  nsCOMPtr<nsIPrivateTextRangeList> textRangeList;
-
-  textEvent->GetText(composedText);
-  textRangeList = textEvent->GetInputRange();
-
   // if we are readonly or disabled, then do nothing.
   if (mEditor->IsReadonly() || mEditor->IsDisabled()) {
     return NS_OK;
   }
 
-  return mEditor->UpdateIMEComposition(composedText, textRangeList);
+  return mEditor->UpdateIMEComposition(aTextEvent);
 }
 
 /**
  * Drag event implementation
  */
 
 nsresult
 nsEditorEventListener::DragEnter(nsIDOMDragEvent* aDragEvent)
@@ -900,17 +887,19 @@ nsEditorEventListener::CanDrop(nsIDOMDra
 
 NS_IMETHODIMP
 nsEditorEventListener::HandleStartComposition(nsIDOMEvent* aCompositionEvent)
 {
   NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
   if (!mEditor->IsAcceptableInputEvent(aCompositionEvent)) {
     return NS_OK;
   }
-  return mEditor->BeginIMEComposition();
+  WidgetCompositionEvent* compositionStart =
+    aCompositionEvent->GetInternalNSEvent()->AsCompositionEvent();
+  return mEditor->BeginIMEComposition(compositionStart);
 }
 
 void
 nsEditorEventListener::HandleEndComposition(nsIDOMEvent* aCompositionEvent)
 {
   MOZ_ASSERT(mEditor);
   if (!mEditor->IsAcceptableInputEvent(aCompositionEvent)) {
     return;
--- a/editor/libeditor/text/moz.build
+++ b/editor/libeditor/text/moz.build
@@ -15,12 +15,13 @@ UNIFIED_SOURCES += [
     'nsTextEditUtils.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     '../base',
     '/content/base/src',
+    '/dom/events',
     '/editor/txmgr/src',
 ]
 
 FINAL_LIBRARY = 'gklayout'
--- a/editor/libeditor/text/nsPlaintextEditor.cpp
+++ b/editor/libeditor/text/nsPlaintextEditor.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
+#include "TextComposition.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Selection.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/mozalloc.h"
 #include "nsAString.h"
 #include "nsAutoPtr.h"
@@ -34,16 +35,17 @@
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIEditorIMESupport.h"
 #include "nsINameSpaceManager.h"
 #include "nsINode.h"
 #include "nsIPresShell.h"
+#include "nsIPrivateTextEvent.h"
 #include "nsIPrivateTextRange.h"
 #include "nsISelection.h"
 #include "nsISelectionController.h"
 #include "nsISelectionPrivate.h"
 #include "nsISupportsPrimitives.h"
 #include "nsITransferable.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsInternetCiter.h"
@@ -690,18 +692,17 @@ nsPlaintextEditor::DeleteSelection(EDire
 NS_IMETHODIMP nsPlaintextEditor::InsertText(const nsAString &aStringToInsert)
 {
   if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
 
   // Protect the edit rules object from dying
   nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
 
   EditAction opID = EditAction::insertText;
-  if (mInIMEMode) 
-  {
+  if (mComposition) {
     opID = EditAction::insertIMEText;
   }
   nsAutoPlaceHolderBatch batch(this, nullptr); 
   nsAutoRules beginRulesSniffing(this, opID, nsIEditor::eNext);
 
   // pre-process
   nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
@@ -806,72 +807,81 @@ NS_IMETHODIMP nsPlaintextEditor::InsertL
     // post-process, always called if WillInsertBreak didn't return cancel==true
     res = mRules->DidDoAction(selection, &ruleInfo, res);
   }
 
   return res;
 }
 
 nsresult
-nsPlaintextEditor::BeginIMEComposition()
+nsPlaintextEditor::BeginIMEComposition(WidgetCompositionEvent* aEvent)
 {
-  NS_ENSURE_TRUE(!mInIMEMode, NS_OK);
+  NS_ENSURE_TRUE(!mComposition, NS_OK);
 
   if (IsPasswordEditor()) {
     NS_ENSURE_TRUE(mRules, NS_ERROR_NULL_POINTER);
     // Protect the edit rules object from dying
     nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
 
     nsTextEditRules *textEditRules =
       static_cast<nsTextEditRules*>(mRules.get());
     textEditRules->ResetIMETextPWBuf();
   }
 
-  return nsEditor::BeginIMEComposition();
+  return nsEditor::BeginIMEComposition(aEvent);
 }
 
 nsresult
-nsPlaintextEditor::UpdateIMEComposition(const nsAString& aCompositionString,
-                                        nsIPrivateTextRangeList* aTextRangeList)
+nsPlaintextEditor::UpdateIMEComposition(nsIDOMEvent* aDOMTextEvent)
 {
-  NS_ABORT_IF_FALSE(aTextRangeList, "aTextRangeList must not be nullptr");
+  NS_ABORT_IF_FALSE(aDOMTextEvent, "aDOMTextEvent must not be nullptr");
+
+  WidgetTextEvent* widgetTextEvent =
+    aDOMTextEvent->GetInternalNSEvent()->AsTextEvent();
+  NS_ENSURE_TRUE(widgetTextEvent, NS_ERROR_INVALID_ARG);
+
+  EnsureComposition(widgetTextEvent);
 
   nsCOMPtr<nsIPresShell> ps = GetPresShell();
   NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
 
   nsCOMPtr<nsISelection> selection;
   nsresult rv = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRefPtr<nsCaret> caretP = ps->GetCaret();
 
-  // Update information of clauses in the new composition string.
-  // This will be refered by followed methods.
-  mIMETextRangeList = aTextRangeList;
-
-  // We set mIsIMEComposing properly.
-  SetIsIMEComposing();
+  nsCOMPtr<nsIPrivateTextEvent> privateTextEvent =
+    do_QueryInterface(aDOMTextEvent);
+  NS_ENSURE_TRUE(privateTextEvent, NS_ERROR_INVALID_ARG);
 
   {
+    TextComposition::TextEventHandlingMarker
+      textEventHandlingMarker(mComposition, widgetTextEvent);
+
+    // Update information of clauses in the new composition string.
+    // This will be refered by followed methods.
+    mIMETextRangeList = privateTextEvent->GetInputRange();
+    NS_ABORT_IF_FALSE(mIMETextRangeList,
+                      "mIMETextRangeList must not be nullptr");
+
     nsAutoPlaceHolderBatch batch(this, nsGkAtoms::IMETxnName);
 
-    rv = InsertText(aCompositionString);
-
-    mIMEBufferLength = aCompositionString.Length();
+    rv = InsertText(widgetTextEvent->theText);
 
     if (caretP) {
       caretP->SetCaretDOMSelection(selection);
     }
   }
 
   // If still composing, we should fire input event via observer.
   // Note that if committed, we don't need to notify it since it will be
   // notified at followed compositionend event.
   // NOTE: We must notify after the auto batch will be gone.
-  if (mIsIMEComposing) {
+  if (IsIMEComposing()) {
     NotifyEditorObservers();
   }
 
   return rv;
 }
 
 already_AddRefed<nsIContent>
 nsPlaintextEditor::GetInputEventTargetContent()
--- a/editor/libeditor/text/nsPlaintextEditor.h
+++ b/editor/libeditor/text/nsPlaintextEditor.h
@@ -117,19 +117,18 @@ public:
 
   /** make the given selection span the entire document */
   NS_IMETHOD SelectEntireDocument(nsISelection *aSelection);
 
   virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
 
   virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget();
 
-  virtual nsresult BeginIMEComposition();
-  virtual nsresult UpdateIMEComposition(const nsAString &aCompositionString,
-                                        nsIPrivateTextRangeList *aTextRange);
+  virtual nsresult BeginIMEComposition(mozilla::WidgetCompositionEvent* aEvent);
+  virtual nsresult UpdateIMEComposition(nsIDOMEvent* aTextEvent) MOZ_OVERRIDE;
 
   virtual already_AddRefed<nsIContent> GetInputEventTargetContent();
 
   /* ------------ Utility Routines, not part of public API -------------- */
   NS_IMETHOD TypedText(const nsAString& aString, ETypingAction aAction);
 
   nsresult InsertTextAt(const nsAString &aStringToInsert,
                         nsIDOMNode *aDestinationNode,
--- a/editor/libeditor/text/nsTextEditRules.cpp
+++ b/editor/libeditor/text/nsTextEditRules.cpp
@@ -1,13 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "TextComposition.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Selection.h"
 #include "mozilla/dom/Element.h"
 #include "nsAString.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
@@ -1203,17 +1204,18 @@ nsTextEditRules::TruncateInsertionIfNeed
     int32_t docLength;
     res = mEditor->GetTextLength(&docLength);
     if (NS_FAILED(res)) { return res; }
 
     int32_t start, end;
     nsContentUtils::GetSelectionInTextControl(aSelection, mEditor->GetRoot(),
                                               start, end);
 
-    int32_t oldCompStrLength = mEditor->GetIMEBufferLength();
+    TextComposition* composition = mEditor->GetComposition();
+    int32_t oldCompStrLength = composition ? composition->String().Length() : 0;
 
     const int32_t selectionLength = end - start;
     const int32_t resultingDocLength = docLength - selectionLength - oldCompStrLength;
     if (resultingDocLength >= aMaxLength)
     {
       aOutString->Truncate();
       if (aTruncated) {
         *aTruncated = true;
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -1,13 +1,14 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include <initguid.h>
 #include "DrawTargetD2D1.h"
 #include "DrawTargetD2D.h"
 #include "FilterNodeSoftware.h"
 #include "GradientStopsD2D.h"
 #include "SourceSurfaceD2D1.h"
 #include "SourceSurfaceD2D.h"
 #include "RadialGradientEffectD2D1.h"
 
--- a/gfx/2d/RadialGradientEffectD2D1.cpp
+++ b/gfx/2d/RadialGradientEffectD2D1.cpp
@@ -45,21 +45,21 @@ static const PCWSTR kXmlDescription =
             <Property name='Transform' type='matrix3x2'>
               <Property name='DisplayName' type='string' value='Transform applied to the pattern'/>
             </Property>
 
         </Effect>
         );
 
 // {FB947CDA-718E-40CC-AE7B-D255830D7D14}
-DEFINE_GUID(GUID_SampleRadialGradientPS, 
-0xfb947cda, 0x718e, 0x40cc, 0xae, 0x7b, 0xd2, 0x55, 0x83, 0xd, 0x7d, 0x14);
+static const GUID GUID_SampleRadialGradientPS =
+  {0xfb947cda, 0x718e, 0x40cc, {0xae, 0x7b, 0xd2, 0x55, 0x83, 0xd, 0x7d, 0x14}};
 // {2C468128-6546-453C-8E25-F2DF0DE10A0F}
-DEFINE_GUID(GUID_SampleRadialGradientA0PS, 
-0x2c468128, 0x6546, 0x453c, 0x8e, 0x25, 0xf2, 0xdf, 0xd, 0xe1, 0xa, 0xf);
+static const GUID GUID_SampleRadialGradientA0PS =
+  {0x2c468128, 0x6546, 0x453c, {0x8e, 0x25, 0xf2, 0xdf, 0xd, 0xe1, 0xa, 0xf}};
 
 namespace mozilla {
 namespace gfx {
 
 RadialGradientEffectD2D1::RadialGradientEffectD2D1()
   : mRefCount(0)
   , mCenter1(D2D1::Vector2F(0, 0))
   , mCenter2(D2D1::Vector2F(0, 0))
--- a/gfx/2d/gfx2d.vcxproj
+++ b/gfx/2d/gfx2d.vcxproj
@@ -1,9 +1,9 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
       <Configuration>Debug</Configuration>
       <Platform>Win32</Platform>
     </ProjectConfiguration>
     <ProjectConfiguration Include="Release|Win32">
       <Configuration>Release</Configuration>
@@ -37,17 +37,17 @@
     <ExecutablePath>$(DXSDK_DIR)\Utilities\bin\x86;$(ExecutablePath)</ExecutablePath>
     <IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <LinkIncremental>true</LinkIncremental>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
-      <PreprocessorDefinitions>INITGUID;USE_SSE2;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);GFX_LOG_DEBUG;GFX_LOG_WARNING;MFBT_STAND_ALONE;XP_WIN</PreprocessorDefinitions>
+      <PreprocessorDefinitions>USE_SSE2;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);GFX_LOG_DEBUG;GFX_LOG_WARNING;MFBT_STAND_ALONE;XP_WIN</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <Optimization>Disabled</Optimization>
     </ClCompile>
     <Link>
       <TargetMachine>MachineX86</TargetMachine>
       <GenerateDebugInformation>true</GenerateDebugInformation>
@@ -57,17 +57,17 @@
     </Link>
     <PreBuildEvent>
       <Command>xcopy $(ProjectDir)..\..\mfbt\*.h mozilla\ /Y</Command>
       <Message>Copying MFBT files</Message>
     </PreBuildEvent>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
-      <PreprocessorDefinitions>INITGUID;USE_SSE2;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>USE_SSE2;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <AdditionalIncludeDirectories>./</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <TargetMachine>MachineX86</TargetMachine>
       <GenerateDebugInformation>true</GenerateDebugInformation>
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -47,17 +47,16 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wi
     SOURCES += [
         'DrawTargetD2D.cpp',
         'PathD2D.cpp',
         'ScaledFontDWrite.cpp',
         'SourceSurfaceD2D.cpp',
         'SourceSurfaceD2DTarget.cpp',
     ]
     DEFINES['WIN32'] = True
-    DEFINES['INITGUID'] = True
     # For Direct2D 1.1 we require WINSDK_MAXVER 0x06020000 or higher.
     if CONFIG['MOZ_ENABLE_DIRECT2D1_1']:
         SOURCES += [
             'DrawTargetD2D1.cpp',
             'FilterNodeD2D1.cpp',
             'RadialGradientEffectD2D1.cpp',
             'SourceSurfaceD2D1.cpp'
         ]
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -71,16 +71,17 @@ static const char *sExtensionNames[] = {
     "GL_OES_stencil8",
     "GL_OES_texture_npot",
     "GL_ARB_depth_texture",
     "GL_OES_depth_texture",
     "GL_OES_packed_depth_stencil",
     "GL_IMG_read_format",
     "GL_EXT_read_format_bgra",
     "GL_APPLE_client_storage",
+    "GL_APPLE_texture_range",
     "GL_ARB_texture_non_power_of_two",
     "GL_ARB_pixel_buffer_object",
     "GL_ARB_ES2_compatibility",
     "GL_ARB_ES3_compatibility",
     "GL_OES_texture_float",
     "GL_OES_texture_float_linear",
     "GL_ARB_texture_float",
     "GL_OES_texture_half_float",
@@ -751,16 +752,27 @@ GLContext::InitWithPrefix(const char *pr
                 NS_ERROR("GL supports OES_EGL_image without supplying its functions.");
 
                 MarkExtensionUnsupported(OES_EGL_image);
                 mSymbols.fEGLImageTargetTexture2D = nullptr;
                 mSymbols.fEGLImageTargetRenderbufferStorage = nullptr;
             }
         }
 
+        if (IsExtensionSupported(APPLE_texture_range)) {
+            SymLoadStruct vaoSymbols[] = {
+                { (PRFuncPtr*) &mSymbols.fTextureRangeAPPLE, { "TextureRangeAPPLE", nullptr } },
+                { nullptr, { nullptr } },
+            };
+
+            if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
+                mSymbols.fTextureRangeAPPLE = nullptr;
+            }
+        }
+
         if (IsExtensionSupported(ARB_vertex_array_object) ||
             IsExtensionSupported(OES_vertex_array_object)) {
             SymLoadStruct vaoSymbols[] = {
                 { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", "IsVertexArrayOES", nullptr } },
                 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", "GenVertexArraysOES", nullptr } },
                 { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", "BindVertexArrayOES", nullptr } },
                 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", "DeleteVertexArraysOES", nullptr } },
                 { nullptr, { nullptr } },
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -347,16 +347,17 @@ public:
         OES_stencil8,
         OES_texture_npot,
         ARB_depth_texture,
         OES_depth_texture,
         OES_packed_depth_stencil,
         IMG_read_format,
         EXT_read_format_bgra,
         APPLE_client_storage,
+        APPLE_texture_range,
         ARB_texture_non_power_of_two,
         ARB_pixel_buffer_object,
         ARB_ES2_compatibility,
         ARB_ES3_compatibility,
         OES_texture_float,
         OES_texture_float_linear,
         ARB_texture_float,
         OES_texture_half_float,
@@ -1339,16 +1340,22 @@ public:
     }
 
     void fPixelStorei(GLenum pname, GLint param) {
         BEFORE_GL_CALL;
         mSymbols.fPixelStorei(pname, param);
         AFTER_GL_CALL;
     }
 
+    void fTextureRangeAPPLE(GLenum target, GLsizei length, GLvoid *pointer) {
+        BEFORE_GL_CALL;
+        mSymbols.fTextureRangeAPPLE(target, length, pointer);
+        AFTER_GL_CALL;
+    }
+
     void fPointParameterf(GLenum pname, GLfloat param) {
         BEFORE_GL_CALL;
         mSymbols.fPointParameterf(pname, param);
         AFTER_GL_CALL;
     }
 
     void fPolygonOffset(GLfloat factor, GLfloat bias) {
         BEFORE_GL_CALL;
--- a/gfx/gl/GLContextSymbols.h
+++ b/gfx/gl/GLContextSymbols.h
@@ -206,16 +206,18 @@ struct GLContextSymbols
     typedef void (GLAPIENTRY * PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
     PFNGLSTENCILOPPROC fStencilOp;
     typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
     PFNGLSTENCILOPSEPARATEPROC fStencilOpSeparate;
     typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
     PFNGLTEXIMAGE2DPROC fTexImage2D;
     typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
     PFNGLTEXSUBIMAGE2DPROC fTexSubImage2D;
+    typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, GLvoid *pointer);
+    PFNGLTEXTURERANGEAPPLEPROC fTextureRangeAPPLE;
     typedef void (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
     PFNGLUNIFORM1FPROC fUniform1f;
     typedef void (GLAPIENTRY * PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat* value);
     PFNGLUNIFORM1FVPROC fUniform1fv;
     typedef void (GLAPIENTRY * PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
     PFNGLUNIFORM1IPROC fUniform1i;
     typedef void (GLAPIENTRY * PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint* value);
     PFNGLUNIFORM1IVPROC fUniform1iv;
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -15,16 +15,17 @@
 #ifdef MOZ_WIDGET_GONK
 #include "SharedSurfaceGralloc.h"
 #include "nsXULAppAPI.h"
 #endif
 #ifdef XP_MACOSX
 #include "SharedSurfaceIO.h"
 #endif
 #include "ScopedGLHelpers.h"
+#include "gfx2DGlue.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace gl {
 
 GLScreenBuffer*
 GLScreenBuffer::Create(GLContext* gl,
@@ -473,19 +474,32 @@ GLScreenBuffer::CreateRead(SharedSurface
 {
     GLContext* gl = mFactory->GL();
     const GLFormats& formats = mFactory->Formats();
     const SurfaceCaps& caps = mFactory->ReadCaps();
 
     return ReadBuffer::Create(gl, caps, formats, surf);
 }
 
+void
+GLScreenBuffer::Readback(SharedSurface_GL* src, DataSourceSurface* dest)
+{
+  MOZ_ASSERT(src && dest);
+  DataSourceSurface::MappedSurface ms;
+  dest->Map(DataSourceSurface::MapType::READ, &ms);
+  nsRefPtr<gfxImageSurface> wrappedDest =
+    new gfxImageSurface(ms.mData,
+                        ThebesIntSize(dest->GetSize()),
+                        ms.mStride,
+                        SurfaceFormatToImageFormat(dest->GetFormat()));
+  DeprecatedReadback(src, wrappedDest);
+}
 
 void
-GLScreenBuffer::Readback(SharedSurface_GL* src, gfxImageSurface* dest)
+GLScreenBuffer::DeprecatedReadback(SharedSurface_GL* src, gfxImageSurface* dest)
 {
     MOZ_ASSERT(src && dest);
     MOZ_ASSERT(ToIntSize(dest->GetSize()) == src->Size());
     MOZ_ASSERT(dest->Format() == (src->HasAlpha() ? gfxImageFormat::ARGB32
                                                   : gfxImageFormat::RGB24));
 
     mGL->MakeCurrent();
 
@@ -504,18 +518,16 @@ GLScreenBuffer::Readback(SharedSurface_G
     delete buffer;
 
     if (needsSwap) {
         src->UnlockProd();
         SharedSurf()->LockProd();
     }
 }
 
-
-
 DrawBuffer*
 DrawBuffer::Create(GLContext* const gl,
                    const SurfaceCaps& caps,
                    const GLFormats& formats,
                    const gfx::IntSize& size)
 {
     if (!caps.color) {
         MOZ_ASSERT(!caps.alpha && !caps.depth && !caps.stencil);
--- a/gfx/gl/GLScreenBuffer.h
+++ b/gfx/gl/GLScreenBuffer.h
@@ -13,16 +13,17 @@
 */
 
 #ifndef SCREEN_BUFFER_H_
 #define SCREEN_BUFFER_H_
 
 #include "SurfaceTypes.h"
 #include "GLContextTypes.h"
 #include "GLDefs.h"
+#include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Point.h"
 
 // Forwards:
 class gfxImageSurface;
 
 namespace mozilla {
     namespace gfx {
         class SurfaceStream;
@@ -272,17 +273,18 @@ protected:
     // Returns false on error or inability to resize.
     bool Swap(const gfx::IntSize& size);
 
 public:
     bool PublishFrame(const gfx::IntSize& size);
 
     bool Resize(const gfx::IntSize& size);
 
-    void Readback(SharedSurface_GL* src, gfxImageSurface* dest);
+    void Readback(SharedSurface_GL* src, gfx::DataSourceSurface* dest);
+    void DeprecatedReadback(SharedSurface_GL* src, gfxImageSurface* dest);
 
 protected:
     void Attach(SharedSurface* surface, const gfx::IntSize& size);
 
     DrawBuffer* CreateDraw(const gfx::IntSize& size);
     ReadBuffer* CreateRead(SharedSurface_GL* surf);
 
 public:
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -59,22 +59,16 @@ const TextureFlags TEXTURE_TILE         
 // from the previous texture.
 const TextureFlags TEXTURE_COPY_PREVIOUS      = 1 << 24;
 // Who is responsible for deallocating the shared data.
 // if TEXTURE_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.
 const TextureFlags TEXTURE_DEALLOCATE_CLIENT  = 1 << 25;
-// The host side is responsible for deallocation, but that may not happen
-// immediately after the client side requests it. Exactly when the texture is
-// deallocated is up to the compositable. The texture must be deallocated by
-// the time the compositable or texture host is destroyed. A texture may not
-// have both TEXTURE_DEALLOCATE_CLIENT and TEXTURE_DEALLOCATE_DEFERRED flags.
-const TextureFlags TEXTURE_DEALLOCATE_DEFERRED  = 1 << 26;
 // 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.
 const TextureFlags TEXTURE_IMMUTABLE          = 1 << 27;
 // The contents of the texture must be uploaded or copied immediately
 // during the transaction, because the producer may want to write
 // to it again.
 const TextureFlags TEXTURE_IMMEDIATE_UPLOAD   = 1 << 28;
--- a/gfx/layers/CopyableCanvasLayer.cpp
+++ b/gfx/layers/CopyableCanvasLayer.cpp
@@ -17,16 +17,17 @@
 #include "gfxRect.h"                    // for gfxRect
 #include "gfxUtils.h"                   // for gfxUtils
 #include "gfx2DGlue.h"                  // for thebes --> moz2d transition
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "nsDebug.h"                    // for NS_ASSERTION, NS_WARNING, etc
 #include "nsISupportsImpl.h"            // for gfxContext::AddRef, etc
 #include "nsRect.h"                     // for nsIntRect
 #include "nsSize.h"                     // for nsIntSize
+#include "LayerUtils.h"
 
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData) :
@@ -51,49 +52,142 @@ CopyableCanvasLayer::Initialize(const Da
     mIsGLAlphaPremult = aData.mIsGLAlphaPremult;
     mNeedsYFlip = true;
     MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
 
     // [Basic Layers, non-OMTC] WebGL layer init.
     // `GLScreenBuffer::Morph`ing is only needed in BasicShadowableCanvasLayer.
   } else if (aData.mDrawTarget) {
     mDrawTarget = aData.mDrawTarget;
-    mSurface =
+    mSurface = mDrawTarget->Snapshot();
+    mDeprecatedSurface =
       gfxPlatform::GetPlatform()->CreateThebesSurfaceAliasForDrawTarget_hack(mDrawTarget);
     mNeedsYFlip = false;
   } else {
     NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
   }
 
   mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
 }
 
 bool
 CopyableCanvasLayer::IsDataValid(const Data& aData)
 {
   return mGLContext == aData.mGLContext;
 }
 
 void
-CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
+CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget,
+                                  SourceSurface* aMaskSurface)
 {
   if (!IsDirty())
     return;
   Painted();
 
   if (mDrawTarget) {
     mDrawTarget->Flush();
-    mSurface =
+    mSurface = mDrawTarget->Snapshot();
+  }
+
+  if (!mGLContext && aDestTarget) {
+    PaintWithOpacity(aDestTarget, 1.0f, aMaskSurface);
+    return;
+  }
+
+  if (mGLContext) {
+    RefPtr<DataSourceSurface> readSurf;
+    RefPtr<SourceSurface> resultSurf;
+
+    SharedSurface* sharedSurf = mGLContext->RequestFrame();
+    if (!sharedSurf) {
+      NS_WARNING("Null frame received.");
+      return;
+    }
+
+    IntSize readSize(sharedSurf->Size());
+    SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
+                            ? SurfaceFormat::B8G8R8X8
+                            : SurfaceFormat::B8G8R8A8;
+
+    if (aDestTarget) {
+      resultSurf = aDestTarget->Snapshot();
+      if (!resultSurf) {
+        resultSurf = GetTempSurface(readSize, format);
+      }
+    } else {
+      resultSurf = GetTempSurface(readSize, format);
+    }
+    MOZ_ASSERT(resultSurf);
+    MOZ_ASSERT(sharedSurf->APIType() == APITypeT::OpenGL);
+    SharedSurface_GL* surfGL = SharedSurface_GL::Cast(sharedSurf);
+
+    if (surfGL->Type() == SharedSurfaceType::Basic) {
+      // sharedSurf_Basic->mData must outlive readSurf. Alas, readSurf may not
+      // leave the scope it was declared in.
+      SharedSurface_Basic* sharedSurf_Basic = SharedSurface_Basic::Cast(surfGL);
+      readSurf = sharedSurf_Basic->GetData();
+    } else {
+      if (resultSurf->GetSize() != readSize ||
+          !(readSurf = resultSurf->GetDataSurface()) ||
+          readSurf->GetFormat() != format)
+      {
+        readSurf = GetTempSurface(readSize, format);
+      }
+
+      // Readback handles Flush/MarkDirty.
+      mGLContext->Screen()->Readback(surfGL, readSurf);
+    }
+    MOZ_ASSERT(readSurf);
+
+    bool needsPremult = surfGL->HasAlpha() && !mIsGLAlphaPremult;
+    if (needsPremult) {
+      PremultiplySurface(readSurf);
+    }
+
+    if (readSurf != resultSurf) {
+      RefPtr<DataSourceSurface> resultDataSurface =
+        resultSurf->GetDataSurface();
+      RefPtr<DrawTarget> dt =
+        Factory::CreateDrawTargetForData(BackendType::CAIRO,
+                                         resultDataSurface->GetData(),
+                                         resultDataSurface->GetSize(),
+                                         resultDataSurface->Stride(),
+                                         resultDataSurface->GetFormat());
+      IntSize readSize = readSurf->GetSize();
+      Rect r(0, 0, readSize.width, readSize.height);
+      DrawOptions opts(1.0f, CompositionOp::OP_SOURCE, AntialiasMode::DEFAULT);
+      dt->DrawSurface(readSurf, r, r, DrawSurfaceOptions(), opts);
+    }
+
+    // If !aDestSurface then we will end up painting using mSurface, so
+    // stick our surface into mSurface, so that the Paint() path is the same.
+    if (!aDestTarget) {
+      mSurface = resultSurf;
+    }
+  }
+}
+
+void
+CopyableCanvasLayer::DeprecatedUpdateSurface(gfxASurface* aDestSurface,
+                                             Layer* aMaskLayer)
+{
+  if (!IsDirty())
+    return;
+  Painted();
+
+  if (mDrawTarget) {
+    mDrawTarget->Flush();
+    mDeprecatedSurface =
       gfxPlatform::GetPlatform()->CreateThebesSurfaceAliasForDrawTarget_hack(mDrawTarget);
   }
 
   if (!mGLContext && aDestSurface) {
     nsRefPtr<gfxContext> tmpCtx = new gfxContext(aDestSurface);
     tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
-    CopyableCanvasLayer::PaintWithOpacity(tmpCtx, 1.0f, aMaskLayer);
+    DeprecatedPaintWithOpacity(tmpCtx, 1.0f, aMaskLayer);
     return;
   }
 
   if (mGLContext) {
     nsRefPtr<gfxImageSurface> readSurf;
     RefPtr<DataSourceSurface> readDSurf;
     nsRefPtr<gfxASurface> resultSurf;
 
@@ -106,17 +200,17 @@ CopyableCanvasLayer::UpdateSurface(gfxAS
     IntSize readSize(sharedSurf->Size());
     gfxImageFormat format = (GetContentFlags() & CONTENT_OPAQUE)
                             ? gfxImageFormat::RGB24
                             : gfxImageFormat::ARGB32;
 
     if (aDestSurface) {
       resultSurf = aDestSurface;
     } else {
-      resultSurf = GetTempSurface(readSize, format);
+      resultSurf = DeprecatedGetTempSurface(readSize, format);
     }
     MOZ_ASSERT(resultSurf);
     if (resultSurf->CairoStatus() != 0) {
       MOZ_ASSERT(false, "Bad resultSurf->CairoStatus().");
       return;
     }
 
     MOZ_ASSERT(sharedSurf->APIType() == APITypeT::OpenGL);
@@ -131,59 +225,105 @@ CopyableCanvasLayer::UpdateSurface(gfxAS
                                      ThebesIntSize(readDSurf->GetSize()),
                                      readDSurf->Stride(),
                                      SurfaceFormatToImageFormat(readDSurf->GetFormat()));
     } else {
       if (ToIntSize(resultSurf->GetSize()) != readSize ||
           !(readSurf = resultSurf->GetAsImageSurface()) ||
           readSurf->Format() != format)
       {
-        readSurf = GetTempSurface(readSize, format);
+        readSurf = DeprecatedGetTempSurface(readSize, format);
       }
 
       // Readback handles Flush/MarkDirty.
-      mGLContext->Screen()->Readback(surfGL, readSurf);
+      mGLContext->Screen()->DeprecatedReadback(surfGL, readSurf);
     }
     MOZ_ASSERT(readSurf);
 
     bool needsPremult = surfGL->HasAlpha() && !mIsGLAlphaPremult;
     if (needsPremult) {
       readSurf->Flush();
       gfxUtils::PremultiplyImageSurface(readSurf);
       readSurf->MarkDirty();
     }
-    
+
     if (readSurf != resultSurf) {
       readSurf->Flush();
       nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf);
       ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
       ctx->SetSource(readSurf);
       ctx->Paint();
     }
 
     // If !aDestSurface then we will end up painting using mSurface, so
     // stick our surface into mSurface, so that the Paint() path is the same.
     if (!aDestSurface) {
-      mSurface = resultSurf;
+      mDeprecatedSurface = resultSurf;
     }
   }
 }
 
 void
-CopyableCanvasLayer::PaintWithOpacity(gfxContext* aContext,
+CopyableCanvasLayer::PaintWithOpacity(gfx::DrawTarget* aTarget,
                                       float aOpacity,
-                                      Layer* aMaskLayer,
-                                      gfxContext::GraphicsOperator aOperator)
+                                      SourceSurface* aMaskSurface,
+                                      gfx::CompositionOp aOperator)
 {
   if (!mSurface) {
     NS_WARNING("No valid surface to draw!");
     return;
   }
 
-  nsRefPtr<gfxPattern> pat = new gfxPattern(mSurface);
+  SurfacePattern pat(mSurface, ExtendMode::CLAMP, Matrix(), ToFilter(mFilter));
+
+  Matrix oldTransform;
+  if (mNeedsYFlip) {
+    oldTransform = aTarget->GetTransform();
+    Matrix flipped = oldTransform;
+    flipped.Translate(0, mBounds.height);
+    flipped.Scale(1.0, -1.0);
+    aTarget->SetTransform(flipped);
+  }
+
+  DrawOptions options = DrawOptions(aOpacity, CompositionOp::OP_SOURCE);
+
+  // If content opaque, then save off current operator and set to source.
+  // This ensures that alpha is not applied even if the source surface
+  // has an alpha channel
+  if (GetContentFlags() & CONTENT_OPAQUE) {
+    options.mCompositionOp = CompositionOp::OP_SOURCE;
+  }
+
+  if (aOperator != CompositionOp::OP_OVER) {
+    options.mCompositionOp = aOperator;
+  }
+
+  Rect rect = Rect(0, 0, mBounds.width, mBounds.height);
+  aTarget->FillRect(rect, pat, options);
+  if (aMaskSurface) {
+    aTarget->MaskSurface(pat, aMaskSurface, Point(0, 0), options);
+  }
+
+  if (mNeedsYFlip) {
+    aTarget->SetTransform(oldTransform);
+  }
+}
+
+void
+CopyableCanvasLayer::DeprecatedPaintWithOpacity(gfxContext* aContext,
+                                                float aOpacity,
+                                                Layer* aMaskLayer,
+                                                gfxContext::GraphicsOperator aOperator)
+{
+  if (!mDeprecatedSurface) {
+    NS_WARNING("No valid surface to draw!");
+    return;
+  }
+
+  nsRefPtr<gfxPattern> pat = new gfxPattern(mDeprecatedSurface);
 
   pat->SetFilter(mFilter);
   pat->SetExtend(gfxPattern::EXTEND_PAD);
 
   gfxMatrix m;
   if (mNeedsYFlip) {
     m = aContext->CurrentMatrix();
     aContext->Translate(gfxPoint(0.0, mBounds.height));
@@ -211,33 +351,56 @@ CopyableCanvasLayer::PaintWithOpacity(gf
     aContext->SetOperator(savedOp);
   }  
 
   if (mNeedsYFlip) {
     aContext->SetMatrix(m);
   }
 }
 
-gfxImageSurface*
-CopyableCanvasLayer::GetTempSurface(const IntSize& aSize, const gfxImageFormat aFormat)
+DataSourceSurface*
+CopyableCanvasLayer::GetTempSurface(const IntSize& aSize,
+                                    const SurfaceFormat aFormat)
 {
   if (!mCachedTempSurface ||
       aSize.width != mCachedSize.width ||
       aSize.height != mCachedSize.height ||
       aFormat != mCachedFormat)
   {
-    mCachedTempSurface = new gfxImageSurface(ThebesIntSize(aSize), aFormat);
+    mCachedTempSurface = Factory::CreateDataSourceSurface(aSize, aFormat);
     mCachedSize = aSize;
     mCachedFormat = aFormat;
   }
 
-  MOZ_ASSERT(mCachedTempSurface->Stride() == mCachedTempSurface->Width() * 4);
+  MOZ_ASSERT(mCachedTempSurface->Stride() ==
+             mCachedTempSurface->GetSize().width * 4);
   return mCachedTempSurface;
 }
 
+gfxImageSurface*
+CopyableCanvasLayer::DeprecatedGetTempSurface(const IntSize& aSize,
+                                              const gfxImageFormat aFormat)
+{
+  if (!mDeprecatedCachedTempSurface ||
+      aSize.width != mCachedSize.width ||
+      aSize.height != mCachedSize.height ||
+      aFormat != mDeprecatedCachedFormat)
+  {
+    mDeprecatedCachedTempSurface =
+      new gfxImageSurface(ThebesIntSize(aSize), aFormat);
+    mCachedSize = aSize;
+    mDeprecatedCachedFormat = aFormat;
+  }
+
+  MOZ_ASSERT(mDeprecatedCachedTempSurface->Stride() ==
+             mDeprecatedCachedTempSurface->Width() * 4);
+  return mDeprecatedCachedTempSurface;
+}
+
 void
 CopyableCanvasLayer::DiscardTempSurface()
 {
   mCachedTempSurface = nullptr;
+  mDeprecatedCachedTempSurface = nullptr;
 }
 
 }
 }
--- a/gfx/layers/CopyableCanvasLayer.h
+++ b/gfx/layers/CopyableCanvasLayer.h
@@ -36,39 +36,57 @@ public:
   CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData);
   virtual ~CopyableCanvasLayer();
 
   virtual void Initialize(const Data& aData);
 
   virtual bool IsDataValid(const Data& aData);
 
 protected:
-  void PaintWithOpacity(gfxContext* aContext,
+  void PaintWithOpacity(gfx::DrawTarget* aTarget,
                         float aOpacity,
-                        Layer* aMaskLayer,
-                        gfxContext::GraphicsOperator aOperator = gfxContext::OPERATOR_OVER);
+                        gfx::SourceSurface* aMaskSurface,
+                        gfx::CompositionOp aOperator = gfx::CompositionOp::OP_OVER);
 
-  void UpdateSurface(gfxASurface* aDestSurface = nullptr,
-                     Layer* aMaskLayer = nullptr);
+  void UpdateTarget(gfx::DrawTarget* aDestTarget = nullptr,
+                    gfx::SourceSurface* aMaskSurface = nullptr);
 
-  nsRefPtr<gfxASurface> mSurface;
+  RefPtr<gfx::SourceSurface> mSurface;
+  nsRefPtr<gfxASurface> mDeprecatedSurface;
   nsRefPtr<mozilla::gl::GLContext> mGLContext;
   mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
 
   uint32_t mCanvasFramebuffer;
 
   bool mIsGLAlphaPremult;
   bool mNeedsYFlip;
   bool mForceReadback;
 
-  nsRefPtr<gfxImageSurface> mCachedTempSurface;
+  RefPtr<gfx::DataSourceSurface> mCachedTempSurface;
+  nsRefPtr<gfxImageSurface> mDeprecatedCachedTempSurface;
   gfx::IntSize mCachedSize;
-  gfxImageFormat mCachedFormat;
+  gfx::SurfaceFormat mCachedFormat;
+  gfxImageFormat mDeprecatedCachedFormat;
 
-  gfxImageSurface* GetTempSurface(const gfx::IntSize& aSize, const gfxImageFormat aFormat);
+  gfx::DataSourceSurface* GetTempSurface(const gfx::IntSize& aSize,
+                                         const gfx::SurfaceFormat aFormat);
 
   void DiscardTempSurface();
+
+  /* Deprecated thebes methods */
+protected:
+  void DeprecatedPaintWithOpacity(gfxContext* aContext,
+                                  float aOpacity,
+                                  Layer* aMaskLayer,
+                                  gfxContext::GraphicsOperator aOperator = gfxContext::OPERATOR_OVER);
+
+  void DeprecatedUpdateSurface(gfxASurface* aDestSurface = nullptr,
+                               Layer* aMaskLayer = nullptr);
+
+  gfxImageSurface* DeprecatedGetTempSurface(const gfx::IntSize& aSize,
+                                            const gfxImageFormat aFormat);
+
 };
 
 }
 }
 
 #endif
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -705,18 +705,18 @@ protected:
   // asynchronusly using the ImageBridge IPDL protocol.
   ImageClient* mImageClient;
 };
 
 class AutoLockImage
 {
 public:
   AutoLockImage(ImageContainer *aContainer) : mContainer(aContainer) { mImage = mContainer->LockCurrentImage(); }
-  AutoLockImage(ImageContainer *aContainer, gfxASurface **aSurface) : mContainer(aContainer) {
-    *aSurface = mContainer->DeprecatedLockCurrentAsSurface(&mSize, getter_AddRefs(mImage)).get();
+  AutoLockImage(ImageContainer *aContainer, RefPtr<gfx::SourceSurface> *aSurface) : mContainer(aContainer) {
+    *aSurface = mContainer->LockCurrentAsSourceSurface(&mSize, getter_AddRefs(mImage));
   }
   ~AutoLockImage() { if (mContainer) { mContainer->UnlockCurrentImage(); } }
 
   Image* GetImage() { return mImage; }
   const gfx::IntSize &GetSize() { return mSize; }
 
   void Unlock() { 
     if (mContainer) {
new file mode 100644
--- /dev/null
+++ b/gfx/layers/LayerUtils.cpp
@@ -0,0 +1,79 @@
+/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "LayerUtils.h"
+#include "PremultiplyTables.h"
+
+namespace mozilla {
+namespace layers {
+
+using namespace mozilla::gfx;
+
+static inline const uint8_t PremultiplyValue(uint8_t a, uint8_t v) {
+  return PremultiplyTable[a*256+v];
+}
+
+static inline const uint8_t UnpremultiplyValue(uint8_t a, uint8_t v) {
+  return UnpremultiplyTable[a*256+v];
+}
+
+void
+PremultiplySurface(DataSourceSurface* srcSurface,
+                   DataSourceSurface* destSurface)
+{
+  if (!destSurface)
+    destSurface = srcSurface;
+
+  IntSize srcSize = srcSurface->GetSize();
+  MOZ_ASSERT(srcSurface->GetFormat() == destSurface->GetFormat() &&
+             srcSize.width  == destSurface->GetSize().width &&
+             srcSize.height  == destSurface->GetSize().height &&
+             srcSurface->Stride() == destSurface->Stride(),
+             "Source and destination surfaces don't have identical characteristics");
+
+  MOZ_ASSERT(srcSurface->Stride() == srcSize.width * 4,
+             "Source surface stride isn't tightly packed");
+
+  // Only premultiply ARGB32
+  if (srcSurface->GetFormat() != SurfaceFormat::B8G8R8A8) {
+    if (destSurface != srcSurface) {
+      memcpy(destSurface->GetData(), srcSurface->GetData(),
+             srcSurface->Stride() * srcSize.height);
+    }
+    return;
+  }
+
+  uint8_t *src = srcSurface->GetData();
+  uint8_t *dst = destSurface->GetData();
+
+  uint32_t dim = srcSize.width * srcSize.height;
+  for (uint32_t i = 0; i < dim; ++i) {
+#ifdef IS_LITTLE_ENDIAN
+    uint8_t b = *src++;
+    uint8_t g = *src++;
+    uint8_t r = *src++;
+    uint8_t a = *src++;
+
+    *dst++ = PremultiplyValue(a, b);
+    *dst++ = PremultiplyValue(a, g);
+    *dst++ = PremultiplyValue(a, r);
+    *dst++ = a;
+#else
+    uint8_t a = *src++;
+    uint8_t r = *src++;
+    uint8_t g = *src++;
+    uint8_t b = *src++;
+
+    *dst++ = a;
+    *dst++ = PremultiplyValue(a, r);
+    *dst++ = PremultiplyValue(a, g);
+    *dst++ = PremultiplyValue(a, b);
+#endif
+  }
+}
+
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/layers/LayerUtils.h
@@ -0,0 +1,21 @@
+/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_LAYERS_LAYERUTILS_H_
+#define MOZILLA_LAYERS_LAYERUTILS_H_
+
+#include "mozilla/gfx/2D.h"
+
+namespace mozilla {
+namespace layers {
+
+void
+PremultiplySurface(gfx::DataSourceSurface* srcSurface,
+                   gfx::DataSourceSurface* destSurface = nullptr);
+
+}
+}
+
+#endif /* MOZILLA_LAYERS_LAYERUTILS_H_ */
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -164,17 +164,17 @@ Layer::Layer(LayerManager* aManager, voi
   mParent(nullptr),
   mNextSibling(nullptr),
   mPrevSibling(nullptr),
   mImplData(aImplData),
   mMaskLayer(nullptr),
   mPostXScale(1.0f),
   mPostYScale(1.0f),
   mOpacity(1.0),
-  mMixBlendMode(gfxContext::OPERATOR_OVER),
+  mMixBlendMode(CompositionOp::OP_OVER),
   mForceIsolatedGroup(false),
   mContentFlags(0),
   mUseClipRect(false),
   mUseTileSourceRect(false),
   mIsFixedPosition(false),
   mMargins(0, 0, 0, 0),
   mStickyPositionData(nullptr),
   mScrollbarTargetId(FrameMetrics::NULL_SCROLL_ID),
@@ -665,30 +665,36 @@ Layer::GetEffectiveOpacity()
   float opacity = GetLocalOpacity();
   for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
        c = c->GetParent()) {
     opacity *= c->GetLocalOpacity();
   }
   return opacity;
 }
   
-gfxContext::GraphicsOperator
+CompositionOp
 Layer::GetEffectiveMixBlendMode()
 {
-  if(mMixBlendMode != gfxContext::OPERATOR_OVER)
+  if(mMixBlendMode != CompositionOp::OP_OVER)
     return mMixBlendMode;
   for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
     c = c->GetParent()) {
-    if(c->mMixBlendMode != gfxContext::OPERATOR_OVER)
+    if(c->mMixBlendMode != CompositionOp::OP_OVER)
       return c->mMixBlendMode;
   }
 
   return mMixBlendMode;
 }
 
+gfxContext::GraphicsOperator
+Layer::DeprecatedGetEffectiveMixBlendMode()
+{
+  return ThebesOp(GetEffectiveMixBlendMode());
+}
+
 void
 Layer::ComputeEffectiveTransformForMaskLayer(const Matrix4x4& aTransformToSurface)
 {
   if (mMaskLayer) {
     mMaskLayer->mEffectiveTransform = aTransformToSurface;
 
 #ifdef DEBUG
     bool maskIs2D = mMaskLayer->GetTransform().CanDraw2D();
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -13,16 +13,17 @@
 #include "Units.h"                      // for LayerMargin, LayerPoint
 #include "gfxContext.h"                 // for GraphicsOperator
 #include "gfxTypes.h"
 #include "gfxColor.h"                   // for gfxRGBA
 #include "gfxMatrix.h"                  // for gfxMatrix
 #include "GraphicsFilter.h"             // for GraphicsFilter
 #include "gfxPoint.h"                   // for gfxPoint
 #include "gfxRect.h"                    // for gfxRect
+#include "gfx2DGlue.h"
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT_HELPER2, etc
 #include "mozilla/DebugOnly.h"          // for DebugOnly
 #include "mozilla/EventForwards.h"      // for nsPaintEvent
 #include "mozilla/RefPtr.h"             // for TemporaryRef
 #include "mozilla/TimeStamp.h"          // for TimeStamp, TimeDuration
 #include "mozilla/gfx/BaseMargin.h"     // for BaseMargin
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/gfx/Point.h"          // for IntSize
@@ -781,25 +782,30 @@ public:
   {
     if (mOpacity != aOpacity) {
       MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) Opacity", this));
       mOpacity = aOpacity;
       Mutated();
     }
   }
 
-  void SetMixBlendMode(gfxContext::GraphicsOperator aMixBlendMode)
+  void SetMixBlendMode(gfx::CompositionOp aMixBlendMode)
   {
     if (mMixBlendMode != aMixBlendMode) {
       MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) MixBlendMode", this));
       mMixBlendMode = aMixBlendMode;
       Mutated();
     }
   }
   
+  void DeprecatedSetMixBlendMode(gfxContext::GraphicsOperator aMixBlendMode)
+  {
+    SetMixBlendMode(gfx::CompositionOpForOp(aMixBlendMode));
+  }
+
   void SetForceIsolatedGroup(bool aForceIsolatedGroup)
   {
     if(mForceIsolatedGroup != aForceIsolatedGroup) {
       MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ForceIsolatedGroup", this));
       mForceIsolatedGroup = aForceIsolatedGroup;
       Mutated();
     }
   }
@@ -1028,17 +1034,17 @@ public:
       mScrollbarTargetId = aScrollId;
       mScrollbarDirection = aDir;
       Mutated();
     }
   }
 
   // These getters can be used anytime.
   float GetOpacity() { return mOpacity; }
-  gfxContext::GraphicsOperator GetMixBlendMode() const { return mMixBlendMode; }
+  gfx::CompositionOp GetMixBlendMode() const { return mMixBlendMode; }
   const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nullptr; }
   uint32_t GetContentFlags() { return mContentFlags; }
   const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; }
   const EventRegions& GetEventRegions() const { return mEventRegions; }
   ContainerLayer* GetParent() { return mParent; }
   Layer* GetNextSibling() { return mNextSibling; }
   const Layer* GetNextSibling() const { return mNextSibling; }
   Layer* GetPrevSibling() { return mPrevSibling; }
@@ -1202,17 +1208,18 @@ public:
    * Returns the product of the opacities of this layer and all ancestors up
    * to and excluding the nearest ancestor that has UseIntermediateSurface() set.
    */
   float GetEffectiveOpacity();
   
   /**
    * Returns the blendmode of this layer.
    */
-  gfxContext::GraphicsOperator GetEffectiveMixBlendMode();
+  gfx::CompositionOp GetEffectiveMixBlendMode();
+  gfxContext::GraphicsOperator DeprecatedGetEffectiveMixBlendMode();
   
   /**
    * This returns the effective transform computed by
    * ComputeEffectiveTransforms. Typically this is a transform that transforms
    * this layer all the way to some intermediate surface or destination
    * surface. For non-BasicLayers this will be a transform to the nearest
    * ancestor with UseIntermediateSurface() (or to the root, if there is no
    * such ancestor), but for BasicLayers it's different.
@@ -1403,17 +1410,17 @@ protected:
   // meantime).
   nsAutoPtr<gfx::Matrix4x4> mPendingTransform;
   float mPostXScale;
   float mPostYScale;
   gfx::Matrix4x4 mEffectiveTransform;
   AnimationArray mAnimations;
   InfallibleTArray<AnimData> mAnimationData;
   float mOpacity;
-  gfxContext::GraphicsOperator mMixBlendMode;
+  gfx::CompositionOp mMixBlendMode;
   bool mForceIsolatedGroup;
   nsIntRect mClipRect;
   nsIntRect mTileSourceRect;
   nsIntRegion mInvalidRegion;
   uint32_t mContentFlags;
   bool mUseClipRect;
   bool mUseTileSourceRect;
   bool mIsFixedPosition;
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -8,8 +8,11 @@ include $(topsrcdir)/config/rules.mk
 CXXFLAGS += \
         -I$(ANDROID_SOURCE)/frameworks/base/include/media/stagefright \
         -I$(ANDROID_SOURCE)/frameworks/base/include/media/stagefright/openmax \
         -I$(ANDROID_SOURCE)/frameworks/av/include/media/stagefright \
         -I$(ANDROID_SOURCE)/frameworks/native/include/media/openmax \
         $(NULL)
 
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
+
+PremultiplyTables.h: $(srcdir)/genTables.py
+	$(PYTHON) $(srcdir)/genTables.py
--- a/gfx/layers/RotatedBuffer.cpp
+++ b/gfx/layers/RotatedBuffer.cpp
@@ -296,19 +296,27 @@ RotatedContentBuffer::BufferContentType(
     return ContentForFormat(format);
   }
   return gfxContentType::SENTINEL;
 }
 
 bool
 RotatedContentBuffer::BufferSizeOkFor(const nsIntSize& aSize)
 {
-  return (aSize == mBufferRect.Size() ||
-          (SizedToVisibleBounds != mBufferSizePolicy &&
-           aSize < mBufferRect.Size()));
+  if (aSize == mBufferRect.Size()) {
+    return true;
+  }
+
+  if (SizedToVisibleBounds != mBufferSizePolicy &&
+      aSize < mBufferRect.Size()) {
+    return (aSize.width * 2 > mBufferRect.width) &&
+           (aSize.height * 2 > mBufferRect.height);
+  }
+
+  return false;
 }
 
 bool
 RotatedContentBuffer::EnsureBuffer()
 {
   NS_ASSERTION(!mLoanedDrawTarget, "Loaned draw target must be returned");
   if (!mDTBuffer) {
     if (mDeprecatedBufferProvider) {
@@ -498,18 +506,19 @@ RotatedContentBuffer::BeginPaint(ThebesL
 
   result.mRegionToDraw.Sub(neededRegion, validRegion);
 
   // Do not modify result.mRegionToDraw or result.mContentType after this call.
   // Do not modify mBufferRect, mBufferRotation, or mDidSelfCopy,
   // or call CreateBuffer before this call.
   FinalizeFrame(result.mRegionToDraw);
 
-  if (result.mRegionToDraw.IsEmpty())
+  if (result.mRegionToDraw.IsEmpty()) {
     return result;
+  }
 
   nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
   RefPtr<DrawTarget> destDTBuffer;
   RefPtr<DrawTarget> destDTBufferOnWhite;
   uint32_t bufferFlags = canHaveRotation ? ALLOW_REPEAT : 0;
   if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
     bufferFlags |= BUFFER_COMPONENT_ALPHA;
   }
@@ -609,17 +618,17 @@ RotatedContentBuffer::BeginPaint(ThebesL
     } else {
       // No pixels are going to be kept. The whole visible region
       // will be redrawn, so we don't need to copy anything, so we don't
       // set destBuffer.
       mBufferRect = destBufferRect;
       mBufferRotation = nsIntPoint(0,0);
     }
   } else {
-    // The buffer's not big enough, so allocate a new one
+    // The buffer's not big enough or the buffer needs to shrink, so allocate a new one
     CreateBuffer(result.mContentType, destBufferRect, bufferFlags,
                  &destDTBuffer, &destDTBufferOnWhite);
     if (!destDTBuffer) {
       return result;
     }
   }
 
   NS_ASSERTION(!(aFlags & PAINT_WILL_RESAMPLE) || destBufferRect == neededRegion.GetBounds(),
--- a/gfx/layers/basic/BasicCanvasLayer.cpp
+++ b/gfx/layers/basic/BasicCanvasLayer.cpp
@@ -4,36 +4,60 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BasicCanvasLayer.h"
 #include "basic/BasicLayers.h"          // for BasicLayerManager
 #include "mozilla/mozalloc.h"           // for operator new
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
+#include "gfx2DGlue.h"
+
 class gfxContext;
 
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 void
-BasicCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
+BasicCanvasLayer::Paint(DrawTarget* aTarget, SourceSurface* aMaskSurface)
 {
   if (IsHidden())
     return;
 
   FirePreTransactionCallback();
-  UpdateSurface();
+  UpdateTarget();
   FireDidTransactionCallback();
 
-  gfxContext::GraphicsOperator mixBlendMode = GetEffectiveMixBlendMode();
-  PaintWithOpacity(aContext, GetEffectiveOpacity(), aMaskLayer, mixBlendMode != gfxContext::OPERATOR_OVER ? mixBlendMode : GetOperator());
+  CompositionOp mixBlendMode = GetEffectiveMixBlendMode();
+  PaintWithOpacity(aTarget,
+                   GetEffectiveOpacity(),
+                   aMaskSurface,
+                   mixBlendMode != CompositionOp::OP_OVER ? mixBlendMode : GetOperator());
+}
+
+void
+BasicCanvasLayer::DeprecatedPaint(gfxContext* aContext, Layer* aMaskLayer)
+{
+  if (IsHidden())
+    return;
+
+  FirePreTransactionCallback();
+  DeprecatedUpdateSurface();
+  FireDidTransactionCallback();
+
+  gfxContext::GraphicsOperator mixBlendMode = DeprecatedGetEffectiveMixBlendMode();
+  DeprecatedPaintWithOpacity(aContext,
+                             GetEffectiveOpacity(),
+                             aMaskLayer,
+                             mixBlendMode != gfxContext::OPERATOR_OVER ?
+                               mixBlendMode :
+                               DeprecatedGetOperator());
 }
 
 already_AddRefed<CanvasLayer>
 BasicLayerManager::CreateCanvasLayer()
 {
   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
   nsRefPtr<CanvasLayer> layer = new BasicCanvasLayer(this);
   return layer.forget();
--- a/gfx/layers/basic/BasicCanvasLayer.h
+++ b/gfx/layers/basic/BasicCanvasLayer.h
@@ -29,17 +29,19 @@ public:
   
   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(BasicManager()->InConstruction(),
                  "Can only set properties in construction phase");
     CanvasLayer::SetVisibleRegion(aRegion);
   }
   
-  virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
+  virtual void Paint(gfx::DrawTarget* aTarget,
+                     gfx::SourceSurface* aMaskSurface);
+  virtual void DeprecatedPaint(gfxContext* aContext, Layer* aMaskLayer);
  
 protected:
   BasicLayerManager* BasicManager()
   {
     return static_cast<BasicLayerManager*>(mManager);
   }
 };
 
--- a/gfx/layers/basic/BasicColorLayer.cpp
+++ b/gfx/layers/basic/BasicColorLayer.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BasicLayersImpl.h"            // for FillWithMask, etc
 #include "Layers.h"                     // for ColorLayer, etc
 #include "BasicImplData.h"              // for BasicImplData
 #include "BasicLayers.h"                // for BasicLayerManager
 #include "gfxContext.h"                 // for gfxContext, etc
 #include "gfxRect.h"                    // for gfxRect
+#include "gfx2DGlue.h"
 #include "mozilla/mozalloc.h"           // for operator new
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "nsRect.h"                     // for nsIntRect
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
@@ -38,23 +39,45 @@ public:
 
   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(BasicManager()->InConstruction(),
                  "Can only set properties in construction phase");
     ColorLayer::SetVisibleRegion(aRegion);
   }
 
-  virtual void Paint(gfxContext* aContext, Layer* aMaskLayer)
+  virtual void Paint(DrawTarget* aTarget, SourceSurface* aMaskSurface)
   {
-    if (IsHidden())
+    if (IsHidden()) {
       return;
+    }
+    CompositionOp mixBlendMode = GetEffectiveMixBlendMode();
+    CompositionOp op =
+      mixBlendMode != CompositionOp::OP_OVER ? mixBlendMode : GetOperator();
+
+    DrawOptions opts = DrawOptions();
+    opts.mCompositionOp = op;
+    ColorPattern pattern(ToColor(mColor));
+    aTarget->MaskSurface(pattern,
+                         aMaskSurface,
+                         ToIntRect(GetBounds()).TopLeft(),
+                         opts);
+  }
+
+  virtual void DeprecatedPaint(gfxContext* aContext, Layer* aMaskLayer)
+  {
+    if (IsHidden()) {
+      return;
+    }
     gfxContextAutoSaveRestore contextSR(aContext);
-    gfxContext::GraphicsOperator mixBlendMode = GetEffectiveMixBlendMode();
-    AutoSetOperator setOptimizedOperator(aContext, mixBlendMode != gfxContext::OPERATOR_OVER ? mixBlendMode : GetOperator());
+    gfxContext::GraphicsOperator mixBlendMode = DeprecatedGetEffectiveMixBlendMode();
+    AutoSetOperator setOptimizedOperator(aContext,
+                                         mixBlendMode != gfxContext::OPERATOR_OVER ?
+                                           mixBlendMode :
+                                           DeprecatedGetOperator());
 
     aContext->SetColor(mColor);
 
     nsIntRect bounds = GetBounds();
     aContext->NewPath();
     aContext->SnappedRectangle(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height));
 
     FillWithMask(aContext, GetEffectiveOpacity(), aMaskLayer);
--- a/gfx/layers/basic/BasicContainerLayer.cpp
+++ b/gfx/layers/basic/BasicContainerLayer.cpp
@@ -54,30 +54,30 @@ BasicContainerLayer::ComputeEffectiveTra
   // need to apply any compensation using the residual from SnapTransformTranslation.
   ComputeEffectiveTransformsForChildren(idealTransform);
 
   ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
 
   Layer* child = GetFirstChild();
   bool hasSingleBlendingChild = false;
   if (!HasMultipleChildren() && child) {
-    hasSingleBlendingChild = child->GetMixBlendMode() != gfxContext::OPERATOR_OVER;
+    hasSingleBlendingChild = child->GetMixBlendMode() != CompositionOp::OP_OVER;
   }
 
   /* If we have a single childand it is not blending,, it can just inherit our opacity,
    * otherwise we need a PushGroup and we need to mark ourselves as using
    * an intermediate surface so our children don't inherit our opacity
    * via GetEffectiveOpacity.
    * Having a mask layer always forces our own push group
    * Having a blend mode also always forces our own push group
    */
   mUseIntermediateSurface =
     GetMaskLayer() ||
     GetForceIsolatedGroup() ||
-    (GetMixBlendMode() != gfxContext::OPERATOR_OVER && HasMultipleChildren()) ||
+    (GetMixBlendMode() != CompositionOp::OP_OVER && HasMultipleChildren()) ||
     (GetEffectiveOpacity() != 1.0 && (HasMultipleChildren() || hasSingleBlendingChild));
 }
 
 bool
 BasicContainerLayer::ChildrenPartitionVisibleRegion(const nsIntRect& aInRect)
 {
   Matrix transform;
   if (!GetEffectiveTransform().CanDraw2D(&transform) ||
--- a/gfx/layers/basic/BasicImageLayer.cpp
+++ b/gfx/layers/basic/BasicImageLayer.cpp
@@ -47,93 +47,157 @@ public:
 
   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(BasicManager()->InConstruction(),
                  "Can only set properties in construction phase");
     ImageLayer::SetVisibleRegion(aRegion);
   }
 
-  virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
+  virtual void Paint(DrawTarget* aTarget, SourceSurface* aMaskSurface);
+  virtual void DeprecatedPaint(gfxContext* aContext, Layer* aMaskLayer);
 
   virtual bool GetAsSurface(gfxASurface** aSurface,
                             SurfaceDescriptor* aDescriptor);
 
 protected:
   BasicLayerManager* BasicManager()
   {
     return static_cast<BasicLayerManager*>(mManager);
   }
 
   // only paints the image if aContext is non-null
+  void
+  GetAndPaintCurrentImage(DrawTarget* aTarget,
+                          float aOpacity,
+                          SourceSurface* aMaskSurface);
   already_AddRefed<gfxPattern>
-  GetAndPaintCurrentImage(gfxContext* aContext,
-                          float aOpacity,
-                          Layer* aMaskLayer);
+  DeprecatedGetAndPaintCurrentImage(gfxContext* aContext,
+                                    float aOpacity,
+                                    Layer* aMaskLayer);
 
   gfx::IntSize mSize;
 };
 
+static void
+DeprecatedPaintContext(gfxPattern* aPattern,
+                       const nsIntRegion& aVisible,
+                       float aOpacity,
+                       gfxContext* aContext,
+                       Layer* aMaskLayer);
+
 void
-BasicImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
+BasicImageLayer::Paint(DrawTarget* aTarget, SourceSurface* aMaskSurface)
+{
+  if (IsHidden()) {
+    return;
+  }
+  GetAndPaintCurrentImage(aTarget, GetEffectiveOpacity(), aMaskSurface);
+}
+
+void
+BasicImageLayer::DeprecatedPaint(gfxContext* aContext, Layer* aMaskLayer)
 {
-  if (IsHidden())
+  if (IsHidden()) {
+    return;
+  }
+  nsRefPtr<gfxPattern> dontcare =
+    DeprecatedGetAndPaintCurrentImage(aContext,
+                                      GetEffectiveOpacity(),
+                                      aMaskLayer);
+}
+
+void
+BasicImageLayer::GetAndPaintCurrentImage(DrawTarget* aTarget,
+                                         float aOpacity,
+                                         SourceSurface* aMaskSurface)
+{
+  if (!mContainer) {
     return;
-  nsRefPtr<gfxPattern> dontcare =
-    GetAndPaintCurrentImage(aContext, GetEffectiveOpacity(), aMaskLayer);
+  }
+
+  mContainer->SetImageFactory(mManager->IsCompositingCheap() ?
+                              nullptr :
+                              BasicManager()->GetImageFactory());
+  IntSize size;
+  Image* image = nullptr;
+  RefPtr<SourceSurface> surf =
+    mContainer->LockCurrentAsSourceSurface(&size, &image);
+
+  if (!surf) {
+    return;
+  }
+
+  if (aTarget) {
+    // The visible region can extend outside the image, so just draw
+    // within the image bounds.
+    SurfacePattern pat(surf, ExtendMode::CLAMP, Matrix(), ToFilter(mFilter));
+    CompositionOp mixBlendMode = GetEffectiveMixBlendMode();
+    CompositionOp op =
+    mixBlendMode != CompositionOp::OP_OVER ? mixBlendMode : GetOperator();
+    DrawOptions opts(aOpacity, op);
+
+    aTarget->MaskSurface(pat, aMaskSurface, Point(0, 0), opts);
+
+    GetContainer()->NotifyPaintedImage(image);
+  }
+
+  mContainer->UnlockCurrentImage();
 }
 
 already_AddRefed<gfxPattern>
-BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
-                                         float aOpacity,
-                                         Layer* aMaskLayer)
+BasicImageLayer::DeprecatedGetAndPaintCurrentImage(gfxContext* aContext,
+                                                   float aOpacity,
+                                                   Layer* aMaskLayer)
 {
   if (!mContainer)
     return nullptr;
 
   mContainer->SetImageFactory(mManager->IsCompositingCheap() ? nullptr : BasicManager()->GetImageFactory());
 
-  nsRefPtr<gfxASurface> surface;
-  AutoLockImage autoLock(mContainer, getter_AddRefs(surface));
+  RefPtr<gfx::SourceSurface> surface;
+  AutoLockImage autoLock(mContainer, &surface);
   Image *image = autoLock.GetImage();
   gfx::IntSize size = mSize = autoLock.GetSize();
 
-  if (!surface || surface->CairoStatus()) {
+  if (!surface || !surface->IsValid()) {
     return nullptr;
   }
 
-  nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
+  nsRefPtr<gfxPattern> pat = new gfxPattern(surface, gfx::Matrix());
   if (!pat) {
     return nullptr;
   }
 
   pat->SetFilter(mFilter);
 
   // The visible region can extend outside the image, so just draw
   // within the image bounds.
   if (aContext) {
-    gfxContext::GraphicsOperator mixBlendMode = GetEffectiveMixBlendMode();
-    AutoSetOperator setOptimizedOperator(aContext, mixBlendMode != gfxContext::OPERATOR_OVER ? mixBlendMode : GetOperator());
+    CompositionOp mixBlendMode = GetEffectiveMixBlendMode();
+    CompositionOp op =
+      mixBlendMode != CompositionOp::OP_OVER ? mixBlendMode : GetOperator();
+    AutoSetOperator setOptimizedOperator(aContext, ThebesOp(op));
 
-    PaintContext(pat,
+    DeprecatedPaintContext(pat,
                  nsIntRegion(nsIntRect(0, 0, size.width, size.height)),
                  aOpacity, aContext, aMaskLayer);
 
     GetContainer()->NotifyPaintedImage(image);
   }
 
   return pat.forget();
 }
 
-void
-PaintContext(gfxPattern* aPattern,
-             const nsIntRegion& aVisible,
-             float aOpacity,
-             gfxContext* aContext,
-             Layer* aMaskLayer)
+static void
+DeprecatedPaintContext(gfxPattern* aPattern,
+                       const nsIntRegion& aVisible,
+                       float aOpacity,
+                       gfxContext* aContext,
+                       Layer* aMaskLayer)
 {
   // Set PAD mode so that when the video is being scaled, we do not sample
   // outside the bounds of the video image.
   gfxPattern::GraphicsExtend extend = gfxPattern::EXTEND_PAD;
 
 #ifdef MOZ_X11
   // PAD is slow with cairo and old X11 servers, so prefer speed over
   // correctness and use NONE.
--- a/gfx/layers/basic/BasicImplData.h
+++ b/gfx/layers/basic/BasicImplData.h
@@ -4,16 +4,18 @@
 
 #ifndef GFX_BASICIMPLDATA_H
 #define GFX_BASICIMPLDATA_H
 
 #include "Layers.h"                     // for Layer (ptr only), etc
 #include "gfxContext.h"                 // for gfxContext, etc
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
+#include "mozilla/gfx/Types.h"
+
 class gfxASurface;
 
 namespace mozilla {
 namespace layers {
 
 class ReadbackProcessor;
 class SurfaceDescriptor;
 
@@ -39,32 +41,34 @@ class SurfaceDescriptor;
  *       |                                  |
  *       +-> BasicImageLayer <--------------+
  */
 class BasicImplData {
 public:
   BasicImplData() : mHidden(false),
     mClipToVisibleRegion(false),
     mDrawAtomically(false),
-    mOperator(gfxContext::OPERATOR_OVER)
+    mOperator(gfx::CompositionOp::OP_OVER)
   {
     MOZ_COUNT_CTOR(BasicImplData);
   }
   virtual ~BasicImplData()
   {
     MOZ_COUNT_DTOR(BasicImplData);
   }
 
   /**
    * Layers that paint themselves, such as ImageLayers, should paint
    * in response to this method call. aContext will already have been
    * set up to account for all the properties of the layer (transform,
    * opacity, etc).
    */
-  virtual void Paint(gfxContext* aContext, Layer* aMaskLayer) {}
+  virtual void Paint(gfx::DrawTarget* aTarget,
+                     gfx::SourceSurface* aMaskSurface) {}
+  virtual void DeprecatedPaint(gfxContext* aContext, Layer* aMaskLayer) {}
 
   /**
    * Like Paint() but called for ThebesLayers with the additional parameters
    * they need.
    * If mClipToVisibleRegion is set, then the layer must clip to its
    * effective visible region (snapped or unsnapped, it doesn't matter).
    */
   virtual void PaintThebes(gfxContext* aContext,
@@ -89,24 +93,29 @@ public:
    */
   void SetHidden(bool aCovered) { mHidden = aCovered; }
   bool IsHidden() const { return false; }
   /**
    * This variable is set by MarkLayersHidden() before painting. This is
    * the operator to be used when compositing the layer in this transaction. It must
    * be OVER or SOURCE.
    */
-  void SetOperator(gfxContext::GraphicsOperator aOperator)
+  void SetOperator(gfx::CompositionOp aOperator)
   {
-    NS_ASSERTION(aOperator == gfxContext::OPERATOR_OVER ||
-                 aOperator == gfxContext::OPERATOR_SOURCE,
+    NS_ASSERTION(aOperator == gfx::CompositionOp::OP_OVER ||
+                 aOperator == gfx::CompositionOp::OP_SOURCE,
                  "Bad composition operator");
     mOperator = aOperator;
   }
-  gfxContext::GraphicsOperator GetOperator() const { return mOperator; }
+
+  gfx::CompositionOp GetOperator() const { return mOperator; }
+  gfxContext::GraphicsOperator DeprecatedGetOperator() const
+  {
+    return gfx::ThebesOp(mOperator);
+  }
 
   /**
    * Return a surface for this layer. Will use an existing surface, if
    * possible, or may create a temporary surface.  Implement this
    * method for any layers that might be used as a mask.  Should only
    * return false if a surface cannot be created.  If true is
    * returned, only one of |aSurface| or |aDescriptor| is valid.
    */
@@ -118,15 +127,15 @@ public:
   void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; }
 
   void SetDrawAtomically(bool aDrawAtomically) { mDrawAtomically = aDrawAtomically; }
 
 protected:
   bool mHidden;
   bool mClipToVisibleRegion;
   bool mDrawAtomically;
-  gfxContext::GraphicsOperator mOperator;
+  gfx::CompositionOp mOperator;
 };
 
 } // layers
 } // mozilla
 
 #endif
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -410,17 +410,17 @@ MarkLayersHidden(Layer* aLayer, const ns
           cr.SetRect(0, 0, 0, 0);
         }
       }
       newClipRect.IntersectRect(newClipRect, cr);
     }
   }
 
   BasicImplData* data = ToData(aLayer);
-  data->SetOperator(gfxContext::OPERATOR_OVER);
+  data->SetOperator(CompositionOp::OP_OVER);
   data->SetClipToVisibleRegion(false);
   data->SetDrawAtomically(false);
 
   if (!aLayer->AsContainerLayer()) {
     Matrix transform;
     if (!aLayer->GetEffectiveTransform().CanDraw2D(&transform)) {
       data->SetHidden(false);
       return;
@@ -495,23 +495,23 @@ ApplyDoubleBuffering(Layer* aLayer, cons
   }
 
   BasicContainerLayer* container =
     static_cast<BasicContainerLayer*>(aLayer->AsContainerLayer());
   // Layers that act as their own backbuffers should be drawn to the destination
   // using OPERATOR_SOURCE to ensure that alpha values in a transparent window
   // are cleared. This can also be faster than OPERATOR_OVER.
   if (!container) {
-    data->SetOperator(gfxContext::OPERATOR_SOURCE);
+    data->SetOperator(CompositionOp::OP_SOURCE);
     data->SetDrawAtomically(true);
   } else {
     if (container->UseIntermediateSurface() ||
         !container->ChildrenPartitionVisibleRegion(newVisibleRect)) {
       // We need to double-buffer this container.
-      data->SetOperator(gfxContext::OPERATOR_SOURCE);
+      data->SetOperator(CompositionOp::OP_SOURCE);
       container->ForceIntermediateSurface();
     } else {
       // Tell the children to clip to their visible regions so our assumption
       // that they don't paint outside their visible regions is valid!
       for (Layer* child = aLayer->GetFirstChild(); child;
            child = child->GetNextSibling()) {
         ToData(child)->SetClipToVisibleRegion(true);
         ApplyDoubleBuffering(child, newVisibleRect);
@@ -819,17 +819,17 @@ BasicLayerManager::PaintSelfOrChildren(P
   /* Only paint ourself, or our children - This optimization relies on this! */
   Layer* child = aPaintContext.mLayer->GetFirstChild();
   if (!child) {
     if (aPaintContext.mLayer->AsThebesLayer()) {
       data->PaintThebes(aGroupTarget, aPaintContext.mLayer->GetMaskLayer(),
           aPaintContext.mCallback, aPaintContext.mCallbackData,
           aPaintContext.mReadback);
     } else {
-      data->Paint(aGroupTarget, aPaintContext.mLayer->GetMaskLayer());
+      data->DeprecatedPaint(aGroupTarget, aPaintContext.mLayer->GetMaskLayer());
     }
   } else {
     ReadbackProcessor readback;
     ContainerLayer* container =
         static_cast<ContainerLayer*>(aPaintContext.mLayer);
     if (IsRetained()) {
       readback.BuildUpdates(container);
     }
@@ -857,17 +857,18 @@ BasicLayerManager::FlushGroup(PaintLayer
   // incomplete, the contents of this container layer are the final contents
   // for the window.
   if (!mTransactionIncomplete) {
     if (aNeedsClipToVisibleRegion) {
       gfxUtils::ClipToRegion(aPaintContext.mTarget,
                              aPaintContext.mLayer->GetEffectiveVisibleRegion());
     }
     BasicContainerLayer* container = static_cast<BasicContainerLayer*>(aPaintContext.mLayer);
-    AutoSetOperator setOperator(aPaintContext.mTarget, container->GetOperator());
+    AutoSetOperator setOperator(aPaintContext.mTarget,
+                                ThebesOp(container->GetOperator()));
     PaintWithMask(aPaintContext.mTarget, aPaintContext.mLayer->GetEffectiveOpacity(),
                   aPaintContext.mLayer->GetMaskLayer());
   }
 }
 
 void
 BasicLayerManager::PaintLayer(gfxContext* aTarget,
                               Layer* aLayer,
@@ -891,17 +892,17 @@ BasicLayerManager::PaintLayer(gfxContext
   // the container variable
   BasicContainerLayer* container = static_cast<BasicContainerLayer*>(aLayer);
   bool needsGroup = aLayer->GetFirstChild() &&
                     container->UseIntermediateSurface();
   BasicImplData* data = ToData(aLayer);
   bool needsClipToVisibleRegion =
     data->GetClipToVisibleRegion() && !aLayer->AsThebesLayer();
   NS_ASSERTION(needsGroup || !aLayer->GetFirstChild() ||
-               container->GetOperator() == gfxContext::OPERATOR_OVER,
+               container->GetOperator() == CompositionOp::OP_OVER,
                "non-OVER operator should have forced UseIntermediateSurface");
   NS_ASSERTION(!aLayer->GetFirstChild() || !aLayer->GetMaskLayer() ||
                container->UseIntermediateSurface(),
                "ContainerLayer with mask layer should force UseIntermediateSurface");
 
   gfxContextAutoSaveRestore contextSR;
   gfxMatrix transform;
   // Will return an identity matrix for 3d transforms, and is handled separately below.
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -192,19 +192,12 @@ protected:
 
   BufferMode mDoubleBuffering;
   bool mUsingDefaultTarget;
   bool mCachedSurfaceInUse;
   bool mTransactionIncomplete;
   bool mCompositorMightResample;
 };
 
-void
-PaintContext(gfxPattern* aPattern,
-             const nsIntRegion& aVisible,
-             float aOpacity,
-             gfxContext* aContext,
-             Layer* aMaskLayer);
-
 }
 }
 
 #endif /* GFX_BASICLAYERS_H */
--- a/gfx/layers/basic/BasicThebesLayer.cpp
+++ b/gfx/layers/basic/BasicThebesLayer.cpp
@@ -57,17 +57,17 @@ BasicThebesLayer::PaintThebes(gfxContext
                "Can only draw in drawing phase");
 
   nsTArray<ReadbackProcessor::Update> readbackUpdates;
   if (aReadback && UsedForReadback()) {
     aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
   }
 
   float opacity = GetEffectiveOpacity();
-  gfxContext::GraphicsOperator mixBlendMode = GetEffectiveMixBlendMode();
+  CompositionOp mixBlendMode = GetEffectiveMixBlendMode();
 
   if (!BasicManager()->IsRetained()) {
     NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer");
 
     mValidRegion.SetEmpty();
     mContentClient->Clear();
 
     nsIntRegion toDraw = IntersectWithClip(GetEffectiveVisibleRegion(), aContext);
@@ -78,37 +78,42 @@ BasicThebesLayer::PaintThebes(gfxContext
       if (!aCallback) {
         BasicManager()->SetTransactionIncomplete();
         return;
       }
 
       aContext->Save();
 
       bool needsClipToVisibleRegion = GetClipToVisibleRegion();
-      bool needsGroup =
-          opacity != 1.0 || GetOperator() != gfxContext::OPERATOR_OVER || mixBlendMode != gfxContext::OPERATOR_OVER || aMaskLayer;
+      bool needsGroup = opacity != 1.0 ||
+                        GetOperator() != CompositionOp::OP_OVER ||
+                        mixBlendMode != CompositionOp::OP_OVER ||
+                        aMaskLayer;
       nsRefPtr<gfxContext> groupContext;
       if (needsGroup) {
         groupContext =
           BasicManager()->PushGroupForLayer(aContext, this, toDraw,
                                             &needsClipToVisibleRegion);
-        if (GetOperator() != gfxContext::OPERATOR_OVER || mixBlendMode != gfxContext::OPERATOR_OVER) {
+        if (GetOperator() != CompositionOp::OP_OVER ||
+            mixBlendMode != CompositionOp::OP_OVER) {
           needsClipToVisibleRegion = true;
         }
       } else {
         groupContext = aContext;
       }
       SetAntialiasingFlags(this, groupContext);
       aCallback(this, groupContext, toDraw, DrawRegionClip::CLIP_NONE, nsIntRegion(), aCallbackData);
       if (needsGroup) {
         BasicManager()->PopGroupToSourceWithCachedSurface(aContext, groupContext);
         if (needsClipToVisibleRegion) {
           gfxUtils::ClipToRegion(aContext, toDraw);
         }
-        AutoSetOperator setOptimizedOperator(aContext, mixBlendMode != gfxContext::OPERATOR_OVER ? mixBlendMode : GetOperator());
+        CompositionOp op =
+          mixBlendMode != CompositionOp::OP_OVER ? mixBlendMode : GetOperator();
+        AutoSetOperator setOptimizedOperator(aContext, ThebesOp(op));
         PaintWithMask(aContext, opacity, aMaskLayer);
       }
 
       aContext->Restore();
     }
 
     RenderTraceInvalidateEnd(this, "FFFF00");
     return;
@@ -127,17 +132,17 @@ BasicThebesLayer::PaintThebes(gfxContext
   Matrix maskTransform;
   if (GetMaskData(aMaskLayer, &mask)) {
     maskSurface = mask.GetSurface();
     maskTransform = mask.GetTransform();
   }
 
   if (!IsHidden() && !clipExtents.IsEmpty()) {
     mContentClient->DrawTo(this, aContext->GetDrawTarget(), opacity,
-                           CompositionOpForOp(GetOperator()),
+                           GetOperator(),
                            maskSurface, &maskTransform);
   }
 
   for (uint32_t i = 0; i < readbackUpdates.Length(); ++i) {
     ReadbackProcessor::Update& update = readbackUpdates[i];
     nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
     nsRefPtr<gfxContext> ctx =
       update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -71,29 +71,30 @@ CanvasClient2D::Update(gfx::IntSize aSiz
 
     bufferCreated = true;
   }
 
   if (!mBuffer->Lock(OPEN_WRITE_ONLY)) {
     return;
   }
 
-  nsRefPtr<gfxASurface> surface = mBuffer->AsTextureClientSurface()->GetAsSurface();
-  if (surface) {
-    aLayer->UpdateSurface(surface);
+  RefPtr<DrawTarget> drawTarget =
+    mBuffer->AsTextureClientDrawTarget()->GetAsDrawTarget();
+  if (drawTarget) {
+    aLayer->UpdateTarget(drawTarget);
   }
 
   mBuffer->Unlock();
 
   if (bufferCreated && !AddTextureClient(mBuffer)) {
     mBuffer = nullptr;
     return;
   }
 
-  if (surface) {
+  if (drawTarget) {
     GetForwarder()->UpdatedTexture(this, mBuffer, nullptr);
     GetForwarder()->UseTexture(this, mBuffer);
   }
 }
 
 TemporaryRef<BufferTextureClient>
 CanvasClient2D::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
 {
@@ -210,17 +211,17 @@ DeprecatedCanvasClient2D::Update(gfx::In
     MOZ_ASSERT(mDeprecatedTextureClient, "Failed to create texture client");
     if (!mDeprecatedTextureClient->EnsureAllocated(aSize, contentType)) {
       NS_WARNING("Could not allocate texture client");
       return;
     }
   }
 
   gfxASurface* surface = mDeprecatedTextureClient->LockSurface();
-  aLayer->UpdateSurface(surface);
+  aLayer->DeprecatedUpdateSurface(surface);
   mDeprecatedTextureClient->Unlock();
 }
 
 void
 DeprecatedCanvasClientSurfaceStream::Updated()
 {
   mForwarder->UpdateTextureNoSwap(this, 1, mDeprecatedTextureClient->LockSurfaceDescriptor());
 }
--- a/gfx/layers/client/ClientImageLayer.cpp
+++ b/gfx/layers/client/ClientImageLayer.cpp
@@ -100,18 +100,18 @@ protected:
       return mImageClientTypeContainer;
     }
 
     if (mContainer->IsAsync()) {
       mImageClientTypeContainer = BUFFER_BRIDGE;
       return mImageClientTypeContainer;
     }
 
-    nsRefPtr<gfxASurface> surface;
-    AutoLockImage autoLock(mContainer, getter_AddRefs(surface));
+    RefPtr<gfx::SourceSurface> surface;
+    AutoLockImage autoLock(mContainer, &surface);
 
     mImageClientTypeContainer = autoLock.GetImage() ?
                                   BUFFER_IMAGE_SINGLE : BUFFER_UNKNOWN;
     return mImageClientTypeContainer;
   }
 
   RefPtr<ImageClient> mImageClient;
   CompositableType mImageClientTypeContainer;
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -205,18 +205,17 @@ 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 = (aFlags & ~TEXTURE_DEALLOCATE_CLIENT) |
-                               TEXTURE_DEALLOCATE_DEFERRED;
+  mTextureInfo.mTextureFlags = aFlags & ~TEXTURE_DEALLOCATE_CLIENT;
 
   if (!CreateAndAllocateTextureClient(mTextureClient, TEXTURE_ON_BLACK) ||
       !AddTextureClient(mTextureClient)) {
     AbortTextureClientCreation();
     return;
   }
 
   if (aFlags & BUFFER_COMPONENT_ALPHA) {
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -211,31 +211,31 @@ ImageClientSingle::UpdateImage(ImageCont
     mFrontBuffer = buffer;
     if (!AddTextureClient(mFrontBuffer)) {
       mFrontBuffer = nullptr;
       return false;
     }
 
     GetForwarder()->UseTexture(this, mFrontBuffer);
   } else {
-    nsRefPtr<gfxASurface> surface = image->DeprecatedGetAsSurface();
+    RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
     MOZ_ASSERT(surface);
 
-    gfx::IntSize size = gfx::IntSize(image->GetSize().width, image->GetSize().height);
+    gfx::IntSize size = image->GetSize();
 
     if (mFrontBuffer &&
         (mFrontBuffer->IsImmutable() || mFrontBuffer->GetSize() != size)) {
       GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
       mFrontBuffer = nullptr;
     }
 
     bool bufferCreated = false;
     if (!mFrontBuffer) {
       gfxImageFormat format
-        = gfxPlatform::GetPlatform()->OptimalFormatForContent(surface->GetContentType());
+        = gfxPlatform::GetPlatform()->OptimalFormatForContent(gfx::ContentForFormat(surface->GetFormat()));
       mFrontBuffer = CreateTextureClientForDrawing(gfx::ImageFormatToSurfaceFormat(format),
                                                    mTextureFlags);
       MOZ_ASSERT(mFrontBuffer->AsTextureClientDrawTarget());
       if (!mFrontBuffer->AsTextureClientDrawTarget()->AllocateForSurface(size)) {
         mFrontBuffer = nullptr;
         return false;
       }
 
@@ -244,19 +244,18 @@ ImageClientSingle::UpdateImage(ImageCont
 
     if (!mFrontBuffer->Lock(OPEN_WRITE_ONLY)) {
       return false;
     }
 
     {
       // We must not keep a reference to the DrawTarget after it has been unlocked.
       RefPtr<DrawTarget> dt = mFrontBuffer->AsTextureClientDrawTarget()->GetAsDrawTarget();
-      RefPtr<SourceSurface> source = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, surface);
-      MOZ_ASSERT(source.get());
-      dt->CopySurface(source, IntRect(IntPoint(), source->GetSize()), IntPoint());
+      MOZ_ASSERT(surface.get());
+      dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
     }
 
     mFrontBuffer->Unlock();
 
     if (bufferCreated) {
       if (!AddTextureClient(mFrontBuffer)) {
         mFrontBuffer = nullptr;
         return false;
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -239,18 +239,17 @@ TextureHost::TextureHost(TextureFlags aF
 {}
 
 TextureHost::~TextureHost()
 {
 }
 
 void TextureHost::Finalize()
 {
-  if (GetFlags() & TEXTURE_DEALLOCATE_DEFERRED) {
-    MOZ_ASSERT(!(GetFlags() & TEXTURE_DEALLOCATE_CLIENT));
+  if (!(GetFlags() & TEXTURE_DEALLOCATE_CLIENT)) {
     DeallocateSharedData();
     DeallocateDeviceData();
   }
 }
 
 void
 TextureHost::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
@@ -721,36 +720,26 @@ TextureParent::RecvRemoveTextureSync()
 
 void
 TextureParent::ActorDestroy(ActorDestroyReason why)
 {
   if (!mTextureHost) {
     return;
   }
 
-  bool isDeffered = mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED;
   switch (why) {
   case AncestorDeletion:
-    NS_WARNING("PTexture deleted after ancestor");
-    // fall-through to deletion path
   case Deletion:
-    if (!(mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) && !isDeffered) {
-      mTextureHost->DeallocateSharedData();
-    }
-    break;
-
   case NormalShutdown:
   case AbnormalShutdown:
-    mTextureHost->OnShutdown();
     break;
-
   case FailedConstructor:
     NS_RUNTIMEABORT("FailedConstructor isn't possible in PTexture");
   }
 
-  if (!isDeffered) {
+  if (mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
     mTextureHost->ForgetSharedData();
   }
   mTextureHost = nullptr;
 }
 
 } // namespace
 } // namespace
--- a/gfx/layers/d3d10/CanvasLayerD3D10.cpp
+++ b/gfx/layers/d3d10/CanvasLayerD3D10.cpp
@@ -77,35 +77,22 @@ CanvasLayerD3D10::Initialize(const Data&
 
       mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
       device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mSRView));
       return;
     } 
     
     // XXX we should store mDrawTarget and use it directly in UpdateSurface,
     // bypassing Thebes
-    mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
+    mSurface = mDrawTarget->Snapshot();
   } else {
     NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
   }
 
   mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
-
-  if (mSurface && mSurface->GetType() == gfxSurfaceType::D2D) {
-    void *data = mSurface->GetData(&gKeyD3D10Texture);
-    if (data) {
-      mTexture = static_cast<ID3D10Texture2D*>(data);
-      mIsD2DTexture = true;
-      device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mSRView));
-      mHasAlpha =
-        mSurface->GetContentType() == gfxContentType::COLOR_ALPHA;
-      return;
-    }
-  }
-
   mIsD2DTexture = false;
 
   // Create a texture in case we need to readback.
   CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mBounds.width, mBounds.height, 1, 1);
   desc.Usage = D3D10_USAGE_DYNAMIC;
   desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
 
   HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture));
@@ -122,17 +109,16 @@ CanvasLayerD3D10::UpdateSurface()
 {
   if (!IsDirty())
     return;
   Painted();
 
   if (mDrawTarget) {
     mDrawTarget->Flush();
   } else if (mIsD2DTexture) {
-    mSurface->Flush();
     return;
   }
 
   if (mGLContext) {
     SharedSurface* surf = mGLContext->RequestFrame();
     if (!surf)
         return;
 
@@ -174,41 +160,31 @@ CanvasLayerD3D10::UpdateSurface()
         mSRView = mUploadSRView;
         break;
       }
 
       default:
         MOZ_CRASH("Unhandled SharedSurfaceType.");
     }
   } else if (mSurface) {
-    RECT r;
-    r.left = 0;
-    r.top = 0;
-    r.right = mBounds.width;
-    r.bottom = mBounds.height;
-
     D3D10_MAPPED_TEXTURE2D map;
     HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map);
 
     if (FAILED(hr)) {
       NS_WARNING("Failed to lock CanvasLayer texture.");
       return;
     }
 
-    nsRefPtr<gfxImageSurface> dstSurface;
+    RefPtr<DrawTarget> destTarget =
+      Factory::CreateDrawTargetForD3D10Texture(mTexture,
+                                               SurfaceFormat::R8G8B8A8);
+    Rect r(Point(0, 0), ToRect(mBounds).Size());
+    destTarget->DrawSurface(mSurface, r, r, DrawSurfaceOptions(),
+                            DrawOptions(1.0F, CompositionOp::OP_SOURCE));
 
-    dstSurface = new gfxImageSurface((unsigned char*)map.pData,
-                                     gfxIntSize(mBounds.width, mBounds.height),
-                                     map.RowPitch,
-                                     gfxImageFormat::ARGB32);
-    nsRefPtr<gfxContext> ctx = new gfxContext(dstSurface);
-    ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
-    ctx->SetSource(mSurface);
-    ctx->Paint();
-    
     mTexture->Unmap(0);
     mSRView = mUploadSRView;
   }
 }
 
 Layer*
 CanvasLayerD3D10::GetLayer()
 {
--- a/gfx/layers/d3d10/CanvasLayerD3D10.h
+++ b/gfx/layers/d3d10/CanvasLayerD3D10.h
@@ -34,17 +34,17 @@ public:
   virtual Layer* GetLayer();
   virtual void RenderLayer();
 
 private:
   typedef mozilla::gl::GLContext GLContext;
 
   void UpdateSurface();
 
-  nsRefPtr<gfxASurface> mSurface;
+  RefPtr<gfx::SourceSurface> mSurface;
   mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
   nsRefPtr<GLContext> mGLContext;
   nsRefPtr<ID3D10Texture2D> mTexture;
   nsRefPtr<ID3D10ShaderResourceView> mUploadSRView;
   nsRefPtr<ID3D10ShaderResourceView> mSRView;
 
   bool mDataIsPremultiplied;
   bool mNeedsYFlip;
--- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -37,30 +37,29 @@ CanvasLayerD3D9::~CanvasLayerD3D9()
   if (mD3DManager) {
     mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this);
   }
 }
 
 void
 CanvasLayerD3D9::Initialize(const Data& aData)
 {
-  NS_ASSERTION(mSurface == nullptr, "BasicCanvasLayer::Initialize called twice!");
+  NS_ASSERTION(mDrawTarget == nullptr, "BasicCanvasLayer::Initialize called twice!");
 
   if (aData.mDrawTarget) {
     mDrawTarget = aData.mDrawTarget;
-    mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
     mNeedsYFlip = false;
     mDataIsPremultiplied = true;
   } else if (aData.mGLContext) {
     mGLContext = aData.mGLContext;
     NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen.");
     mDataIsPremultiplied = aData.mIsGLAlphaPremult;
     mNeedsYFlip = true;
   } else {
-    NS_ERROR("CanvasLayer created without mSurface, mGLContext or mDrawTarget?");
+    NS_ERROR("CanvasLayer created without mGLContext or mDrawTarget?");
   }
 
   mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
 
   CreateTexture();
 }
 
 void
@@ -74,97 +73,47 @@ CanvasLayerD3D9::UpdateSurface()
     CreateTexture();
 
     if (!mTexture) {
       NS_WARNING("CanvasLayerD3D9::Updated called but no texture present and creation failed!");
       return;
     }
   }
 
+  RefPtr<SourceSurface> surface;
+
   if (mGLContext) {
     SharedSurface* surf = mGLContext->RequestFrame();
     if (!surf)
         return;
 
     SharedSurface_Basic* shareSurf = SharedSurface_Basic::Cast(surf);
-
-    // WebGL reads entire surface.
-    LockTextureRectD3D9 textureLock(mTexture);
-    if (!textureLock.HasLock()) {
-      NS_WARNING("Failed to lock CanvasLayer texture.");
-      return;
-    }
+    surface = shareSurf->GetData();
+  } else {
+    surface = mDrawTarget->Snapshot();
+  }
 
-    D3DLOCKED_RECT rect = textureLock.GetLockRect();
-    
-    DataSourceSurface* frameData = shareSurf->GetData();
-    // Scope for DrawTarget, so it's destroyed early.
-    {
-      RefPtr<DrawTarget> rectDt = Factory::CreateDrawTargetForData(BackendType::CAIRO,
-                                                                   (uint8_t*)rect.pBits,
-                                                                   frameData->GetSize(),
-                                                                   rect.Pitch,
-                                                                   SurfaceFormat::B8G8R8A8);
-
-      Rect drawRect(0, 0, frameData->GetSize().width, frameData->GetSize().height);
-      rectDt->DrawSurface(frameData, drawRect, drawRect,
-                          DrawSurfaceOptions(),  DrawOptions(1.0F, CompositionOp::OP_SOURCE));
-      rectDt->Flush();
-    }
-  } else {
-    RECT r;
-    r.left = mBounds.x;
-    r.top = mBounds.y;
-    r.right = mBounds.XMost();
-    r.bottom = mBounds.YMost();
-
-    LockTextureRectD3D9 textureLock(mTexture);
-    if (!textureLock.HasLock()) {
-      NS_WARNING("Failed to lock CanvasLayer texture.");
-      return;
-    }
+  // WebGL reads entire surface.
+  LockTextureRectD3D9 textureLock(mTexture);
+  if (!textureLock.HasLock()) {
+    NS_WARNING("Failed to lock CanvasLayer texture.");
+    return;
+  }
 
-    D3DLOCKED_RECT lockedRect = textureLock.GetLockRect();
-
-    nsRefPtr<gfxImageSurface> sourceSurface;
+  D3DLOCKED_RECT rect = textureLock.GetLockRect();
+  RefPtr<DrawTarget> rectDt = Factory::CreateDrawTargetForData(BackendType::CAIRO,
+                                                               (uint8_t*)rect.pBits,
+                                                               surface->GetSize(),
+                                                               rect.Pitch,
+                                                               SurfaceFormat::B8G8R8A8);
 
-    if (mSurface->GetType() == gfxSurfaceType::Win32) {
-      sourceSurface = mSurface->GetAsImageSurface();
-    } else if (mSurface->GetType() == gfxSurfaceType::Image) {
-      sourceSurface = static_cast<gfxImageSurface*>(mSurface.get());
-      if (sourceSurface->Format() != gfxImageFormat::ARGB32 &&
-          sourceSurface->Format() != gfxImageFormat::RGB24)
-      {
-        return;
-      }
-    } else {
-      sourceSurface = new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
-                                          gfxImageFormat::ARGB32);
-      nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface);
-      ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
-      ctx->SetSource(mSurface);
-      ctx->Paint();
-    }
-
-    uint8_t *startBits = sourceSurface->Data();
-    uint32_t sourceStride = sourceSurface->Stride();
-
-    if (sourceSurface->Format() != gfxImageFormat::ARGB32) {
-      mHasAlpha = false;
-    } else {
-      mHasAlpha = true;
-    }
-
-    for (int y = 0; y < mBounds.height; y++) {
-      memcpy((uint8_t*)lockedRect.pBits + lockedRect.Pitch * y,
-             startBits + sourceStride * y,
-             mBounds.width * 4);
-    }
-
-  }
+  Rect drawRect(0, 0, surface->GetSize().width, surface->GetSize().height);
+  rectDt->DrawSurface(surface, drawRect, drawRect,
+                      DrawSurfaceOptions(),  DrawOptions(1.0F, CompositionOp::OP_SOURCE));
+  rectDt->Flush();
 }
 
 Layer*
 CanvasLayerD3D9::GetLayer()
 {
   return this;
 }
 
--- a/gfx/layers/d3d9/CanvasLayerD3D9.h
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.h
@@ -34,17 +34,16 @@ public:
 
   void CreateTexture();
 
 protected:
   typedef mozilla::gl::GLContext GLContext;
 
   void UpdateSurface();
 
-  nsRefPtr<gfxASurface> mSurface;
   nsRefPtr<GLContext> mGLContext;
   nsRefPtr<IDirect3DTexture9> mTexture;
   RefPtr<gfx::DrawTarget> mDrawTarget;
 
   bool mDataIsPremultiplied;
   bool mNeedsYFlip;
   bool mHasAlpha;
 
new file mode 100644
--- /dev/null
+++ b/gfx/layers/genTables.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+
+def table_generator(f):
+  return ",\n".join([", ".join(["0x%2.2x" % h for h in [f(i) for i in range(r,r+16)]]) for r in range(0, 65536, 16)])
+
+with open("PremultiplyTables.h", "w") as f:
+  f.write("const uint8_t PremultiplyTable[256*256] = {\n");
+  f.write(table_generator(lambda i: ((i / 256) * (i % 256) + 254) / 255) + "\n")
+  f.write("};\n");
+  f.write("const uint8_t UnpremultiplyTable[256*256] = {\n");
+  f.write(table_generator(lambda i: (i % 256) * 255 / ((i / 256) if (i / 256) > 0 else 255) % 256) + "\n")
+  f.write("};\n");
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -1700,16 +1700,22 @@ void AsyncPanZoomController::NotifyLayer
         aLayerMetrics.mScrollOffset.x, aLayerMetrics.mScrollOffset.y);
 
       mFrameMetrics.mScrollOffset = aLayerMetrics.mScrollOffset;
 
       // Once layout issues a scroll offset update, it becomes impervious to
       // scroll offset updates from APZ until we acknowledge the update it sent.
       // This prevents APZ updates from clobbering scroll updates from other
       // more "legitimate" sources like content scripts.
+      // Furthermore, any inflight paint requests we have already dispatched are
+      // going to be ignored by layout, and so mLastDispatchedPaintMetrics
+      // becomes incorrect for the purposes of calculating the LD transform. To
+      // correct this we need to update mLastDispatchedPaintMetrics to be the
+      // last thing we know was painted by Gecko.
+      mLastDispatchedPaintMetrics = aLayerMetrics;
       nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
       if (controller) {
         controller->AcknowledgeScrollUpdate(aLayerMetrics.mScrollId,
                                             aLayerMetrics.GetScrollGeneration());
       }
     }
   }
 
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -55,23 +55,23 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
             'd3d9/TextureD3D9.h',
         ]
         UNIFIED_SOURCES += [
             'd3d9/CanvasLayerD3D9.cpp',
             'd3d9/ColorLayerD3D9.cpp',
             'd3d9/ContainerLayerD3D9.cpp',
             'd3d9/ImageLayerD3D9.cpp',
             'd3d9/LayerManagerD3D9.cpp',
-            'd3d9/Nv3DVUtils.cpp',
             'd3d9/TextureD3D9.cpp',
             'd3d9/ThebesLayerD3D9.cpp',
         ]
         SOURCES += [
             'd3d9/CompositorD3D9.cpp',
             'd3d9/DeviceManagerD3D9.cpp',
+            'd3d9/Nv3DVUtils.cpp',
         ]
     if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
         EXPORTS += [
             'd3d10/LayerManagerD3D10.h',
             'd3d10/ReadbackManagerD3D10.h',
         ]
         EXPORTS.mozilla.layers += [
             'd3d11/CompositorD3D11.h',
@@ -256,16 +256,17 @@ UNIFIED_SOURCES += [
     'ipc/ShadowLayerParent.cpp',
     'ipc/ShadowLayers.cpp',
     'ipc/SharedPlanarYCbCrImage.cpp',
     'ipc/SharedRGBImage.cpp',
     'ipc/TaskThrottler.cpp',
     'LayerScope.cpp',
     'LayersLogging.cpp',
     'LayerSorter.cpp',
+    'LayerUtils.cpp',
     'opengl/CompositingRenderTargetOGL.cpp',
     'opengl/CompositorOGL.cpp',
     'opengl/OGLShaderProgram.cpp',
     'opengl/TextureClientOGL.cpp',
     'opengl/TextureHostOGL.cpp',
     'opengl/TexturePoolOGL.cpp',
     'ReadbackProcessor.cpp',
     'RenderTrace.cpp',
@@ -319,8 +320,12 @@ LOCAL_INCLUDES += [
     '/dom/events',
 ]
 
 if CONFIG['MOZ_DEBUG']:
     DEFINES['D3D_DEBUG_INFO'] = True
 
 if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
     DEFINES['MOZ_ENABLE_D3D10_LAYER'] = True
+
+GENERATED_FILES = [
+    'PremultiplyTables.h',
+]
--- a/gfx/src/nsScriptableRegion.cpp
+++ b/gfx/src/nsScriptableRegion.cpp
@@ -131,17 +131,17 @@ NS_IMETHODIMP nsScriptableRegion::GetRec
 {
   uint32_t numRects = mRegion.GetNumRects();
 
   if (!numRects) {
     aRects.setNull();
     return NS_OK;
   }
 
-  JS::Rooted<JSObject*> destArray(aCx, JS_NewArrayObject(aCx, numRects * 4, nullptr));
+  JS::Rooted<JSObject*> destArray(aCx, JS_NewArrayObject(aCx, numRects * 4));
   if (!destArray) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   aRects.setObject(*destArray);
 
   uint32_t n = 0;
   nsIntRegionRectIterator iter(mRegion);
--- a/gfx/thebes/Makefile.in
+++ b/gfx/thebes/Makefile.in
@@ -36,10 +36,10 @@ ifdef GNU_CC
 gfxAlphaRecoverySSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
 endif
 
 ifdef SOLARIS_SUNPRO_CXX
 gfxAlphaRecoverySSE2.$(OBJ_SUFFIX): OS_CXXFLAGS += -xarch=sse2 -xO4
 endif
 endif
 
-PremultiplyTables.h: $(srcdir)/genTables.py
+DeprecatedPremultiplyTables.h: $(srcdir)/genTables.py
 	$(PYTHON) $(srcdir)/genTables.py
--- a/gfx/thebes/genTables.py
+++ b/gfx/thebes/genTables.py
@@ -1,12 +1,12 @@
 #!/usr/bin/python
 
 def table_generator(f):
     return ",\n".join([", ".join(["0x%2.2x" % h for h in [f(i) for i in range(r,r+16)]]) for r in range(0, 65536, 16)])
 
-with open("PremultiplyTables.h", "w") as f:
+with open("DeprecatedPremultiplyTables.h", "w") as f:
   f.write("const uint8_t gfxUtils::sPremultiplyTable[256*256] = {\n");
   f.write(table_generator(lambda i: ((i / 256) * (i % 256) + 254) / 255) + "\n")
   f.write("};\n");
   f.write("const uint8_t gfxUtils::sUnpremultiplyTable[256*256] = {\n");
   f.write(table_generator(lambda i: (i % 256) * 255 / ((i / 256) if (i / 256) > 0 else 255) % 256) + "\n")
   f.write("};\n");
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -17,17 +17,17 @@
 #ifdef XP_WIN
 #include "gfxWindowsPlatform.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::layers;
 using namespace mozilla::gfx;
 
-#include "PremultiplyTables.h"
+#include "DeprecatedPremultiplyTables.h"
 
 static const uint8_t PremultiplyValue(uint8_t a, uint8_t v) {
     return gfxUtils::sPremultiplyTable[a*256+v];
 }
 
 static const uint8_t UnpremultiplyValue(uint8_t a, uint8_t v) {
     return gfxUtils::sUnpremultiplyTable[a*256+v];
 }
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -623,17 +623,17 @@ gfxWindowsPlatform::VerifyD2DDevice(bool
 gfxPlatformFontList*
 gfxWindowsPlatform::CreatePlatformFontList()
 {
     mUsingGDIFonts = false;
     gfxPlatformFontList *pfl;
 #ifdef CAIRO_HAS_DWRITE_FONT
     // bug 630201 - older pre-RTM versions of Direct2D/DirectWrite cause odd
     // crashers so blacklist them altogether
-    if (IsWin7RTMOrLater() && GetDWriteFactory()) {
+    if (IsNotWin7PreRTM() && GetDWriteFactory()) {
         pfl = new gfxDWriteFontList();
         if (NS_SUCCEEDED(pfl->InitFontList())) {
             return pfl;
         }
         // DWrite font initialization failed! Don't know why this would happen,
         // but apparently it can - see bug 594865.
         // So we're going to fall back to GDI fonts & rendering.
         gfxPlatformFontList::Shutdown();
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -263,17 +263,17 @@ MSVC_ENABLE_PGO = True
 
 LIBRARY_NAME = 'thebes'
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 GENERATED_FILES = [
-    'PremultiplyTables.h',
+    'DeprecatedPremultiplyTables.h',
 ]
 
 LOCAL_INCLUDES += [
     '/content/xml/document/src',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'qt'):
     DEFINES['MOZ_ENABLE_FREETYPE'] = True
new file mode 100644
--- /dev/null
+++ b/ipc/chromium/src/third_party/libevent-use-non-deprecated-syscalls.patch
@@ -0,0 +1,43 @@
+---
+ ipc/chromium/src/third_party/libevent/epoll_sub.c |   13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- mozilla-central.orig/ipc/chromium/src/third_party/libevent/epoll_sub.c
++++ mozilla-central/ipc/chromium/src/third_party/libevent/epoll_sub.c
+@@ -29,15 +29,24 @@
+ #include <sys/param.h>
+ #include <sys/types.h>
+ #include <sys/syscall.h>
+ #include <sys/epoll.h>
+ #include <unistd.h>
++#include <errno.h>
+
+ int
+ epoll_create(int size)
+ {
++#if !defined(__NR_epoll_create) && defined(__NR_epoll_create1)
++	if (size <= 0) {
++		errno = EINVAL;
++		return -1;
++	}
++	return (syscall(__NR_epoll_create1, 0));
++#else
+ 	return (syscall(__NR_epoll_create, size));
++#endif
+ }
+
+ int
+ epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
+ {
+@@ -46,7 +55,11 @@ epoll_ctl(int epfd, int op, int fd, stru
+ }
+
+ int
+ epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
+ {
++#if !defined(__NR_epoll_wait) && defined(__NR_epoll_pwait)
++	return (syscall(__NR_epoll_pwait, epfd, events, maxevents, timeout, NULL, 0));
++#else
+ 	return (syscall(__NR_epoll_wait, epfd, events, maxevents, timeout));
++#endif
+ }
--- a/ipc/chromium/src/third_party/libevent/README.mozilla
+++ b/ipc/chromium/src/third_party/libevent/README.mozilla
@@ -8,8 +8,10 @@ android/event2/event-config.h
 
 These files are taken from libevent-2.0.21-stable built on the development environment indicated by the first path component. You have to run "./configure" and "make" to get all of the pre-processing done. The file can then be found in "include/event2/".
 
 2. This is ugly, prepare yourself. OS X has a weird problem with how the "TAILQ_END(head)" is used, causing a linking error. Just replace all use of the "TAILQ_END(head)" macro with "NULL".
 
 3. Apply "add mac-arc4random-buf.patch", which removes some bad OS X compatibility code. This will allow libevent to compile on all supported versions of OS X.
 
 4. Apply "openbsd-no-arc4random_addrandom.patch", which fixes the build on OpenBSD (which doesnt provide arc4random_addrandom anymore, see #931354)
+
+5. Apply "libevent-use-non-deprecated-syscalls.patch", which fixes the build on AArch64 architecture (which does not provide deprecated syscalls)
--- a/ipc/chromium/src/third_party/libevent/epoll_sub.c
+++ b/ipc/chromium/src/third_party/libevent/epoll_sub.c
@@ -26,27 +26,40 @@
  */
 #include <stdint.h>
 
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/syscall.h>
 #include <sys/epoll.h>
 #include <unistd.h>
+#include <errno.h>
 
 int
 epoll_create(int size)
 {
+#if !defined(__NR_epoll_create) && defined(__NR_epoll_create1)
+	if (size <= 0) {
+		errno = EINVAL;
+		return -1;
+	}
+	return (syscall(__NR_epoll_create1, 0));
+#else
 	return (syscall(__NR_epoll_create, size));
+#endif
 }
 
 int
 epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
 {
 
 	return (syscall(__NR_epoll_ctl, epfd, op, fd, event));
 }
 
 int
 epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
 {
+#if !defined(__NR_epoll_wait) && defined(__NR_epoll_pwait)
+	return (syscall(__NR_epoll_pwait, epfd, events, maxevents, timeout, NULL, 0));
+#else
 	return (syscall(__NR_epoll_wait, epfd, events, maxevents, timeout));
+#endif
 }
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -133,17 +133,16 @@ class Float32x4Defn {
     static const JSFunctionSpec TypeDescriptorMethods[];
     static const JSPropertySpec TypedDatumProperties[];
     static const JSFunctionSpec TypedDatumMethods[];
 };
 } // namespace js
 
 const JSFunctionSpec js::Float32x4Defn::TypeDescriptorMethods[] = {
     JS_SELF_HOSTED_FN("toSource", "DescrToSourceMethod", 0, 0),
-    JS_SELF_HOSTED_FN("handle", "HandleCreate", 2, 0),
     JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, 0),
     JS_SELF_HOSTED_FN("equivalent", "TypeDescrEquivalent", 1, 0),
     JS_FS_END
 };
 
 const JSPropertySpec js::Float32x4Defn::TypedDatumProperties[] = {
     JS_PSG("x", Float32x4Lane0, JSPROP_PERMANENT),
     JS_PSG("y", Float32x4Lane1, JSPROP_PERMANENT),
@@ -155,17 +154,16 @@ const JSPropertySpec js::Float32x4Defn::
 
 const JSFunctionSpec js::Float32x4Defn::TypedDatumMethods[] = {
     JS_SELF_HOSTED_FN("toSource", "X4ToSource", 0, 0),
     JS_FS_END
 };
 
 const JSFunctionSpec js::Int32x4Defn::TypeDescriptorMethods[] = {
     JS_SELF_HOSTED_FN("toSource", "DescrToSourceMethod", 0, 0),
-    JS_SELF_HOSTED_FN("handle", "HandleCreate", 2, 0),
     JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, 0),
     JS_SELF_HOSTED_FN("equivalent", "TypeDescrEquivalent", 1, 0),
     JS_FS_END,
 };
 
 const JSPropertySpec js::Int32x4Defn::TypedDatumProperties[] = {
     JS_PSG("x", Int32x4Lane0, JSPROP_PERMANENT),
     JS_PSG("y", Int32x4Lane1, JSPROP_PERMANENT),
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -211,17 +211,16 @@ const Class js::ScalarTypeDescr::class_ 
     ScalarTypeDescr::call,
     nullptr,
     nullptr,
     nullptr
 };
 
 const JSFunctionSpec js::ScalarTypeDescr::typeObjectMethods[] = {
     JS_SELF_HOSTED_FN("toSource", "DescrToSourceMethod", 0, 0),
-    {"handle", {nullptr, nullptr}, 2, 0, "HandleCreate"},
     {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
     {"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
     JS_FS_END
 };
 
 static size_t ScalarSizes[] = {
 #define SCALAR_SIZE(_kind, _type, _name)                        \
     sizeof(_type),
@@ -312,17 +311,16 @@ const Class js::ReferenceTypeDescr::clas
     ReferenceTypeDescr::call,
     nullptr,
     nullptr,
     nullptr
 };
 
 const JSFunctionSpec js::ReferenceTypeDescr::typeObjectMethods[] = {
     JS_SELF_HOSTED_FN("toSource", "DescrToSourceMethod", 0, 0),
-    {"handle", {nullptr, nullptr}, 2, 0, "HandleCreate"},
     {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
     {"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
     JS_FS_END
 };
 
 /*static*/ const char *
 ReferenceTypeDescr::typeName(Type type)
 {
@@ -462,17 +460,16 @@ const Class SizedArrayTypeDescr::class_ 
     nullptr
 };
 
 const JSPropertySpec ArrayMetaTypeDescr::typeObjectProperties[] = {
     JS_PS_END
 };
 
 const JSFunctionSpec ArrayMetaTypeDescr::typeObjectMethods[] = {
-    {"handle", {nullptr, nullptr}, 2, 0, "HandleCreate"},
     {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
     JS_FN("dimension", UnsizedArrayTypeDescr::dimension, 1, 0),
     JS_SELF_HOSTED_FN("toSource", "DescrToSourceMethod", 0, 0),
     {"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
     JS_SELF_HOSTED_FN("build",    "TypedObjectArrayTypeBuild", 3, 0),
     JS_SELF_HOSTED_FN("buildPar", "TypedObjectArrayTypeBuildPar", 3, 0),
     JS_SELF_HOSTED_FN("from",     "TypedObjectArrayTypeFrom", 3, 0),
     JS_SELF_HOSTED_FN("fromPar",  "TypedObjectArrayTypeFromPar", 3, 0),
@@ -751,17 +748,16 @@ const Class StructTypeDescr::class_ = {
     nullptr  /* trace */
 };
 
 const JSPropertySpec StructMetaTypeDescr::typeObjectProperties[] = {
     JS_PS_END
 };
 
 const JSFunctionSpec StructMetaTypeDescr::typeObjectMethods[] = {
-    {"handle", {nullptr, nullptr}, 2, 0, "HandleCreate"},
     {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
     JS_SELF_HOSTED_FN("toSource", "DescrToSourceMethod", 0, 0),
     {"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
     JS_FS_END
 };
 
 const JSPropertySpec StructMetaTypeDescr::typedObjectProperties[] = {
     JS_PS_END
@@ -1245,34 +1241,16 @@ GlobalObject::initTypedObjectModule(JSCo
 
     RootedValue structTypeValue(cx, ObjectValue(*structType));
     if (!JSObject::defineProperty(cx, module, cx->names().StructType,
                                   structTypeValue,
                                   nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
         return nullptr;
 
-    //  Handle
-
-    RootedObject handle(cx, NewBuiltinClassInstance(cx, &JSObject::class_));
-    if (!module)
-        return nullptr;
-
-    if (!JS_DefineFunctions(cx, handle, TypedHandle::handleStaticMethods))
-        return nullptr;
-
-    RootedValue handleValue(cx, ObjectValue(*handle));
-    if (!JSObject::defineProperty(cx, module, cx->names().Handle,
-                                  handleValue,
-                                  nullptr, nullptr,
-                                  JSPROP_READONLY | JSPROP_PERMANENT))
-    {
-        return nullptr;
-    }
-
     // Everything is setup, install module on the global object:
     RootedValue moduleValue(cx, ObjectValue(*module));
     global->setConstructor(JSProto_TypedObject, moduleValue);
     if (!JSObject::defineProperty(cx, global, cx->names().TypedObject,
                                   moduleValue,
                                   nullptr, nullptr,
                                   0))
     {
--- a/js/src/builtin/TypedObject.js
+++ b/js/src/builtin/TypedObject.js
@@ -176,16 +176,22 @@ TypedObjectPointer.prototype.copy = func
 
 TypedObjectPointer.prototype.reset = function(inPtr) {
   this.descr = inPtr.descr;
   this.datum = inPtr.datum;
   this.offset = inPtr.offset;
   return this;
 };
 
+TypedObjectPointer.prototype.bump = function(size) {
+  assert(TO_INT32(this.offset) === this.offset, "current offset not int");
+  assert(TO_INT32(size) === size, "size not int");
+  this.offset += size;
+}
+
 TypedObjectPointer.prototype.kind = function() {
   return DESCR_KIND(this.descr);
 }
 
 // Extract the length. This does a switch on kind, so it's
 // best if we can avoid it.
 TypedObjectPointer.prototype.length = function() {
   switch (this.kind()) {
@@ -307,45 +313,48 @@ TypedObjectPointer.prototype.moveToField
 //
 // The methods in this section read from the memory pointed at
 // by `this` and produce JS values. This process is called *reification*
 // in the spec.
 
 // Reifies the value referenced by the pointer, meaning that it
 // returns a new object pointing at the value. If the value is
 // a scalar, it will return a JS number, but otherwise the reified
-// result will be a typed object or handle, depending on the type
-// of the ptr's datum.
+// result will be a datum of the same class as the ptr's datum.
 TypedObjectPointer.prototype.get = function() {
   assert(ObjectIsAttached(this.datum), "get() called with unattached datum");
 
   switch (this.kind()) {
   case JS_TYPEREPR_SCALAR_KIND:
     return this.getScalar();
 
   case JS_TYPEREPR_REFERENCE_KIND:
     return this.getReference();
 
   case JS_TYPEREPR_X4_KIND:
     return this.getX4();
 
   case JS_TYPEREPR_SIZED_ARRAY_KIND:
-    return NewDerivedTypedDatum(this.descr, this.datum, this.offset);
-
   case JS_TYPEREPR_STRUCT_KIND:
-    return NewDerivedTypedDatum(this.descr, this.datum, this.offset);
+    return this.getDerived();
 
   case JS_TYPEREPR_UNSIZED_ARRAY_KIND:
     assert(false, "Unhandled repr kind: " + this.kind());
   }
 
   assert(false, "Unhandled kind: " + this.kind());
   return undefined;
 }
 
+TypedObjectPointer.prototype.getDerived = function() {
+  assert(!TypeDescrIsSimpleType(this.descr),
+         "getDerived() used with simple type");
+  return NewDerivedTypedDatum(this.descr, this.datum, this.offset);
+}
+
 TypedObjectPointer.prototype.getScalar = function() {
   var type = DESCR_TYPE(this.descr);
   switch (type) {
   case JS_SCALARTYPEREPR_INT8:
     return Load_int8(this.datum, this.offset);
 
   case JS_SCALARTYPEREPR_UINT8:
   case JS_SCALARTYPEREPR_UINT8_CLAMPED:
@@ -722,109 +731,16 @@ function TypedArrayRedimension(newArrayT
   assert(DESCR_SIZE(oldArrayType) == DESCR_SIZE(newArrayType),
          "Byte sizes should be equal");
 
   // Rewrap the data from `this` in a new type.
   return NewDerivedTypedDatum(newArrayType, this, 0);
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// Handles
-//
-// Note: these methods are directly invokable by users and so must be
-// defensive.
-
-// This is the `handle([obj, [...path]])` method on type objects.
-// User exposed!
-//
-// FIXME bug 929656 -- label algorithms with steps from the spec
-function HandleCreate(obj, ...path) {
-  if (!IsObject(this) || !ObjectIsTypeDescr(this))
-    ThrowError(JSMSG_INCOMPATIBLE_PROTO, "Type", "handle", "value");
-
-  switch (DESCR_KIND(this)) {
-  case JS_TYPEREPR_SCALAR_KIND:
-  case JS_TYPEREPR_REFERENCE_KIND:
-  case JS_TYPEREPR_X4_KIND:
-  case JS_TYPEREPR_SIZED_ARRAY_KIND:
-  case JS_TYPEREPR_STRUCT_KIND:
-    break;
-
-  case JS_TYPEREPR_UNSIZED_ARRAY_KIND:
-    ThrowError(JSMSG_TYPEDOBJECT_HANDLE_TO_UNSIZED);
-  }
-
-  var handle = NewTypedHandle(this);
-
-  if (obj !== undefined)
-    HandleMoveInternal(handle, obj, path);
-
-  return handle;
-}
-
-// Handle.move: user exposed!
-// FIXME bug 929656 -- label algorithms with steps from the spec
-function HandleMove(handle, obj, ...path) {
-  if (!IsObject(handle) || !ObjectIsTypedHandle(handle))
-    ThrowError(JSMSG_INCOMPATIBLE_PROTO, "Handle", "set", typeof value);
-
-  HandleMoveInternal(handle, obj, path);
-}
-
-function HandleMoveInternal(handle, obj, path) {
-  assert(IsObject(handle) && ObjectIsTypedHandle(handle),
-         "HandleMoveInternal: not typed handle");
-
-  if (!IsObject(obj) || !ObjectIsTypedDatum(obj))
-    ThrowError(JSMSG_INCOMPATIBLE_PROTO, "Handle", "set", "value");
-
-  var ptr = TypedObjectPointer.fromTypedDatum(obj);
-  for (var i = 0; i < path.length; i++)
-    ptr.moveTo(path[i]);
-
-  // Check that the new destination is equivalent to the handle type.
-  if (DESCR_TYPE_REPR(ptr.descr) !== DATUM_TYPE_REPR(handle))
-    ThrowError(JSMSG_TYPEDOBJECT_HANDLE_BAD_TYPE);
-
-  AttachHandle(handle, ptr.datum, ptr.offset)
-}
-
-// Handle.get: user exposed!
-// FIXME bug 929656 -- label algorithms with steps from the spec
-function HandleGet(handle) {
-  if (!IsObject(handle) || !ObjectIsTypedHandle(handle))
-    ThrowError(JSMSG_INCOMPATIBLE_PROTO, "Handle", "set", typeof value);
-
-  if (!ObjectIsAttached(handle))
-    ThrowError(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED);
-
-  var ptr = TypedObjectPointer.fromTypedDatum(handle);
-  return ptr.get();
-}
-
-// Handle.set: user exposed!
-// FIXME bug 929656 -- label algorithms with steps from the spec
-function HandleSet(handle, value) {
-  if (!IsObject(handle) || !ObjectIsTypedHandle(handle))
-    ThrowError(JSMSG_INCOMPATIBLE_PROTO, "Handle", "set", typeof value);
-
-  if (!ObjectIsAttached(handle))
-    ThrowError(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED);
-
-  var ptr = TypedObjectPointer.fromTypedDatum(handle);
-  ptr.set(value);
-}
-
-// Handle.isHandle: user exposed!
-// FIXME bug 929656 -- label algorithms with steps from the spec
-function HandleTest(obj) {
-  return IsObject(obj) && ObjectIsTypedHandle(obj);
-}
-
-///////////////////////////////////////////////////////////////////////////
 // X4
 
 function X4ProtoString(type) {
   switch (type) {
   case JS_X4TYPEREPR_INT32:
     return "int32x4";
   case JS_X4TYPEREPR_FLOAT32:
     return "float32x4";
@@ -948,17 +864,16 @@ function TypedObjectArrayTypeFrom(a, b, 
 
   var untypedInput = !IsObject(a) || !ObjectIsTypedDatum(a);
 
   // for untyped input array, the expectation (in terms of error
   // reporting for invalid parameters) is no-depth, despite
   // supporting an explicit depth of 1; while for typed input array,
   // the expectation is explicit depth.
 
-
   if (untypedInput) {
     var explicitDepth = (b === 1);
     if (explicitDepth && IsCallable(c))
       return MapUntypedSeqImpl(a, this, c);
     else if (IsCallable(b))
       return MapUntypedSeqImpl(a, this, b);
     else
       return ThrowError(JSMSG_TYPEDOBJECT_HANDLE_BAD_ARGS, "2", "function");
@@ -1163,35 +1078,35 @@ function BuildTypedSeqImpl(arrayType, le
   // Create a zeroed instance with no data
   var result = arrayType.variable ? new arrayType(len) : new arrayType();
 
   var indices = NewDenseArray(depth);
   for (var i = 0; i < depth; i++) {
     indices[i] = 0;
   }
 
-  var handle = callFunction(HandleCreate, grainType);
-  var offset = 0;
+  var grainTypeIsSimple = TypeDescrIsSimpleType(grainType);
+  var size = DESCR_SIZE(grainType);
+  var outPointer = new TypedObjectPointer(grainType, result, 0);
   for (i = 0; i < totalLength; i++) {
-    // Position handle to point at &result[...indices]
-    AttachHandle(handle, result, offset);
+    // Position out-pointer to point at &result[...indices], if appropriate.
+    var userOutPointer = (grainTypeIsSimple
+                          ? undefined
+                          : outPointer.getDerived());
 
-    // Invoke func(...indices, out)
-    callFunction(std_Array_push, indices, handle);
-    var r = callFunction(std_Function_apply, func, void 0, indices);
+    // Invoke func(...indices, userOutPointer) and store the result
+    callFunction(std_Array_push, indices, userOutPointer);
+    var r = callFunction(std_Function_apply, func, undefined, indices);
     callFunction(std_Array_pop, indices);
+    if (r !== undefined)
+      outPointer.set(r); // result[...indices] = r;
 
-    if (r !== undefined) {
-      // result[...indices] = r;
-      AttachHandle(handle, result, offset); // (func might have moved handle)
-      HandleSet(handle, r);                 // *handle = r
-    }
     // Increment indices.
-    offset += DESCR_SIZE(grainType);
     IncrementIterationSpace(indices, iterationSpace);
+    outPointer.bump(size);
   }
 
   return result;
 }
 
 function ComputeIterationSpace(arrayType, depth, len) {
   assert(IsObject(arrayType) && ObjectIsTypeDescr(arrayType), "ComputeIterationSpace called on non-type-object");
   assert(TypeDescrIsArrayType(arrayType), "ComputeIterationSpace called on non-array-type");
@@ -1256,45 +1171,42 @@ function MapUntypedSeqImpl(inArray, outp
   // is trivially compatible with any iteration space of depth 1.
 
   var outLength = outputType.variable ? inArray.length : outputType.length;
   var outGrainType = outputType.elementType;
 
   // Create a zeroed instance with no data
   var result = outputType.variable ? new outputType(inArray.length) : new outputType();
 
-  var outHandle = callFunction(HandleCreate, outGrainType);
   var outUnitSize = DESCR_SIZE(outGrainType);
+  var outGrainTypeIsSimple = TypeDescrIsSimpleType(outGrainType);
+  var outPointer = new TypedObjectPointer(outGrainType, result, 0);
 
   // Core of map computation starts here (comparable to
   // DoMapTypedSeqDepth1 and DoMapTypedSeqDepthN below).
 
-  var offset = 0;
   for (var i = 0; i < outLength; i++) {
     // In this loop, since depth is 1, "indices" denotes singleton array [i].
 
-    // Adjust handle to point at &array[...indices] for result array.
-    AttachHandle(outHandle, result, offset);
-
     if (i in inArray) { // Check for holes (only needed for untyped case).
-
-      // Extract element value (no input handles for untyped case).
+      // Extract element value.
       var element = inArray[i];
 
-      // Invoke: var r = func(element, ...indices, collection, out);
-      var r = func(element, i, inArray, outHandle);
+      // Create out pointer to point at &array[...indices] for result array.
+      var out = (outGrainTypeIsSimple ? undefined : outPointer.getDerived());
 
-      if (r !== undefined) {
-        AttachHandle(outHandle, result, offset); // (func could move handle)
-        HandleSet(outHandle, r); // *handle = r; (i.e. result[i] = r).
-      }
+      // Invoke: var r = func(element, ...indices, collection, out);
+      var r = func(element, i, inArray, out);
+
+      if (r !== undefined)
+        outPointer.set(r); // result[i] = r
     }
 
     // Update offset and (implicitly) increment indices.
-    offset += outUnitSize;
+    outPointer.bump(outUnitSize);
   }
 
   return result;
 }
 
 // Implements |map| and |from| methods for typed |inArray|.
 function MapTypedSeqImpl(inArray, depth, outputType, func) {
   assert(IsObject(outputType) && ObjectIsTypeDescr(outputType), "2. Map/From called on non-type-object outputType");
@@ -1315,82 +1227,67 @@ function MapTypedSeqImpl(inArray, depth,
   for (var i = 0; i < depth; i++)
     if (inIterationSpace[i] !== iterationSpace[i])
       // TypeError("Incompatible iteration space in input and output type");
       ThrowError(JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS);
 
   // Create a zeroed instance with no data
   var result = outputType.variable ? new outputType(inArray.length) : new outputType();
 
-  var inHandle = callFunction(HandleCreate, inGrainType);
-  var outHandle = callFunction(HandleCreate, outGrainType);
+  var inGrainTypeIsSimple = TypeDescrIsSimpleType(inGrainType);
+  var outGrainTypeIsSimple = TypeDescrIsSimpleType(outGrainType);
+
+  var inPointer = new TypedObjectPointer(inGrainType, inArray, 0);
+  var outPointer = new TypedObjectPointer(outGrainType, result, 0);
+
   var inUnitSize = DESCR_SIZE(inGrainType);
   var outUnitSize = DESCR_SIZE(outGrainType);
 
-  var inGrainTypeIsSimple = TypeDescrIsSimpleType(inGrainType);
-
   // Bug 956914: add additional variants for depth = 2, 3, etc.
 
   function DoMapTypedSeqDepth1() {
-    var inOffset = 0;
-    var outOffset = 0;
-
     for (var i = 0; i < totalLength; i++) {
       // In this loop, since depth is 1, "indices" denotes singleton array [i].
 
-      // Adjust handles to point at &array[...indices] for in and out array.
-      AttachHandle(inHandle, inArray, inOffset);
-      AttachHandle(outHandle, result, outOffset);
-
-      // Extract element value if simple; if not, handle acts as array element.
-      var element = (inGrainTypeIsSimple ? HandleGet(inHandle) : inHandle);
+      // Prepare input element/handle and out pointer
+      var element = inPointer.get();
+      var out = (outGrainTypeIsSimple ? undefined : outPointer.getDerived());
 
       // Invoke: var r = func(element, ...indices, collection, out);
-      var r = func(element, i, inArray, outHandle);
-
-      if (r !== undefined) {
-        AttachHandle(outHandle, result, outOffset); // (func could move handle)
-        HandleSet(outHandle, r); // *handle = r; (i.e. result[i] = r).
-      }
+      var r = func(element, i, inArray, out);
+      if (r !== undefined)
+        outPointer.set(r); // result[i] = r
 
       // Update offsets and (implicitly) increment indices.
-      inOffset += inUnitSize;
-      outOffset += outUnitSize;
+      inPointer.bump(inUnitSize);
+      outPointer.bump(outUnitSize);
     }
 
     return result;
   }
 
   function DoMapTypedSeqDepthN() {
     var indices = new Uint32Array(depth);
 
-    var inOffset = 0;
-    var outOffset = 0;
     for (var i = 0; i < totalLength; i++) {
-      // Adjust handles to point at &array[...indices] for in and out array.
-      AttachHandle(inHandle, inArray, inOffset);
-      AttachHandle(outHandle, result, outOffset);
-
-      // Extract element value if simple; if not, handle acts as array element.
-      var element = (inGrainTypeIsSimple ? HandleGet(inHandle) : inHandle);
+      // Prepare input element and out pointer
+      var element = inPointer.get();
+      var out = (outGrainTypeIsSimple ? undefined : outPointer.getDerived());
 
       // Invoke: var r = func(element, ...indices, collection, out);
       var args = [element];
       callFunction(std_Function_apply, std_Array_push, args, indices);
-      callFunction(std_Array_push, args, inArray, outHandle);
+      callFunction(std_Array_push, args, inArray, out);
       var r = callFunction(std_Function_apply, func, void 0, args);
-
-      if (r !== undefined) {
-        AttachHandle(outHandle, result, outOffset); // (func could move handle)
-        HandleSet(outHandle, r);                    // *handle = r
-      }
+      if (r !== undefined)
+        outPointer.set(r); // result[...indices] = r
 
       // Update offsets and explicitly increment indices.
-      inOffset += inUnitSize;
-      outOffset += outUnitSize;
+      inPointer.bump(inUnitSize);
+      outPointer.bump(outUnitSize);
       IncrementIterationSpace(indices, iterationSpace);
     }
 
     return result;
   }
 
   if  (depth == 1) {
     return DoMapTypedSeqDepth1();
@@ -1476,24 +1373,25 @@ function FilterTypedSeqImpl(array, func)
   assert(typeof func === "function", "Filter called with non-function predicate");
 
   var arrayType = TypeOfTypedDatum(array);
   if (!TypeDescrIsArrayType(arrayType))
     ThrowError(JSMSG_TYPEDOBJECT_HANDLE_BAD_ARGS, "this", "typed array");
 
   var elementType = arrayType.elementType;
   var flags = new Uint8Array(NUM_BYTES(array.length));
-  var handle = callFunction(HandleCreate, elementType);
   var count = 0;
+  var size = DESCR_SIZE(elementType);
+  var inPointer = new TypedObjectPointer(elementType, array, 0);
   for (var i = 0; i < array.length; i++) {
-    HandleMove(handle, array, i);
-    if (func(HandleGet(handle), i, array)) {
+    if (func(inPointer.get(), i, array)) {
       SET_BIT(flags, i);
       count++;
     }
+    inPointer.bump(size);
   }
 
   var resultType = (arrayType.variable ? arrayType : arrayType.unsized);
   var result = new resultType(count);
   for (var i = 0, j = 0; i < array.length; i++) {
     if (GET_BIT(flags, i))
       result[j++] = array[i];
   }
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -821,16 +821,34 @@ mingw*)
     HOST_OS_ARCH=WINNT
     ;;
 darwin*)
     HOST_OS_ARCH=Darwin
     ;;
 linux*)
     HOST_OS_ARCH=Linux
     ;;
+kfreebsd*-gnu)
+    HOST_OS_ARCH=GNU_kFreeBSD
+    ;;
+gnu*)
+    HOST_OS_ARCH=GNU
+    ;;
+dragonfly*)
+    HOST_OS_ARCH=DragonFly
+    ;;
+freebsd*)
+    HOST_OS_ARCH=FreeBSD
+    ;;
+netbsd*)
+    HOST_OS_ARCH=NetBSD
+    ;;
+openbsd*)
+    HOST_OS_ARCH=OpenBSD
+    ;;
 solaris*)
     HOST_OS_ARCH=SunOS
     SOLARIS_SUNPRO_CC=
     SOLARIS_SUNPRO_CXX=
     if test -z "$GNU_CC"; then
         if test "`$CC -V 2>&1 | egrep -c 'Sun.*C '`" != "0"; then
             SOLARIS_SUNPRO_CC=1
        fi
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -5133,17 +5133,17 @@ StructType::BuildFieldsArray(JSContext* 
   for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
     const FieldInfoHash::Entry& entry = r.front();
     // Add the field descriptor to the array.
     if (!AddFieldToArray(cx, &fieldsVec[entry.value().mIndex],
                          entry.key(), entry.value().mType))
       return nullptr;
   }
 
-  RootedObject fieldsProp(cx, JS_NewArrayObject(cx, len, fieldsVec.begin()));
+  RootedObject fieldsProp(cx, JS_NewArrayObject(cx, fieldsVec));
   if (!fieldsProp)
     return nullptr;
 
   // Seal the fields array.
   if (!JS_FreezeObject(cx, fieldsProp))
     return nullptr;
 
   return fieldsProp;
@@ -5941,17 +5941,17 @@ FunctionType::ArgTypesGetter(JSContext* 
   {
       JS::AutoValueVector vec(cx);
       if (!vec.resize(len))
         return false;
 
       for (size_t i = 0; i < len; ++i)
         vec[i] = JS::ObjectValue(*fninfo->mArgTypes[i]);
 
-      argTypes = JS_NewArrayObject(cx, len, vec.begin());
+      argTypes = JS_NewArrayObject(cx, vec);
       if (!argTypes)
         return false;
   }
 
   // Seal and cache it.
   if (!JS_FreezeObject(cx, argTypes))
     return false;
   JS_SetReservedSlot(obj, SLOT_ARGS_T, JS::ObjectValue(*argTypes));
--- a/js/src/gdb/tests/test-Root.cpp
+++ b/js/src/gdb/tests/test-Root.cpp
@@ -20,15 +20,15 @@ void callee(JS::Handle<JSObject *> obj, 
 FRAGMENT(Root, handle) {
   JS::Rooted<JSObject *> global(cx, JS::CurrentGlobalOrNull(cx));
   callee(global, &global);
   (void) global;
 }
 
 FRAGMENT(Root, HeapSlot) {
   JS::Rooted<jsval> plinth(cx, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, "plinth")));
-  JS::Rooted<JSObject *> array(cx, JS_NewArrayObject(cx, 1, plinth.address()));
+  JS::Rooted<JSObject *> array(cx, JS_NewArrayObject(cx, plinth));
 
   breakpoint();
 
   (void) plinth;
   (void) array;
 }
deleted file mode 100644
--- a/js/src/jit-test/tests/TypedObject/gcunattachedhandle.js
+++ /dev/null
@@ -1,13 +0,0 @@
-// Test that we can trace a unattached handle.
-
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
-if (!this.hasOwnProperty("TypedObject"))
-  quit();
-
-var Object = TypedObject.Object;
-var handle0 = Object.handle();
-gc();
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1921,17 +1921,16 @@ ICCompare_Fallback::Compiler::generateSt
     masm.pushValue(R0);
     masm.pushValue(R1);
 
     // Push arguments.
     masm.pushValue(R1);
     masm.pushValue(R0);
     masm.push(BaselineStubReg);
     masm.pushBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
-
     return tailCallVM(DoCompareFallbackInfo, masm);
 }
 
 //
 // Compare_String
 //
 
 bool
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -213,17 +213,17 @@ jit::EnterBaselineAtBranch(JSContext *cx
     return IonExec_Ok;
 }
 
 MethodStatus
 jit::BaselineCompile(JSContext *cx, HandleScript script)
 {
     JS_ASSERT(!script->hasBaselineScript());
     JS_ASSERT(script->canBaselineCompile());
-
+    JS_ASSERT(IsBaselineEnabled(cx));
     LifoAlloc alloc(BASELINE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
 
     script->ensureNonLazyCanonicalFunction(cx);
 
     TempAllocator *temp = alloc.new_<TempAllocator>(&alloc);
     if (!temp)
         return Method_Error;
 
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -2142,18 +2142,21 @@ jit::AnalyzeNewScriptProperties(JSContex
     // When invoking 'new' on the specified script, try to find some properties
     // which will definitely be added to the created object before it has a
     // chance to escape and be accessed elsewhere.
 
     RootedScript script(cx, fun->getOrCreateScript(cx));
     if (!script)
         return false;
 
-    if (!script->compileAndGo() || !script->canBaselineCompile())
+    if (!jit::IsIonEnabled(cx) || !jit::IsBaselineEnabled(cx) ||
+        !script->compileAndGo() || !script->canBaselineCompile())
+    {
         return true;
+    }
 
     static const uint32_t MAX_SCRIPT_SIZE = 2000;
     if (script->length() > MAX_SCRIPT_SIZE)
         return true;
 
     Vector<PropertyName *> accessedProperties(cx);
 
     LifoAlloc alloc(types::TypeZone::TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -3488,16 +3488,17 @@ MacroAssemblerARMCompat::setupABICall(ui
     JS_ASSERT(!inCall_);
     inCall_ = true;
     args_ = args;
     passedArgs_ = 0;
     passedArgTypes_ = 0;
 #ifdef JS_CODEGEN_ARM_HARDFP
     usedIntSlots_ = 0;
     usedFloatSlots_ = 0;
+    usedFloat32_ = false;
     padding_ = 0;
 #else
     usedSlots_ = 0;
 #endif
     floatArgsInGPR[0] = MoveOperand();
     floatArgsInGPR[1] = MoveOperand();
     floatArgsInGPRValid[0] = false;
     floatArgsInGPRValid[1] = false;
@@ -3530,41 +3531,59 @@ MacroAssemblerARMCompat::passABIArg(cons
 {
     MoveOperand to;
     ++passedArgs_;
     if (!enoughMemory_)
         return;
     switch (type) {
       case MoveOp::FLOAT32:
       case MoveOp::DOUBLE: {
+        // N.B. this isn't a limitation of the ABI, it is a limitation of the compiler right now.
+        // There isn't a good way to handle odd numbered single registers, so everything goes to hell
+        // when we try.  Current fix is to never use more than one float in a function call.
+        // Fix coming along with complete float32 support in bug 957504.
+        JS_ASSERT(!usedFloat32_);
+        if (type == MoveOp::FLOAT32)
+            usedFloat32_ = true;
         FloatRegister fr;
         if (GetFloatArgReg(usedIntSlots_, usedFloatSlots_, &fr)) {
             if (from.isFloatReg() && from.floatReg() == fr) {
                 // Nothing to do; the value is in the right register already
+                usedFloatSlots_++;
+                if (type == MoveOp::FLOAT32)
+                    passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_Float32;
+                else
+                    passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_Double;
                 return;
             }
             to = MoveOperand(fr);
         } else {
             // If (and only if) the integer registers have started spilling, do we
             // need to take the register's alignment into account
-            uint32_t disp = GetFloatArgStackDisp(usedIntSlots_, usedFloatSlots_, &padding_);
+            uint32_t disp = INT_MAX;
+            if (type == MoveOp::FLOAT32)
+                disp = GetFloat32ArgStackDisp(usedIntSlots_, usedFloatSlots_, &padding_);
+            else
+                disp = GetDoubleArgStackDisp(usedIntSlots_, usedFloatSlots_, &padding_);
             to = MoveOperand(sp, disp);
         }
         usedFloatSlots_++;
         if (type == MoveOp::FLOAT32)
             passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_Float32;
         else
             passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_Double;
         break;
       }
       case MoveOp::GENERAL: {
         Register r;
         if (GetIntArgReg(usedIntSlots_, usedFloatSlots_, &r)) {
             if (from.isGeneralReg() && from.reg() == r) {
                 // Nothing to do; the value is in the right register already
+                usedIntSlots_++;
+                passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_General;
                 return;
             }
             to = MoveOperand(r);
         } else {
             uint32_t disp = GetIntArgStackDisp(usedIntSlots_, usedFloatSlots_, &padding_);
             to = MoveOperand(sp, disp);
         }
         usedIntSlots_++;
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -443,16 +443,17 @@ class MacroAssemblerARMCompat : public M
     // The actual number of arguments that were passed, used to assert that
     // the initial number of arguments declared was correct.
     uint32_t passedArgs_;
     uint32_t passedArgTypes_;
 
 #ifdef JS_CODEGEN_ARM_HARDFP
     uint32_t usedIntSlots_;
     uint32_t usedFloatSlots_;
+    bool usedFloat32_;
     uint32_t padding_;
 #else
     // ARM treats arguments as a vector in registers/memory, that looks like:
     // { r0, r1, r2, r3, [sp], [sp,+4], [sp,+8] ... }
     // usedSlots_ keeps track of how many of these have been used.
     // It bears a passing resemblance to passedArgs_, but a single argument
     // can effectively use between one and three slots depending on its size and
     // alignment requirements
--- a/js/src/jsapi-tests/testAddPropertyPropcache.cpp
+++ b/js/src/jsapi-tests/testAddPropertyPropcache.cpp
@@ -37,17 +37,17 @@ BEGIN_TEST(testAddPropertyHook)
     static const int ExpectedCount = 100;
 
     JS::RootedObject obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
     CHECK(obj);
     JS::RootedValue proto(cx, OBJECT_TO_JSVAL(obj));
     JS_InitClass(cx, global, obj, &AddPropertyClass, nullptr, 0, nullptr, nullptr, nullptr,
                  nullptr);
 
-    obj = JS_NewArrayObject(cx, 0, nullptr);
+    obj = JS_NewArrayObject(cx, 0);
     CHECK(obj);
     JS::RootedValue arr(cx, OBJECT_TO_JSVAL(obj));
 
     CHECK(JS_DefineProperty(cx, global, "arr", arr,
                             JS_PropertyStub, JS_StrictPropertyStub,
                             JSPROP_ENUMERATE));
 
     for (int i = 0; i < ExpectedCount; ++i) {
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3769,26 +3769,34 @@ JS_GetReservedSlot(JSObject *obj, uint32
 
 JS_PUBLIC_API(void)
 JS_SetReservedSlot(JSObject *obj, uint32_t index, Value value)
 {
     obj->setReservedSlot(index, value);
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_NewArrayObject(JSContext *cx, int length, jsval *vector)
-{
-    AutoArrayRooter tvr(cx, length, vector);
-
+JS_NewArrayObject(JSContext *cx, const JS::HandleValueArray& contents)
+{
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
-    assertSameCompartment(cx, JSValueArray(vector, vector ? (uint32_t)length : 0));
-    return NewDenseCopiedArray(cx, (uint32_t)length, vector);
+    assertSameCompartment(cx, contents);
+    return NewDenseCopiedArray(cx, contents.length(), contents.begin());
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewArrayObject(JSContext *cx, size_t length)
+{
+    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+
+    return NewDenseAllocatedArray(cx, length);
 }
 
 JS_PUBLIC_API(bool)
 JS_IsArrayObject(JSContext *cx, JS::HandleObject obj)
 {
     assertSameCompartment(cx, obj);
     return ObjectClassIs(obj, ESClass_Array, cx);
 }
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -621,17 +621,17 @@ class HandleValueArray
     /* CallArgs must already be rooted somewhere up the stack. */
     HandleValueArray(const JS::CallArgs& args) : length_(args.length()), elements_(args.array()) {}
 
     /* Use with care! Only call this if the data is guaranteed to be marked. */
     static HandleValueArray fromMarkedLocation(size_t len, const Value *elements) {
         return HandleValueArray(len, elements);
     }
 
-    static HandleValueArray subarray(const AutoValueVector& values, size_t startIndex, size_t len) {
+    static HandleValueArray subarray(const HandleValueArray& values, size_t startIndex, size_t len) {
         JS_ASSERT(startIndex + len <= values.length());
         return HandleValueArray(len, values.begin() + startIndex);
     }
 
     size_t length() const { return length_; }
     const Value *begin() const { return elements_; }
 
     HandleValue operator[](size_t i) const {
@@ -3065,17 +3065,20 @@ JS_SetUCProperty(JSContext *cx, JS::Hand
                  const jschar *name, size_t namelen,
                  JS::HandleValue v);
 
 extern JS_PUBLIC_API(bool)
 JS_DeleteUCProperty2(JSContext *cx, JS::HandleObject obj, const jschar *name, size_t namelen,
                      bool *succeeded);
 
 extern JS_PUBLIC_API(JSObject *)
-JS_NewArrayObject(JSContext *cx, int length, jsval *vector);
+JS_NewArrayObject(JSContext *cx, const JS::HandleValueArray& contents);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_NewArrayObject(JSContext *cx, size_t length);
 
 extern JS_PUBLIC_API(bool)
 JS_IsArrayObject(JSContext *cx, JS::HandleValue value);
 
 extern JS_PUBLIC_API(bool)
 JS_IsArrayObject(JSContext *cx, JS::HandleObject obj);
 
 extern JS_PUBLIC_API(bool)
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2331,17 +2331,17 @@ GetPDA(JSContext *cx, unsigned argc, jsv
     CallArgs args = CallArgsFromVp(argc, vp);
     if (!JS_ValueToObject(cx, args.get(0), &vobj))
         return false;
     if (!vobj) {
         args.rval().setUndefined();
         return true;
     }
 
-    RootedObject aobj(cx, JS_NewArrayObject(cx, 0, nullptr));
+    RootedObject aobj(cx, JS_NewArrayObject(cx, 0));
     if (!aobj)
         return false;
     args.rval().setObject(*aobj);
 
     ok = !!JS_GetPropertyDescArray(cx, vobj, &pda);
     if (!ok)
         return false;
     pd = pda.array;
@@ -5392,17 +5392,17 @@ NewGlobalObject(JSContext *cx, JS::Compa
 
 static bool
 BindScriptArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
 {
     RootedObject obj(cx, obj_);
 
     MultiStringRange msr = op->getMultiStringArg("scriptArgs");
     RootedObject scriptArgs(cx);
-    scriptArgs = JS_NewArrayObject(cx, 0, nullptr);
+    scriptArgs = JS_NewArrayObject(cx, 0);
     if (!scriptArgs)
         return false;
 
     if (!JS_DefineProperty(cx, obj, "scriptArgs", OBJECT_TO_JSVAL(scriptArgs),
                            nullptr, nullptr, 0))
         return false;
 
     for (size_t i = 0; !msr.empty(); msr.popFront(), ++i) {
--- a/js/src/shell/jsheaptools.cpp
+++ b/js/src/shell/jsheaptools.cpp
@@ -506,17 +506,17 @@ ReferenceFinder::addReferrer(jsval refer
 
     /* Find the property of the results object named |pathName|. */
     RootedValue v(context);
 
     if (!JS_GetProperty(context, result, pathName, &v))
         return false;
     if (v.isUndefined()) {
         /* Create an array to accumulate referents under this path. */
-        JSObject *array = JS_NewArrayObject(context, 1, referrer.address());
+        JSObject *array = JS_NewArrayObject(context, referrer);
         if (!array)
             return false;
         v.setObject(*array);
         return !!JS_SetProperty(context, result, pathName, v);
     }
 
     /* The property's value had better be an array. */
     RootedObject array(context, &v.toObject());
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/handle.js
+++ /dev/null
@@ -1,60 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
-
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
-var BUGNUMBER = 898342;
-var summary = 'Handles';
-
-var T = TypedObject;
-
-function runTests() {
-  var Point = T.float32.array(3);
-  var Line = new T.StructType({from: Point, to: Point});
-  var Lines = Line.array(3);
-
-  var lines = new Lines([
-    {from: [1, 2, 3], to: [4, 5, 6]},
-    {from: [7, 8, 9], to: [10, 11, 12]},
-    {from: [13, 14, 15], to: [16, 17, 18]}
-  ]);
-
-  var handle = Lines.handle(lines);
-  var handle0 = Line.handle(lines, 0);
-  var handle2 = Line.handle(lines, 2);
-
-  // Reads from handles should see the correct data:
-  assertEq(handle[0].from[0], 1);
-  assertEq(handle0.from[0], 1);
-  assertEq(handle2.from[0], 13);
-
-  // Writes to handles should modify the original:
-  handle2.from[0] = 22;
-  assertEq(lines[2].from[0], 22);
-
-  // Reads from handles should see the updated data:
-  assertEq(handle[0].from[0], 1);
-  assertEq(handle0.from[0], 1);
-  assertEq(handle2.from[0], 22);
-
-  // isHandle, when called on nonsense, returns false:
-  assertEq(T.Handle.isHandle(22), false);
-  assertEq(T.Handle.isHandle({}), false);
-
-  // Derived handles should remain handles:
-  assertEq(T.Handle.isHandle(lines), false);
-  assertEq(T.Handle.isHandle(lines[0]), false);
-  assertEq(T.Handle.isHandle(lines[0].from), false);
-  assertEq(T.Handle.isHandle(handle), true);
-  assertEq(T.Handle.isHandle(handle[0]), true);
-  assertEq(T.Handle.isHandle(handle[0].from), true);
-
-  reportCompare(true, true);
-  print("Tests complete");
-}
-
-runTests();
-
-
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/handle_get_set.js
+++ /dev/null
@@ -1,79 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
-
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
-var BUGNUMBER = 898342;
-var summary = 'Handle Move';
-
-var T = TypedObject;
-
-var Point = T.float32.array(3);
-var Line = new T.StructType({from: Point, to: Point});
-var Lines = Line.array(3);
-
-var Objects = T.Object.array(3);
-
-function runTests() {
-  function testHandleGetSetWithScalarType() {
-    var lines = new Lines([
-      {from: [1, 2, 3], to: [4, 5, 6]},
-      {from: [7, 8, 9], to: [10, 11, 12]},
-      {from: [13, 14, 15], to: [16, 17, 18]}
-    ]);
-
-    var handle = T.float32.handle(lines, 0, "to", 1);
-    assertEq(T.Handle.get(handle), 5);
-    T.Handle.set(handle, 22);
-    assertEq(T.Handle.get(handle), 22);
-    assertEq(lines[0].to[1], 22);
-  }
-  testHandleGetSetWithScalarType();
-
-  function testHandleGetSetWithObjectType() {
-    var one = {x: 1};
-    var two = {x: 2};
-    var three = {x: 3};
-    var objects = new Objects([one, two, three]);
-
-    var handle = T.Object.handle(objects, 0);
-    assertEq(T.Handle.get(handle), one);
-    T.Handle.set(handle, three);
-    assertEq(T.Handle.get(handle), three);
-    assertEq(objects[0], three);
-
-    T.Handle.move(handle, objects, 1);
-    assertEq(T.Handle.get(handle), two);
-  }
-  testHandleGetSetWithScalarType();
-
-  function testHandleGetSetWithComplexType() {
-    var lines = new Lines([
-      {from: [1, 2, 3], to: [4, 5, 6]},
-      {from: [7, 8, 9], to: [10, 11, 12]},
-      {from: [13, 14, 15], to: [16, 17, 18]}
-    ]);
-
-    var handle = Point.handle(lines, 0, "to");
-
-    T.Handle.set(handle, [22, 23, 24]);
-
-    assertEq(handle[0], 22);
-    assertEq(handle[1], 23);
-    assertEq(handle[2], 24);
-
-    assertEq(T.Handle.get(handle)[0], 22);
-    assertEq(T.Handle.get(handle)[1], 23);
-    assertEq(T.Handle.get(handle)[2], 24);
-  }
-  testHandleGetSetWithComplexType();
-
-  reportCompare(true, true);
-  print("Tests complete");
-}
-
-runTests();
-
-
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/handle_move.js
+++ /dev/null
@@ -1,162 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
-
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
-var BUGNUMBER = 898342;
-var summary = 'Handle Move';
-
-var T = TypedObject;
-
-var Point = T.float32.array(3);
-var Line = new T.StructType({from: Point, to: Point});
-var Lines = Line.array(3);
-
-function runTests() {
-  function testHandleToPoint() {
-    var lines = new Lines([
-      {from: [1, 2, 3], to: [4, 5, 6]},
-      {from: [7, 8, 9], to: [10, 11, 12]},
-      {from: [13, 14, 15], to: [16, 17, 18]}
-    ]);
-
-    function allPoints(lines, func) {
-      var handle = Point.handle();
-      for (var i = 0; i < lines.length; i++) {
-        T.Handle.move(handle, lines, i, "from");
-        func(handle);
-
-        T.Handle.move(handle, lines, i, "to");
-        func(handle);
-      }
-    }
-
-    // Iterate over all ponts and mutate them in place:
-    allPoints(lines, function(p) {
-      p[0] += 100;
-      p[1] += 200;
-      p[2] += 300;
-    });
-
-    // Spot check the results
-    assertEq(lines[0].from[0], 101);
-    assertEq(lines[1].to[1], 211);
-    assertEq(lines[2].to[2], 318);
-  }
-  testHandleToPoint();
-
-  function testHandleToFloat() {
-    var lines = new Lines([
-      {from: [1, 2, 3], to: [4, 5, 6]},
-      {from: [7, 8, 9], to: [10, 11, 12]},
-      {from: [13, 14, 15], to: [16, 17, 18]}
-    ]);
-
-    function allPoints(lines, func) {
-      var handle = T.float32.handle();
-      for (var i = 0; i < lines.length; i++) {
-        T.Handle.move(handle, lines, i, "from", 0);
-        func(handle);
-
-        T.Handle.move(handle, lines, i, "from", 1);
-        func(handle);
-
-        T.Handle.move(handle, lines, i, "from", 2);
-        func(handle);
-
-        T.Handle.move(handle, lines, i, "to", 0);
-        func(handle);
-
-        T.Handle.move(handle, lines, i, "to", 1);
-        func(handle);
-
-        T.Handle.move(handle, lines, i, "to", 2);
-        func(handle);
-      }
-    }
-
-    // Iterate over all ponts and mutate them in place:
-    allPoints(lines, function(p) {
-      T.Handle.set(p, T.Handle.get(p) + 100);
-    });
-
-    // Spot check the results
-    assertEq(lines[0].from[0], 101);
-    assertEq(lines[1].to[1], 111);
-    assertEq(lines[2].to[2], 118);
-  }
-  testHandleToFloat();
-
-  function testHandleToEquivalentType() {
-    var Point2 = T.float32.array(3);
-
-    assertEq(Point.equivalent(Point2), true);
-
-    var lines = new Lines([
-      {from: [1, 2, 3], to: [4, 5, 6]},
-      {from: [7, 8, 9], to: [10, 11, 12]},
-      {from: [13, 14, 15], to: [16, 17, 18]}
-    ]);
-
-    var handle = Point2.handle(lines, 0, "to");
-    assertEq(handle[0], 4);
-    assertEq(handle[1], 5);
-    assertEq(handle[2], 6);
-  }
-  testHandleToEquivalentType();
-
-  function testHandleMoveToIllegalType() {
-    var lines = new Lines([
-      {from: [1, 2, 3], to: [4, 5, 6]},
-      {from: [7, 8, 9], to: [10, 11, 12]},
-      {from: [13, 14, 15], to: [16, 17, 18]}
-    ]);
-
-    // Moving a handle to a value of incorrect type should report an error:
-    assertThrowsInstanceOf(function() {
-      Line.handle(lines);
-    }, TypeError, "handle moved to destination of incorrect type");
-    assertThrowsInstanceOf(function() {
-      var h = Line.handle();
-      T.Handle.move(h, lines);
-    }, TypeError, "handle moved to destination of incorrect type");
-    assertThrowsInstanceOf(function() {
-      var h = T.float32.handle();
-      T.Handle.move(h, lines, 0);
-    }, TypeError, "handle moved to destination of incorrect type");
-  }
-  testHandleMoveToIllegalType();
-
-  function testHandleMoveToIllegalProperty() {
-    var lines = new Lines([
-      {from: [1, 2, 3], to: [4, 5, 6]},
-      {from: [7, 8, 9], to: [10, 11, 12]},
-      {from: [13, 14, 15], to: [16, 17, 18]}
-    ]);
-
-    assertThrowsInstanceOf(function() {
-      var h = Point.handle();
-      T.Handle.move(h, lines, 0, "foo");
-    }, TypeError, "No such property: foo");
-
-    assertThrowsInstanceOf(function() {
-      var h = Point.handle();
-      T.Handle.move(h, lines, 22, "to");
-    }, TypeError, "No such property: 22");
-
-    assertThrowsInstanceOf(function() {
-      var h = Point.handle();
-      T.Handle.move(h, lines, -100, "to");
-    }, TypeError, "No such property: -100");
-  }
-  testHandleMoveToIllegalProperty();
-
-  reportCompare(true, true);
-  print("Tests complete");
-}
-
-runTests();
-
-
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/handle_unattached.js
+++ /dev/null
@@ -1,49 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
-
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
-var BUGNUMBER = 898342;
-var summary = 'Unattached handles';
-
-var T = TypedObject;
-
-function runTests() {
-  var Line = new T.StructType({from: T.uint8, to: T.uint8});
-  var Lines = Line.array(3);
-
-  // Create unattached handle to array, struct:
-  var handle = Lines.handle();
-  var handle0 = Line.handle();
-
-  // Accessing length throws:
-  assertThrowsInstanceOf(function() handle.length, TypeError,
-                         "handle.length did not yield error");
-
-  // Accessing properties throws:
-  assertThrowsInstanceOf(function() handle[0], TypeError,
-                         "Unattached handle did not yield error");
-  assertThrowsInstanceOf(function() handle0.from, TypeError,
-                         "Unattached handle did not yield error");
-
-  // Handle.get() throws:
-  assertThrowsInstanceOf(function() T.Handle.get(handle), TypeError,
-                         "Unattached handle did not yield error");
-  assertThrowsInstanceOf(function() T.Handle.get(handle0), TypeError,
-                         "Unattached handle did not yield error");
-
-  // Handle.set() throws:
-  assertThrowsInstanceOf(function() T.Handle.set(handle, [{},{},{}]), TypeError,
-                         "Unattached handle did not yield error");
-  assertThrowsInstanceOf(function() T.Handle.set(handle0, {}), TypeError,
-                         "Unattached handle did not yield error");
-
-  reportCompare(true, true);
-  print("Tests complete");
-}
-
-runTests();
-
-
--- a/js/src/tests/ecma_6/TypedObject/method_build.js
+++ b/js/src/tests/ecma_6/TypedObject/method_build.js
@@ -14,25 +14,21 @@ var uint16 = TypedObject.uint16;
 var uint32 = TypedObject.uint32;
 var uint8Clamped = TypedObject.uint8Clamped;
 var int8 = TypedObject.int8;
 var int16 = TypedObject.int16;
 var int32 = TypedObject.int32;
 var float32 = TypedObject.float32;
 var float64 = TypedObject.float64;
 
-var Handle = TypedObject.Handle;
-
 function oneDimensionalArrayOfUints() {
   var grain = uint32;
   var type = grain.array(4);
   var r1 = type.build(x => x * 2);
-  var r2 = type.build((x, out) => Handle.set(out, x * 2));
   assertTypedEqual(type, r1, new type([0, 2, 4, 6]));
-  assertTypedEqual(type, r1, r2);
 }
 
 function oneDimensionalArrayOfStructs() {
   var grain = new StructType({f: uint32});
   var type = grain.array(4);
   var r1 = type.build(x => new grain({f: x * 2}));
   var r2 = type.build((x, out) => { out.f = x * 2; });
   assertTypedEqual(type, r1, new type([{f:0}, {f:2},
@@ -82,20 +78,18 @@ function twoDimensionalArrayOfStructsWit
                                        [{f:10}, {f:11}]]));
   assertTypedEqual(type, r1, r2);
 }
 
 function threeDimensionalArrayOfUintsWithDepth3() {
   var grain = uint32;
   var type = grain.array(2).array(2).array(2);
   var r1 = type.build(3, (x,y,z) => x * 100 + y * 10 + z);
-  var r2 = type.build(3, (x,y,z, out) => Handle.set(out, x * 100 + y * 10 + z));
   assertTypedEqual(type, r1, new type([[[  0,   1], [ 10,  11]],
                                        [[100, 101], [110, 111]]]));
-  assertTypedEqual(type, r1, r2);
 }
 
 function threeDimensionalArrayOfUintsWithDepth2() {
   var grain = uint32.array(2);
   var type = grain.array(2).array(2);
   var r1 = type.build(2, (x,y) => [x * 100 + y * 10 + 0, x * 100 + y * 10 + 1]);
   var r1b = type.build(2, (x,y) => grain.build(z => x * 100 + y * 10 + z));
   var r1c = type.build(2, (x,y) => grain.build(1, z => x * 100 + y * 10 + z));
--- a/js/src/tests/ecma_6/TypedObject/method_from.js
+++ b/js/src/tests/ecma_6/TypedObject/method_from.js
@@ -14,18 +14,16 @@ var uint16 = TypedObject.uint16;
 var uint32 = TypedObject.uint32;
 var uint8Clamped = TypedObject.uint8Clamped;
 var int8 = TypedObject.int8;
 var int16 = TypedObject.int16;
 var int32 = TypedObject.int32;
 var float32 = TypedObject.float32;
 var float64 = TypedObject.float64;
 
-var Handle = TypedObject.Handle;
-
 // Test name format:
 
 // from<N>DimArrayOf<G1>sTo<G2>s where <N> is a positive integer (or its
 // equivalent word in English) and <G1> and <G2> are both grain types
 // (potentially an array themselves.)
 
 function fromOneDimArrayOfUint8ToUint32s() {
   var intype = uint8.array(4);
@@ -53,75 +51,66 @@ function fromTwoDimArrayOfUint8ToUint32s
   var type = rowtype.array(4);
   var i1 = new type([[10, 11, 12, 13],
                      [20, 21, 22, 23],
                      [30, 31, 32, 33],
                      [40, 41, 42, 43]]);
 
   var r1 = type.from(i1, 2, x => x*2);
   var r2 = type.from(i1, 1, a => rowtype.from(a, 1, x => x*2));
-  var r3 = type.from(i1, 1,
-    a => rowtype.from(a, 1, (x, j, c, out) => Handle.set(out, x*2)));
-  var r4 = type.from(i1, 1, (a, j, c, out) => { out[0] = a[0]*2;
+  var r3 = type.from(i1, 1, (a, j, c, out) => { out[0] = a[0]*2;
                                                 out[1] = a[1]*2;
                                                 out[2] = a[2]*2;
                                                 out[3] = a[3]*2; });
   assertTypedEqual(type, r1, new type([[20, 22, 24, 26],
                                        [40, 42, 44, 46],
                                        [60, 62, 64, 66],
                                        [80, 82, 84, 86]]));
   assertTypedEqual(type, r1, r2);
   assertTypedEqual(type, r1, r3);
-  assertTypedEqual(type, r1, r4);
 }
 
 function fromTwoDimArrayOfUint32ToUint8s() {
   var intype = uint32.array(4).array(4);
   var rowtype = uint8.array(4);
   var type = rowtype.array(4);
   var i1 = new type([[10, 11, 12, 13],
                      [20, 21, 22, 23],
                      [30, 31, 32, 33],
                      [40, 41, 42, 43]]);
 
   var r1 = type.from(i1, 2, x => x*2);
   var r2 = type.from(i1, 1, a => rowtype.from(a, 1, x => x*2));
-  var r3 = type.from(i1, 1,
-    a => rowtype.from(a, 1, (x, j, c, out) => Handle.set(out, x*2)));
-  var r4 = type.from(i1, 1, (a, j, c, out) => { out[0] = a[0]*2;
+  var r3 = type.from(i1, 1, (a, j, c, out) => { out[0] = a[0]*2;
                                                 out[1] = a[1]*2;
                                                 out[2] = a[2]*2;
                                                 out[3] = a[3]*2; });
   assertTypedEqual(type, r1, new type([[20, 22, 24, 26],
                                        [40, 42, 44, 46],
                                        [60, 62, 64, 66],
                                        [80, 82, 84, 86]]));
   assertTypedEqual(type, r1, r2);
   assertTypedEqual(type, r1, r3);
-  assertTypedEqual(type, r1, r4);
 }
 
 function fromOneDimArrayOfArrayOfUint8ToUint32s() {
   var intype = uint8.array(4).array(4);
   var type = uint32.array(4);
   var i1 = new intype([[0xdd, 0xcc, 0xbb, 0xaa],
                        [0x09, 0x08, 0x07, 0x06],
                        [0x15, 0x14, 0x13, 0x12],
                        [0x23, 0x32, 0x41, 0x50]]);
 
   function combine(a,b,c,d) { return a << 24 | b << 16 | c << 8 | d; }
 
   var r1 = type.from(i1, x => combine(x[0], x[1], x[2], x[3]));
-  var r2 = type.from(i1, 1,
-    (x, i, c, out) => Handle.set(out, combine(x[0], x[1], x[2], x[3])));
   assertTypedEqual(type, r1, new type([0xddccbbaa,
                                        0x09080706,
                                        0x15141312,
                                        0x23324150]));
-  assertTypedEqual(type, r1, r2);
 }
 
 function fromOneDimArrayOfUint32ToArrayOfUint8s() {
   var intype = uint32.array(4);
   var type = uint8.array(4).array(4);
   var i1 = new intype([0xddccbbaa,
                        0x09080706,
                        0x15141312,
--- a/js/src/tests/ecma_6/TypedObject/method_map.js
+++ b/js/src/tests/ecma_6/TypedObject/method_map.js
@@ -14,18 +14,16 @@ var uint16 = TypedObject.uint16;
 var uint32 = TypedObject.uint32;
 var uint8Clamped = TypedObject.uint8Clamped;
 var int8 = TypedObject.int8;
 var int16 = TypedObject.int16;
 var int32 = TypedObject.int32;
 var float32 = TypedObject.float32;
 var float64 = TypedObject.float64;
 
-var Handle = TypedObject.Handle;
-
 // Test name format:
 
 // map<N>DimArrayOf<G1>sTo<G2>s where <N> is a positive integer (or its
 // equivalent word in English) and <G1> and <G2> are both grain types
 // (potentially an array themselves.)
 
 function mapOneDimArrayOfUint8() {
   var type = uint8.array(4);
@@ -49,51 +47,47 @@ function mapTwoDimArrayOfUint8() {
   var type = uint8.array(4).array(4);
   var i1 = new type([[10, 11, 12, 13],
                      [20, 21, 22, 23],
                      [30, 31, 32, 33],
                      [40, 41, 42, 43]]);
 
   var r1 = i1.map(2, x => x*2);
   var r2 = i1.map(1, a => a.map(1, x => x*2));
-  var r3 = i1.map(1, a => a.map(1, (x, j, c, out) => Handle.set(out, x*2)));
-  var r4 = i1.map(1, (a, j, c, out) => { out[0] = a[0]*2;
+  var r3 = i1.map(1, (a, j, c, out) => { out[0] = a[0]*2;
                                          out[1] = a[1]*2;
                                          out[2] = a[2]*2;
                                          out[3] = a[3]*2; });
   assertTypedEqual(type, r1, new type([[20, 22, 24, 26],
                                        [40, 42, 44, 46],
                                        [60, 62, 64, 66],
                                        [80, 82, 84, 86]]));
   assertTypedEqual(type, r1, r2);
   assertTypedEqual(type, r1, r3);
-  assertTypedEqual(type, r1, r4);
 }
 
 function mapTwoDimArrayOfUint32() {
   var type = uint32.array(4).array(4);
   var i1 = new type([[10, 11, 12, 13],
                      [20, 21, 22, 23],
                      [30, 31, 32, 33],
                      [40, 41, 42, 43]]);
 
   var r1 = i1.map(2, x => x*2);
   var r2 = i1.map(1, a => a.map(1, x => x*2));
-  var r3 = i1.map(1, a => a.map(1, (x, j, c, out) => Handle.set(out, x*2)));
-  var r4 = i1.map(1, (a, j, c, out) => { out[0] = a[0]*2;
+  var r3 = i1.map(1, (a, j, c, out) => { out[0] = a[0]*2;
                                          out[1] = a[1]*2;
                                          out[2] = a[2]*2;
                                          out[3] = a[3]*2; });
   assertTypedEqual(type, r1, new type([[20, 22, 24, 26],
                                        [40, 42, 44, 46],
                                        [60, 62, 64, 66],
                                        [80, 82, 84, 86]]));
   assertTypedEqual(type, r1, r2);
   assertTypedEqual(type, r1, r3);
-  assertTypedEqual(type, r1, r4);
 }
 
 var Grain = new StructType({f: uint32});
 function wrapG(v) { return new Grain({f: v}); }
 function doubleG(g) { return new Grain({f: g.f * 2}); }
 function tenG(x, y) { return new Grain({f: x * 10 + y}); }
 
 function mapOneDimArrayOfStructs() {
--- a/js/xpconnect/public/nsTArrayHelpers.h
+++ b/js/xpconnect/public/nsTArrayHelpers.h
@@ -12,17 +12,17 @@
 template <class T>
 inline nsresult
 nsTArrayToJSArray(JSContext* aCx, const nsTArray<T>& aSourceArray,
                   JSObject** aResultArray)
 {
   MOZ_ASSERT(aCx);
 
   JS::Rooted<JSObject*> arrayObj(aCx,
-    JS_NewArrayObject(aCx, aSourceArray.Length(), nullptr));
+    JS_NewArrayObject(aCx, aSourceArray.Length()));
   if (!arrayObj) {
     NS_WARNING("JS_NewArrayObject failed!");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
   MOZ_ASSERT(global);
 
@@ -54,17 +54,17 @@ template <>
 inline nsresult
 nsTArrayToJSArray<nsString>(JSContext* aCx,
                             const nsTArray<nsString>& aSourceArray,
                             JSObject** aResultArray)
 {
   MOZ_ASSERT(aCx);
 
   JS::Rooted<JSObject*> arrayObj(aCx,
-    JS_NewArrayObject(aCx, aSourceArray.Length(), nullptr));
+    JS_NewArrayObject(aCx, aSourceArray.Length()));
   if (!arrayObj) {
     NS_WARNING("JS_NewArrayObject failed!");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   JS::Rooted<JSString*> s(aCx);
   for (uint32_t index = 0; index < aSourceArray.Length(); index++) {
     s = JS_NewUCStringCopyN(aCx, aSourceArray[index].BeginReading(),
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3036,17 +3036,17 @@ nsXPCComponents_Utils::CreateArrayIn(Han
     // first argument must be an object
     if (vobj.isPrimitive())
         return NS_ERROR_XPC_BAD_CONVERT_JS;
 
     RootedObject scope(cx, js::UncheckedUnwrap(&vobj.toObject()));
     RootedObject obj(cx);
     {
         JSAutoCompartment ac(cx, scope);
-        obj =  JS_NewArrayObject(cx, 0, nullptr);
+        obj =  JS_NewArrayObject(cx, 0);
         if (!obj)
             return NS_ERROR_FAILURE;
     }
 
     if (!JS_WrapObject(cx, &obj))
         return NS_ERROR_FAILURE;
 
     rval.setObject(*obj);
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -1357,17 +1357,17 @@ XPCConvert::NativeArray2JS(MutableHandle
     NS_PRECONDITION(s, "bad param");
 
     AutoJSContext cx;
 
     // XXX add support for putting chars in a string rather than an array
 
     // XXX add support to indicate *which* array element was not convertable
 
-    RootedObject array(cx, JS_NewArrayObject(cx, count, nullptr));
+    RootedObject array(cx, JS_NewArrayObject(cx, count));
     if (!array)
         return false;
 
     if (pErr)
         *pErr = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
 
     uint32_t i;
     RootedValue current(cx, JSVAL_NULL);
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -1088,17 +1088,17 @@ ProcessArgs(JSContext *cx, JS::Handle<JS
           default:;
         }
     }
 
     /*
      * Create arguments early and define it to root it, so it's safe from any
      * GC calls nested below, and so it is available to -f <file> arguments.
      */
-    argsObj = JS_NewArrayObject(cx, 0, nullptr);
+    argsObj = JS_NewArrayObject(cx, 0);
     if (!argsObj)
         return 1;
     if (!JS_DefineProperty(cx, obj, "arguments", OBJECT_TO_JSVAL(argsObj),
                            nullptr, nullptr, 0)) {
         return 1;
     }
 
     for (size_t j = 0, length = argc - i; j < length; j++) {
--- a/js/xpconnect/src/XPCVariant.cpp
+++ b/js/xpconnect/src/XPCVariant.cpp
@@ -636,17 +636,17 @@ XPCVariant::VariantDataToJS(nsIVariant* 
                                            du.u.array.mArrayCount, pErr);
 
 VARIANT_DONE:
             nsVariant::Cleanup(&du);
             return success;
         }
         case nsIDataType::VTYPE_EMPTY_ARRAY:
         {
-            JSObject* array = JS_NewArrayObject(cx, 0, nullptr);
+            JSObject* array = JS_NewArrayObject(cx, 0);
             if (!array)
                 return false;
             pJSVal.setObject(*array);
             return true;
         }
         case nsIDataType::VTYPE_VOID:
             pJSVal.setUndefined();
             return true;
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -3263,17 +3263,17 @@ nsDisplayMixBlendMode::BuildLayer(nsDisp
 
   nsRefPtr<Layer> container = aManager->GetLayerBuilder()->
   BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
                          newContainerParameters, nullptr);
   if (!container) {
     return nullptr;
   }
 
-  container->SetMixBlendMode(nsCSSRendering::GetGFXBlendMode(mFrame->StyleDisplay()->mMixBlendMode));
+  container->DeprecatedSetMixBlendMode(nsCSSRendering::GetGFXBlendMode(mFrame->StyleDisplay()->mMixBlendMode));
 
   return container.forget();
 }
 
 bool nsDisplayMixBlendMode::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                               nsRegion* aVisibleRegion,
                                               const nsRect& aAllowVisibleRegionExpansion) {
   // Our children are need their backdrop so we should not allow them to subtract
--- a/media/webrtc/moz.build
+++ b/media/webrtc/moz.build
@@ -24,17 +24,18 @@ webrtc_non_unified_sources = [
     'trunk/webrtc/modules/audio_processing/echo_cancellation_impl.cc',           # Because of name clash in the MapError function
     'trunk/webrtc/modules/audio_processing/echo_control_mobile_impl.cc',         # Because of name clash in the MapError function
     'trunk/webrtc/modules/audio_processing/gain_control_impl.cc',                # Because of name clash in the Handle typedef
     'trunk/webrtc/modules/audio_processing/high_pass_filter_impl.cc',            # Because of name clash in the Handle typedef
     'trunk/webrtc/modules/audio_processing/noise_suppression_impl.cc',           # Because of name clash in the Handle typedef
     'trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit.mm',       # Because of name clash in the nsAutoreleasePool class
     'trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info.mm',  # Because of name clash in the nsAutoreleasePool class
     'trunk/webrtc/modules/video_capture/windows/device_info_ds.cc',              # Because of the MEDIASUBTYPE_HDYC variable
-    'trunk/webrtc/modules/video_capture/windows/sink_filter_ds.cc',              # Because of the MEDIASUBTYPE_HDYC variable
+    'trunk/webrtc/modules/video_capture/windows/help_functions_ds.cc',           # Because of initguid.h
+    'trunk/webrtc/modules/video_capture/windows/sink_filter_ds.cc',              # Because of the MEDIASUBTYPE_HDYC variable and initguid.h
 ]
 
 GYP_DIRS += ['trunk']
 
 GYP_DIRS['trunk'].input = 'trunk/peerconnection.gyp'
 GYP_DIRS['trunk'].variables = gyp_vars
 GYP_DIRS['trunk'].sandbox_vars['FINAL_LIBRARY'] = 'webrtc'
 GYP_DIRS['trunk'].non_unified_sources += webrtc_non_unified_sources
--- a/media/webrtc/trunk/webrtc/typedefs.h
+++ b/media/webrtc/trunk/webrtc/typedefs.h
@@ -98,16 +98,26 @@
 #define WEBRTC_ARCH_64_BITS 1
 #define WEBRTC_ARCH_BIG_ENDIAN
 #define WEBRTC_BIG_ENDIAN
 #elif defined(__s390__)
 #define WEBRTC_ARCH_S390 1
 #define WEBRTC_ARCH_32_BITS 1
 #define WEBRTC_ARCH_BIG_ENDIAN
 #define WEBRTC_BIG_ENDIAN
+#elif defined(__aarch64__)
+#define WEBRTC_ARCH_AARCH64 1
+#define WEBRTC_ARCH_64_BITS 1
+#if defined(__AARCH64EL__)
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#define WEBRTC_LITTLE_ENDIAN
+#elif defined(__AARCH64EB__)
+#define WEBRTC_ARCH_BIG_ENDIAN
+#define WEBRTC_BIG_ENDIAN
+#endif
 #elif defined(__alpha__)
 #define WEBRTC_ARCH_ALPHA 1
 #define WEBRTC_ARCH_64_BITS 1
 #define WEBRTC_ARCH_LITTLE_ENDIAN
 #define WEBRTC_LITTLE_ENDIAN
 #elif defined(__avr32__)
 #define WEBRTC_ARCH_AVR32 1
 #define WEBRTC_ARCH_32_BITS 1
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -174,40 +174,40 @@
         <receiver android:name="org.mozilla.gecko.webapp.UninstallListener" >
           <intent-filter>
              <action android:name="android.intent.action.PACKAGE_REMOVED" />
              <data android:scheme="package" />
           </intent-filter>
         </receiver>
 #endif
 
-        <activity android:name=".WebApp"
+        <activity android:name=".Webapp"
                   android:label="@string/webapp_generic_name"
                   android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize"
                   android:windowSoftInputMode="stateUnspecified|adjustResize"
                   android:launchMode="singleTask"
                   android:taskAffinity="org.mozilla.gecko.WEBAPP"
-                  android:process=":@ANDROID_PACKAGE_NAME@.WebApp"
+                  android:process=":@ANDROID_PACKAGE_NAME@.Webapp"
                   android:excludeFromRecents="true"
                   android:theme="@style/Gecko.App">
             <intent-filter>
                 <action android:name="org.mozilla.gecko.WEBAPP" />
             </intent-filter>
             <intent-filter>
                 <action android:name="org.mozilla.gecko.ACTION_ALERT_CALLBACK" />
             </intent-filter>
         </activity>
 
-        <!-- Declare a predefined number of WebApp<num> activities. These are
+        <!-- Declare a predefined number of Webapp<num> activities. These are
              used so that each web app can launch in its own process. Keep
              this number in sync with the total number of web apps handled in
-             WebAppAllocator. -->
+             WebappAllocator. -->
 
-#define FRAGMENT WebAppManifestFragment.xml.frag.in
-#include WebAppFragmentRepeater.inc
+#define FRAGMENT WebappManifestFragment.xml.frag.in
+#include WebappFragmentRepeater.inc
 
         <!-- Masquerade as the Resolver so that we can be opened from the Marketplace. -->
         <activity-alias
             android:name="com.android.internal.app.ResolverActivity"
             android:targetActivity=".App"
             android:exported="true" />
 
         <receiver android:name="org.mozilla.gecko.GeckoUpdateReceiver">
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -2710,17 +2710,17 @@ public abstract class GeckoApp
             versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
         } catch (NameNotFoundException e) {
             Log.wtf(LOGTAG, getPackageName() + " not found", e);
         }
         return versionCode;
     }
 
     protected boolean getIsDebuggable() {
-        // Return false so Fennec doesn't appear to be debuggable.  WebAppImpl
+        // Return false so Fennec doesn't appear to be debuggable.  WebappImpl
         // then overrides this and returns the value of android:debuggable for
         // the webapp APK, so webapps get the behavior supported by this method
         // (i.e. automatic configuration and enabling of the remote debugger).
         return false;
 
         // If we ever want to expose this for Fennec, here's how we would do it:
         // int flags = 0;
         // try {
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -715,17 +715,17 @@ public class GeckoAppShell
         System.exit(0);
     }
 
     @WrapElementForJNI
     static void scheduleRestart() {
         gRestartScheduled = true;
     }
 
-    public static Intent getWebAppIntent(String aURI, String aOrigin, String aTitle, Bitmap aIcon) {
+    public static Intent getWebappIntent(String aURI, String aOrigin, String aTitle, Bitmap aIcon) {
         Intent intent;
 
         if (AppConstants.MOZ_ANDROID_SYNTHAPKS) {
             Allocator slots = Allocator.getInstance(getContext());
             int index = slots.getIndexForOrigin(aOrigin);
 
             if (index == -1) {
                 return null;
@@ -733,31 +733,31 @@ public class GeckoAppShell
             String packageName = slots.getAppForIndex(index);
             intent = getContext().getPackageManager().getLaunchIntentForPackage(packageName);
             if (aURI != null) {
                 intent.setData(Uri.parse(aURI));
             }
         } else {
             int index;
             if (aIcon != null && !TextUtils.isEmpty(aTitle))
-                index = WebAppAllocator.getInstance(getContext()).findAndAllocateIndex(aOrigin, aTitle, aIcon);
+                index = WebappAllocator.getInstance(getContext()).findAndAllocateIndex(aOrigin, aTitle, aIcon);
             else
-                index = WebAppAllocator.getInstance(getContext()).getIndexForApp(aOrigin);
+                index = WebappAllocator.getInstance(getContext()).getIndexForApp(aOrigin);
 
             if (index == -1)
                 return null;
 
-            intent = getWebAppIntent(index, aURI);
+            intent = getWebappIntent(index, aURI);
         }
 
         return intent;
     }
 
-    // The old implementation of getWebAppIntent.  Not used by MOZ_ANDROID_SYNTHAPKS.
-    public static Intent getWebAppIntent(int aIndex, String aURI) {
+    // The old implementation of getWebappIntent.  Not used by MOZ_ANDROID_SYNTHAPKS.
+    public static Intent getWebappIntent(int aIndex, String aURI) {
         Intent intent = new Intent();
         intent.setAction(GeckoApp.ACTION_WEBAPP_PREFIX + aIndex);
         intent.setData(Uri.parse(aURI));
         intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
                             AppConstants.ANDROID_PACKAGE_NAME + ".WebApps$WebApp" + aIndex);
         return intent;
     }
 
@@ -802,17 +802,17 @@ public class GeckoAppShell
     /**
      * Call this method only on the background thread.
      */
     private static void doCreateShortcut(final String aTitle, final String aURI, final String aUniqueURI,
                                          final Bitmap aIcon, final String aType) {
         // The intent to be launched by the shortcut.
         Intent shortcutIntent;
         if (aType.equalsIgnoreCase(SHORTCUT_TYPE_WEBAPP)) {
-            shortcutIntent = getWebAppIntent(aURI, aUniqueURI, aTitle, aIcon);
+            shortcutIntent = getWebappIntent(aURI, aUniqueURI, aTitle, aIcon);
         } else {
             shortcutIntent = new Intent();
             shortcutIntent.setAction(GeckoApp.ACTION_BOOKMARK);
             shortcutIntent.setData(Uri.parse(aURI));
             shortcutIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
                                         AppConstants.BROWSER_INTENT_CLASS);
         }
 
@@ -839,17 +839,17 @@ public class GeckoAppShell
 
     public static void removeShortcut(final String aTitle, final String aURI, final String aUniqueURI, final String aType) {
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 // the intent to be launched by the shortcut
                 Intent shortcutIntent;
                 if (aType.equalsIgnoreCase(SHORTCUT_TYPE_WEBAPP)) {
-                    shortcutIntent = getWebAppIntent(aURI, aUniqueURI, "", null);
+                    shortcutIntent = getWebappIntent(aURI, aUniqueURI, "", null);
                     if (shortcutIntent == null)
                         return;
                 } else {
                     shortcutIntent = new Intent();
                     shortcutIntent.setAction(GeckoApp.ACTION_BOOKMARK);
                     shortcutIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
                                                 AppConstants.BROWSER_INTENT_CLASS);
                     shortcutIntent.setData(Uri.parse(aURI));
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -39,17 +39,17 @@ DEFINES += \
   -DMOZ_ANDROID_SHARED_FXACCOUNT_TYPE="$(MOZ_ANDROID_SHARED_FXACCOUNT_TYPE)" \
   -DMOZ_APP_BUILDID=$(MOZ_APP_BUILDID) \
   -DMOZ_BUILD_TIMESTAMP=$(MOZ_BUILD_TIMESTAMP) \
   -DUA_BUILDID=$(UA_BUILDID) \
   $(NULL)
 
 GARBAGE += \
   AndroidManifest.xml  \
-  WebAppManifestFragment.xml.frag \
+  WebappManifestFragment.xml.frag \
   classes.dex  \
   gecko.ap_  \
   res/values/strings.xml \
   .aapt.deps \
   fennec_ids.txt \
   javah.out \
   jni-stubs.inc \
   GeneratedJNIWrappers.cpp \
@@ -137,17 +137,17 @@ android_package_dir = $(addprefix genera
 
 # These _PP_JAVAFILES are specified in moz.build and defined in
 # backend.mk, which is included by config.mk.  Therefore this needs to
 # be defined after config.mk is included.
 PP_JAVAFILES := $(filter-out $(gecko_package_dir)/R.java,$(gecko-mozglue_PP_JAVAFILES) $(gecko-browser_PP_JAVAFILES))
 
 manifest := \
   AndroidManifest.xml.in \
-  WebAppManifestFragment.xml.frag.in \
+  WebappManifestFragment.xml.frag.in \
   $(NULL)
 
 PP_TARGETS += manifest
 
 # Certain source files need to be preprocessed.  This special rule
 # generates these files into generated/org/mozilla/gecko for
 # consumption by the build system and IDEs.
 
@@ -215,17 +215,17 @@ geckoview_resources.zip: $(android_res_f
 # makefile, and trying to work around the lack of information, we
 # force a rebuild of gecko.ap_ during packaging.  See below.
 
 res/values/strings.xml: FORCE
 	$(MAKE) -C locales
 
 all_resources = \
   $(CURDIR)/AndroidManifest.xml \
-  $(CURDIR)/WebAppManifestFragment.xml.frag \
+  $(CURDIR)/WebappManifestFragment.xml.frag \
   $(android_res_files) \
   $(ANDROID_GENERATED_RESFILES) \
   $(NULL)
 
 # All of generated/org/mozilla/gecko/R.java, gecko.ap_, and R.txt are
 # produced by aapt; this saves aapt invocations.
 
 $(gecko_package_dir)/R.java: .aapt.deps
--- a/mobile/android/base/WebApps.java.in
+++ b/mobile/android/base/WebApps.java.in
@@ -2,16 +2,16 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #filter substitution
 package @ANDROID_PACKAGE_NAME@;
 
 /**
- * Declare a predefined number of WebApp<num> classes to the WebApps class.
+ * Declare a predefined number of Webapp<num> classes to the Webapps class.
  * These are used so that each web app can launch in its own process. Keep this
- * number in sync with the number of web apps handled in WebAppAllocator.
+ * number in sync with the number of web apps handled in WebappAllocator.
  */
 public final class WebApps {
-#define FRAGMENT WebAppsFragment.java.frag
-#include WebAppFragmentRepeater.inc
+#define FRAGMENT WebappsFragment.java.frag
+#include WebappFragmentRepeater.inc
 }
rename from mobile/android/base/WebApp.java.in
rename to mobile/android/base/Webapp.java.in
--- a/mobile/android/base/WebApp.java.in
+++ b/mobile/android/base/Webapp.java.in
@@ -2,17 +2,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/. */
 
 #filter substitution
 package @ANDROID_PACKAGE_NAME@;
 
 #ifdef MOZ_ANDROID_SYNTHAPKS
-import org.mozilla.gecko.webapp.WebAppImpl;
+import org.mozilla.gecko.webapp.WebappImpl;
 #else
-import org.mozilla.gecko.WebAppImpl;
+import org.mozilla.gecko.WebappImpl;
 #endif
 
 /**
- * This class serves only as a namespace wrapper for WebAppImpl.
+ * This class serves only as a namespace wrapper for WebappImpl.
  */
-public class WebApp extends WebAppImpl {}
+public class Webapp extends WebappImpl {}
rename from mobile/android/base/WebAppAllocator.java
rename to mobile/android/base/WebappAllocator.java
--- a/mobile/android/base/WebAppAllocator.java
+++ b/mobile/android/base/WebappAllocator.java
@@ -11,37 +11,37 @@ import org.mozilla.gecko.util.ThreadUtil
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
 import android.graphics.Bitmap;
 import android.util.Log;
 
 import java.util.ArrayList;
 
-public class WebAppAllocator {
-    private final String LOGTAG = "GeckoWebAppAllocator";
-    // The number of WebApp# and WEBAPP# activites/apps/intents
+public class WebappAllocator {
+    private final String LOGTAG = "GeckoWebappAllocator";
+    // The number of Webapp# and WEBAPP# activites/apps/intents
     private final static int MAX_WEB_APPS = 100;
 
-    protected static WebAppAllocator sInstance = null;
-    public static WebAppAllocator getInstance() {
+    protected static WebappAllocator sInstance = null;
+    public static WebappAllocator getInstance() {
         return getInstance(GeckoAppShell.getContext());
     }
 
-    public static synchronized WebAppAllocator getInstance(Context cx) {
+    public static synchronized WebappAllocator getInstance(Context cx) {
         if (sInstance == null) {
-            sInstance = new WebAppAllocator(cx);
+            sInstance = new WebappAllocator(cx);
         }
 
         return sInstance;
     }
 
     SharedPreferences mPrefs;
 
-    protected WebAppAllocator(Context context) {
+    protected WebappAllocator(Context context) {
         mPrefs = context.getSharedPreferences("webapps", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
     }
 
     public static String appKey(int index) {
         return "app" + index;
     }
 
     static public String iconKey(int index) {
rename from mobile/android/base/WebAppFragmentRepeater.inc
rename to mobile/android/base/WebappFragmentRepeater.inc
rename from mobile/android/base/WebAppImpl.java
rename to mobile/android/base/WebappImpl.java
--- a/mobile/android/base/WebAppImpl.java
+++ b/mobile/android/base/WebappImpl.java
@@ -21,18 +21,18 @@ import android.graphics.drawable.Gradien
 import android.view.animation.AnimationUtils;
 import android.view.animation.Animation;
 import android.widget.ImageView;
 import android.view.Display;
 
 import java.net.URL;
 import java.io.File;
 
-public class WebAppImpl extends GeckoApp {
-    private static final String LOGTAG = "GeckoWebAppImpl";
+public class WebappImpl extends GeckoApp {
+    private static final String LOGTAG = "GeckoWebappImpl";
 
     private URL mOrigin;
     private TextView mTitlebarText = null;
     private View mTitlebar = null;
 
     private View mSplashscreen;
 
     protected int getIndex() { return 0; }
@@ -57,22 +57,22 @@ public class WebAppImpl extends GeckoApp
         String action = getIntent().getAction();
         Bundle extras = getIntent().getExtras();
         String title = extras != null ? extras.getString(Intent.EXTRA_SHORTCUT_NAME) : null;
         setTitle(title != null ? title : "Web App");
 
         mTitlebarText = (TextView)findViewById(R.id.webapp_title);
         mTitlebar = findViewById(R.id.webapp_titlebar);
         if (!action.startsWith(ACTION_WEBAPP_PREFIX)) {
-            Log.e(LOGTAG, "WebApp launch, but intent action is " + action + "!");
+            Log.e(LOGTAG, "Webapp launch, but intent action is " + action + "!");
             return;
         }
 
-        // Try to use the origin stored in the WebAppAllocator first
-        String origin = WebAppAllocator.getInstance(this).getAppForIndex(getIndex());
+        // Try to use the origin stored in the WebappAllocator first
+        String origin = WebappAllocator.getInstance(this).getAppForIndex(getIndex());
         try {
             mOrigin = new URL(origin);
         } catch (java.net.MalformedURLException ex) {
             // If we can't parse the this is an app protocol, just settle for not having an origin
             if (!origin.startsWith("app://")) {
                 return;
             }
 
@@ -85,32 +85,32 @@ public class WebAppImpl extends GeckoApp
             }
         }
     }
 
     @Override
     protected void loadStartupTab(String uri) {
         String action = getIntent().getAction();
         if (GeckoApp.ACTION_WEBAPP_PREFIX.equals(action)) {
-            // This action assumes the uri is not an installed WebApp. We will
-            // use the WebAppAllocator to register the uri with an Android
+            // This action assumes the uri is not an installed Webapp. We will
+            // use the WebappAllocator to register the uri with an Android
             // process so it can run chromeless.
-            int index = WebAppAllocator.getInstance(this).findAndAllocateIndex(uri, "App", (Bitmap) null);
-            Intent appIntent = GeckoAppShell.getWebAppIntent(index, uri);
+            int index = WebappAllocator.getInstance(this).findAndAllocateIndex(uri, "App", (Bitmap) null);
+            Intent appIntent = GeckoAppShell.getWebappIntent(index, uri);
             startActivity(appIntent);
             finish();
         }
     }
 
     private void showSplash() {
         SharedPreferences prefs = getSharedPreferences("webapps", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
 
         // get the favicon dominant color, stored when the app was installed
         int[] colors = new int[2];
-        int dominantColor = prefs.getInt(WebAppAllocator.iconKey(getIndex()), -1);
+        int dominantColor = prefs.getInt(WebappAllocator.iconKey(getIndex()), -1);
 
         // now lighten it, to ensure that the icon stands out in the center
         float[] f = new float[3];
         Color.colorToHSV(dominantColor, f);
         f[2] = Math.min(f[2]*2, 1.0f);
         colors[0] = Color.HSVToColor(255, f);
 
         // now generate a second, slightly darker version of the same color
@@ -139,17 +139,17 @@ public class WebAppImpl extends GeckoApp
             image.startAnimation(fadein);
         }
     }
 
     @Override
     protected String getDefaultProfileName() {
         String action = getIntent().getAction();
         if (!action.startsWith(ACTION_WEBAPP_PREFIX)) {
-            Log.e(LOGTAG, "WebApp launch, but intent action is " + action + "!");
+            Log.e(LOGTAG, "Webapp launch, but intent action is " + action + "!");
             return null;
         }
 
         return "webapp" + action.substring(ACTION_WEBAPP_PREFIX.length());
     }
 
     @Override
     protected boolean getSessionRestoreState(Bundle savedInstanceState) {
rename from mobile/android/base/WebAppManifestFragment.xml.frag.in
rename to mobile/android/base/WebappManifestFragment.xml.frag.in
--- a/mobile/android/base/WebAppManifestFragment.xml.frag.in
+++ b/mobile/android/base/WebappManifestFragment.xml.frag.in
@@ -1,13 +1,13 @@
         <activity android:name=".WebApps$WebApp@APPNUM@"
                   android:label="@string/webapp_generic_name"
                   android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize"
                   android:windowSoftInputMode="stateUnspecified|adjustResize"
-                  android:process=":@ANDROID_PACKAGE_NAME@.WebApp@APPNUM@"
+                  android:process=":@ANDROID_PACKAGE_NAME@.Webapp@APPNUM@"
                   android:theme="@style/Gecko.App"
 #ifdef MOZ_ANDROID_SYNTHAPKS
                   android:launchMode="singleTop"
                   android:exported="true"
         />
 #else
                   android:launchMode="singleTask"
                   android:taskAffinity="org.mozilla.gecko.WEBAPP@APPNUM@"
rename from mobile/android/base/WebAppsFragment.java.frag
rename to mobile/android/base/WebappsFragment.java.frag
--- a/mobile/android/base/WebAppsFragment.java.frag
+++ b/mobile/android/base/WebappsFragment.java.frag
@@ -1,5 +1,5 @@
-public static class WebApp@APPNUM@ extends WebApp {
+public static class WebApp@APPNUM@ extends Webapp {
     @Override
     protected int getIndex() { return @APPNUM@; }
 }
 
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -344,19 +344,19 @@ gbjar.sources += [
     'VideoPlayer.java',
     'webapp/Allocator.java',
     'webapp/ApkResources.java',
     'webapp/Dispatcher.java',
     'webapp/EventListener.java',
     'webapp/InstallHelper.java',
     'webapp/InstallListener.java',
     'webapp/UninstallListener.java',
-    'webapp/WebAppImpl.java',
-    'WebAppAllocator.java',
-    'WebAppImpl.java',
+    'webapp/WebappImpl.java',
+    'WebappAllocator.java',
+    'WebappImpl.java',
     'widget/ActivityChooserModel.java',
     'widget/AllCapsTextView.java',
     'widget/AnimatedHeightLayout.java',
     'widget/ArrowPopup.java',
     'widget/BasicColorPicker.java',
     'widget/ButtonToast.java',
     'widget/CheckableLinearLayout.java',
     'widget/ClickableWhenDisabledEditText.java',
@@ -380,17 +380,17 @@ gbjar.sources += [ thirdparty_source_dir
     'com/googlecode/eyesfree/braille/selfbraille/SelfBrailleClient.java',
     'com/googlecode/eyesfree/braille/selfbraille/WriteData.java',
 ] ]
 android_package_dir = CONFIG['ANDROID_PACKAGE_NAME'].replace('.', '/')
 # All generated sources are handled specially in Makefile.in.  And
 # R.java is handled even more specially than the others!
 gbjar.generated_sources += [ android_package_dir + f for f in [
     '/App.java',
-    '/WebApp.java',
+    '/Webapp.java',
     '/WebApps.java',
 ] ]
 gbjar.generated_sources += [
     'org/mozilla/gecko/AppConstants.java',
     'org/mozilla/gecko/R.java',
     'org/mozilla/gecko/SysInfo.java',
     'org/mozilla/gecko/widget/GeckoEditText.java',
     'org/mozilla/gecko/widget/GeckoImageButton.java',
--- a/mobile/android/base/webapp/Allocator.java
+++ b/mobile/android/base/webapp/Allocator.java
@@ -13,22 +13,22 @@ import android.content.SharedPreferences
 import android.content.SharedPreferences.Editor;
 
 import java.util.ArrayList;
 
 import android.util.Log;
 
 public class Allocator {
 
-    private final String LOGTAG = "GeckoWebAppAllocator";
+    private final String LOGTAG = "GeckoWebappAllocator";
 
     private static final String PREFIX_ORIGIN = "webapp-origin-";
     private static final String PREFIX_PACKAGE_NAME = "webapp-package-name-";
 
-    // The number of WebApp# and WEBAPP# activites/apps/intents
+    // The number of Webapp# and WEBAPP# activities/apps/intents
     private final static int MAX_WEB_APPS = 100;
 
     protected static Allocator sInstance = null;
     public static Allocator getInstance() {
         return getInstance(GeckoAppShell.getContext());
     }
 
     public static synchronized Allocator getInstance(Context cx) {
--- a/mobile/android/base/webapp/ApkResources.java
+++ b/mobile/android/base/webapp/ApkResources.java
@@ -16,17 +16,17 @@ import android.content.pm.PackageManager
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Environment;
 import android.util.Log;
 
 public class ApkResources {
-    private static final String LOGTAG = "GeckoWebAppApkResources";
+    private static final String LOGTAG = "GeckoWebappApkResources";
     private final String mPackageName;
     private final ApplicationInfo mInfo;
     private final Context mContext;
 
     public ApkResources(Context context, String packageName) throws NameNotFoundException {
         mPackageName = packageName;
         mInfo = context.getPackageManager().getApplicationInfo(
                     mPackageName, PackageManager.GET_META_DATA);
@@ -53,17 +53,17 @@ public class ApkResources {
         return readResource(context, "mini");
     }
 
     public String getManifestUrl() {
         return metadata().getString("manifestUrl");
     }
 
     public boolean isPackaged() {
-        return "packaged".equals(getWebAppType());
+        return "packaged".equals(getWebappType());
     }
 
     public boolean isDebuggable() {
         return (mInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
     }
 
     private String readResource(Context context, String resourceName) {
         Uri resourceUri = Uri.parse("android.resource://" + mPackageName
@@ -89,17 +89,17 @@ public class ApkResources {
     public Uri getAppIconUri() {
         return Uri.parse("android.resource://" + mPackageName + "/" + info().icon);
     }
 
     public Drawable getAppIcon() {
         return info().loadIcon(mContext.getPackageManager());
     }
 
-    public String getWebAppType() {
+    public String getWebappType() {
         return metadata().getString("webapp");
     }
 
     public String getAppName() {
         return info().name;
     }
 
     /**
--- a/mobile/android/base/webapp/Dispatcher.java
+++ b/mobile/android/base/webapp/Dispatcher.java
@@ -6,34 +6,40 @@
 package org.mozilla.gecko.webapp;
 
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
 
 public class Dispatcher extends Activity {
-    private static final String LOGTAG = "GeckoWebAppDispatcher";
+    private static final String LOGTAG = "GeckoWebappDispatcher";
 
     @Override
     protected void onCreate(Bundle bundle) {
         super.onCreate(bundle);
 
         Allocator allocator = Allocator.getInstance(getApplicationContext());
 
         if (bundle == null) {
             bundle = getIntent().getExtras();
         }
 
         if (bundle == null) {
             Log.e(LOGTAG, "Passed intent data missing.");
+            return;
         }
 
         String packageName = bundle.getString("packageName");
 
+        if (packageName == null) {
+            Log.e(LOGTAG, "Package name data missing.");
+            return;
+        }
+
         int index = allocator.getIndexForApp(packageName);
         boolean isInstalled = index >= 0;
         if (!isInstalled) {
             index = allocator.findOrAllocatePackage(packageName);
         }
 
         // Copy the intent, without interfering with it.
         Intent intent = new Intent(getIntent());
--- a/mobile/android/base/webapp/EventListener.java
+++ b/mobile/android/base/webapp/EventListener.java
@@ -10,17 +10,17 @@ import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.favicons.decoders.FaviconDecoder;
 import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.util.ActivityResultHandler;
 import org.mozilla.gecko.util.EventDispatcher;
 import org.mozilla.gecko.util.GeckoEventListener;
 import org.mozilla.gecko.util.GeckoEventResponder;
 import org.mozilla.gecko.util.ThreadUtils;
-import org.mozilla.gecko.WebAppAllocator;
+import org.mozilla.gecko.WebappAllocator;
 
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -35,17 +35,17 @@ import java.util.List;
 import java.util.Set;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
 public class EventListener implements GeckoEventListener, GeckoEventResponder {
 
-    private static final String LOGTAG = "GeckoWebAppEventListener";
+    private static final String LOGTAG = "GeckoWebappEventListener";
 
     private EventListener() { }
 
     private static EventListener mEventListener;
     private String mCurrentResponse = "";
 
     private static EventListener getEventListener() {
         if (mEventListener == null) {
@@ -58,127 +58,127 @@ public class EventListener implements Ge
         GeckoAppShell.getEventDispatcher().registerEventListener(event, EventListener.getEventListener());
     }
 
     private static void unregisterEventListener(String event) {
         GeckoAppShell.getEventDispatcher().unregisterEventListener(event, EventListener.getEventListener());
     }
 
     public static void registerEvents() {
-        registerEventListener("WebApps:PreInstall");
-        registerEventListener("WebApps:InstallApk");
-        registerEventListener("WebApps:PostInstall");
-        registerEventListener("WebApps:Open");
-        registerEventListener("WebApps:Uninstall");
-        registerEventListener("WebApps:GetApkVersions");
+        registerEventListener("Webapps:Preinstall");
+        registerEventListener("Webapps:InstallApk");
+        registerEventListener("Webapps:Postinstall");
+        registerEventListener("Webapps:Open");
+        registerEventListener("Webapps:Uninstall");
+        registerEventListener("Webapps:GetApkVersions");
     }
 
     public static void unregisterEvents() {
-        unregisterEventListener("WebApps:PreInstall");
-        unregisterEventListener("WebApps:InstallApk");
-        unregisterEventListener("WebApps:PostInstall");
-        unregisterEventListener("WebApps:Open");
-        unregisterEventListener("WebApps:Uninstall");
-        unregisterEventListener("WebApps:GetApkVersions");
+        unregisterEventListener("Webapps:Preinstall");
+        unregisterEventListener("Webapps:InstallApk");
+        unregisterEventListener("Webapps:Postinstall");
+        unregisterEventListener("Webapps:Open");
+        unregisterEventListener("Webapps:Uninstall");
+        unregisterEventListener("Webapps:GetApkVersions");
     }
 
     @Override
     public void handleMessage(String event, JSONObject message) {
         try {
-            if (AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("WebApps:InstallApk")) {
+            if (AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("Webapps:InstallApk")) {
                 installApk(GeckoAppShell.getGeckoInterface().getActivity(), message.getString("filePath"), message.getString("data"));
-            } else if (event.equals("WebApps:PostInstall")) {
+            } else if (event.equals("Webapps:Postinstall")) {
                 if (AppConstants.MOZ_ANDROID_SYNTHAPKS) {
-                    postInstallWebApp(message.getString("apkPackageName"), message.getString("origin"));
+                    postInstallWebapp(message.getString("apkPackageName"), message.getString("origin"));
                 } else {
-                    postInstallWebApp(message.getString("name"),
+                    postInstallWebapp(message.getString("name"),
                                       message.getString("manifestURL"),
                                       message.getString("origin"),
                                       message.getString("iconURL"),
                                       message.getString("originalOrigin"));
                 }
-            } else if (event.equals("WebApps:Open")) {
-                Intent intent = GeckoAppShell.getWebAppIntent(message.getString("manifestURL"),
+            } else if (event.equals("Webapps:Open")) {
+                Intent intent = GeckoAppShell.getWebappIntent(message.getString("manifestURL"),
                                                               message.getString("origin"),
                                                               "", null);
                 if (intent == null) {
                     return;
                 }
                 GeckoAppShell.getGeckoInterface().getActivity().startActivity(intent);
-            } else if (!AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("WebApps:Uninstall")) {
-                uninstallWebApp(message.getString("origin"));
-            } else if (!AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("WebApps:PreInstall")) {
+            } else if (!AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("Webapps:Uninstall")) {
+                uninstallWebapp(message.getString("origin"));
+            } else if (!AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("Webapps:Preinstall")) {
                 String name = message.getString("name");
                 String manifestURL = message.getString("manifestURL");
                 String origin = message.getString("origin");
 
                 // preInstallWebapp will return a File object pointing to the profile directory of the webapp
-                mCurrentResponse = preInstallWebApp(name, manifestURL, origin).toString();
+                mCurrentResponse = preInstallWebapp(name, manifestURL, origin).toString();
             } else if (event.equals("WebApps:GetApkVersions")) {
                 mCurrentResponse = getApkVersions(GeckoAppShell.getGeckoInterface().getActivity(),
                                                   message.getJSONArray("packageNames")).toString();
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
 
     public String getResponse(JSONObject origMessage) {
         String res = mCurrentResponse;
         mCurrentResponse = "";
         return res;
     }
 
     // Not used by MOZ_ANDROID_SYNTHAPKS.
-    public static File preInstallWebApp(String aTitle, String aURI, String aOrigin) {
-        int index = WebAppAllocator.getInstance(GeckoAppShell.getContext()).findAndAllocateIndex(aOrigin, aTitle, (String) null);
+    public static File preInstallWebapp(String aTitle, String aURI, String aOrigin) {
+        int index = WebappAllocator.getInstance(GeckoAppShell.getContext()).findAndAllocateIndex(aOrigin, aTitle, (String) null);
         GeckoProfile profile = GeckoProfile.get(GeckoAppShell.getContext(), "webapp" + index);
         return profile.getDir();
     }
 
     // Not used by MOZ_ANDROID_SYNTHAPKS.
-    public static void postInstallWebApp(String aTitle, String aURI, String aOrigin, String aIconURL, String aOriginalOrigin) {
-        WebAppAllocator allocator = WebAppAllocator.getInstance(GeckoAppShell.getContext());
+    public static void postInstallWebapp(String aTitle, String aURI, String aOrigin, String aIconURL, String aOriginalOrigin) {
+        WebappAllocator allocator = WebappAllocator.getInstance(GeckoAppShell.getContext());
         int index = allocator.getIndexForApp(aOriginalOrigin);
 
         assert aIconURL != null;
 
         final int preferredSize = GeckoAppShell.getPreferredIconSize();
         Bitmap icon = FaviconDecoder.getMostSuitableBitmapFromDataURI(aIconURL, preferredSize);
 
         assert aOrigin != null && index != -1;
         allocator.updateAppAllocation(aOrigin, index, icon);
 
         GeckoAppShell.createShortcut(aTitle, aURI, aOrigin, icon, "webapp");
     }
 
     // Used by MOZ_ANDROID_SYNTHAPKS.
-    public static void postInstallWebApp(String aPackageName, String aOrigin) {
+    public static void postInstallWebapp(String aPackageName, String aOrigin) {
         Allocator allocator = Allocator.getInstance(GeckoAppShell.getContext());
         int index = allocator.findOrAllocatePackage(aPackageName);
         allocator.putOrigin(index, aOrigin);
     }
 
-    public static void uninstallWebApp(final String uniqueURI) {
+    public static void uninstallWebapp(final String uniqueURI) {
         // On uninstall, we need to do a couple of things:
         //   1. nuke the running app process.
         //   2. nuke the profile that was assigned to that webapp
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 int index;
                 index = Allocator.getInstance(GeckoAppShell.getContext()).releaseIndexForApp(uniqueURI);
 
                 // if -1, nothing to do; we didn't think it was installed anyway
                 if (index == -1)
                     return;
 
                 // kill the app if it's running
                 String targetProcessName = GeckoAppShell.getContext().getPackageName();
-                targetProcessName = targetProcessName + ":" + targetProcessName + ".WebApp" + index;
+                targetProcessName = targetProcessName + ":" + targetProcessName + ".Webapp" + index;
 
                 ActivityManager am = (ActivityManager) GeckoAppShell.getContext().getSystemService(Context.ACTIVITY_SERVICE);
                 List<ActivityManager.RunningAppProcessInfo> procs = am.getRunningAppProcesses();
                 if (procs != null) {
                     for (ActivityManager.RunningAppProcessInfo proc : procs) {
                         if (proc.processName.equals(targetProcessName)) {
                             android.os.Process.killProcess(proc.pid);
                             break;
--- a/mobile/android/base/webapp/InstallHelper.java
+++ b/mobile/android/base/webapp/InstallHelper.java
@@ -22,18 +22,18 @@ import org.mozilla.gecko.util.GeckoEvent
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.util.Log;
 
 public class InstallHelper implements GeckoEventListener {
-    private static final String LOGTAG = "GeckoWebAppInstallHelper";
-    private static final String[] INSTALL_EVENT_NAMES = new String[] {"WebApps:PostInstall"};
+    private static final String LOGTAG = "GeckoWebappInstallHelper";
+    private static final String[] INSTALL_EVENT_NAMES = new String[] {"Webapps:Postinstall"};
     private final Context mContext;
     private final InstallCallback mCallback;
     private final ApkResources mApkResources;
 
     public static interface InstallCallback {
         // on the GeckoThread
         void installCompleted(InstallHelper installHelper, String event, JSONObject message);
 
@@ -81,17 +81,17 @@ public class InstallHelper implements Ge
         GeckoProfile profile = GeckoProfile.get(mContext, profileName);
 
         try {
             message.put("apkPackageName", mApkResources.getPackageName());
             message.put("manifestUrl", mApkResources.getManifestUrl());
             message.put("title", mApkResources.getAppName());
             message.put("manifest", new JSONObject(mApkResources.getManifest(mContext)));
 
-            String appType = mApkResources.getWebAppType();
+            String appType = mApkResources.getWebappType();
             message.putOpt("type", appType);
             if ("packaged".equals(appType)) {
                 message.putOpt("updateManifest", new JSONObject(mApkResources.getMiniManifest(mContext)));
             }
 
             message.putOpt("profilePath", profile.getDir());
 
             if (mApkResources.isPackaged()) {
--- a/mobile/android/base/webapp/InstallListener.java
+++ b/mobile/android/base/webapp/InstallListener.java
@@ -19,17 +19,17 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Environment;
 import android.text.TextUtils;
 import android.util.Log;
 
 public class InstallListener extends BroadcastReceiver {
 
-    private static String LOGTAG = "GeckoWebAppInstallListener";
+    private static String LOGTAG = "GeckoWebappInstallListener";
     private JSONObject mData = null;
     private String mManifestUrl;
 
     public InstallListener(String manifestUrl, JSONObject data) {
         mData = data;
         mManifestUrl = manifestUrl;
         assert mManifestUrl != null;
     }
--- a/mobile/android/base/webapp/UninstallListener.java
+++ b/mobile/android/base/webapp/UninstallListener.java
@@ -23,17 +23,17 @@ import android.content.pm.PackageManager
 
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.ArrayList;
 
 public class UninstallListener extends BroadcastReceiver {
 
-    private static String LOGTAG = "GeckoWebAppUninstallListener";
+    private static String LOGTAG = "GeckoWebappUninstallListener";
 
     @Override
     public void onReceive(Context context, Intent intent) {
         if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
             Log.i(LOGTAG, "Package is being replaced; ignoring removal intent");
             return;
         }
 
rename from mobile/android/base/webapp/WebAppImpl.java
rename to mobile/android/base/webapp/WebappImpl.java
--- a/mobile/android/base/webapp/WebAppImpl.java
+++ b/mobile/android/base/webapp/WebappImpl.java
@@ -37,18 +37,18 @@ import android.os.Bundle;
 import android.util.Log;
 import android.view.Display;
 import android.view.View;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.widget.ImageView;
 import android.widget.TextView;
 
-public class WebAppImpl extends GeckoApp implements InstallCallback {
-    private static final String LOGTAG = "GeckoWebAppImpl";
+public class WebappImpl extends GeckoApp implements InstallCallback {
+    private static final String LOGTAG = "GeckoWebappImpl";
 
     private URL mOrigin;
     private TextView mTitlebarText = null;
     private View mTitlebar = null;
 
     private View mSplashscreen;
 
     private ApkResources mApkResources;
@@ -122,17 +122,17 @@ public class WebAppImpl extends GeckoApp
                 }
             } else {
                 // an install is already happening, so we should let it complete.
                 Log.i(LOGTAG, "Waiting for existing install to complete");
                 installHelper.registerGeckoListener();
             }
             return;
         } else {
-            launchWebApp(origin, mApkResources.getManifestUrl(), mApkResources.getAppName());
+            launchWebapp(origin, mApkResources.getManifestUrl(), mApkResources.getAppName());
         }
 
         setTitle(mApkResources.getAppName());
     }
 
     @Override
     protected String getURIFromIntent(Intent intent) {
         String uri = super.getURIFromIntent(intent);
@@ -285,28 +285,28 @@ public class WebAppImpl extends GeckoApp
     }
 
     @Override
     public void installCompleted(InstallHelper installHelper, String event, JSONObject message) {
         if (event == null) {
             return;
         }
 
-        if (event.equals("WebApps:PostInstall")) {
+        if (event.equals("Webapps:Postinstall")) {
             String origin = message.optString("origin");
-            launchWebApp(origin, mApkResources.getManifestUrl(), mApkResources.getAppName());
+            launchWebapp(origin, mApkResources.getManifestUrl(), mApkResources.getAppName());
         }
     }
 
     @Override
     public void installErrored(InstallHelper installHelper, Exception exception) {
         Log.e(LOGTAG, "Install errored", exception);
     }
 
-    public void launchWebApp(String origin, String manifestUrl, String name) {
+    public void launchWebapp(String origin, String manifestUrl, String name) {
         try {
             mOrigin = new URL(origin);
         } catch (java.net.MalformedURLException ex) {
             // If we can't parse the this is an app protocol, just settle for not having an origin
             if (!origin.startsWith("app://")) {
                 return;
             }
 
rename from mobile/android/chrome/content/WebAppRT.js
rename to mobile/android/chrome/content/WebappRT.js
--- a/mobile/android/chrome/content/WebAppRT.js
+++ b/mobile/android/chrome/content/WebappRT.js
@@ -19,17 +19,17 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 
 function pref(name, value) {
   return {
     name: name,
     value: value
   }
 }
 
-let WebAppRT = {
+let WebappRT = {
   DEFAULT_PREFS_FILENAME: "default-prefs.js",
 
   prefs: [
     // Disable all add-on locations other than the profile (which can't be disabled this way)
     pref("extensions.enabledScopes", 1),
     // Auto-disable any add-ons that are "dropped in" to the profile
     pref("extensions.autoDisableScopes", 1),
     // Disable add-on installation via the web-exposed APIs
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -466,19 +466,19 @@ var BrowserApp = {
    */
   setLocale: function (locale) {
     console.log("browser.js: requesting locale set: " + locale);
     sendMessageToJava({ type: "Locale:Set", locale: locale });
   },
 
   _initRuntime: function(status, url, callback) {
     let sandbox = {};
-    Services.scriptloader.loadSubScript("chrome://browser/content/WebAppRT.js", sandbox);
-    window.WebAppRT = sandbox.WebAppRT;
-    WebAppRT.init(status, url, callback);
+    Services.scriptloader.loadSubScript("chrome://browser/content/WebappRT.js", sandbox);
+    window.WebappRT = sandbox.WebappRT;
+    WebappRT.init(status, url, callback);
   },
 
   initContextMenu: function ba_initContextMenu() {
     // TODO: These should eventually move into more appropriate classes
     NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.openInNewTab"),
       NativeWindow.contextmenus.linkOpenableNonPrivateContext,
       function(aTarget) {
         let url = NativeWindow.contextmenus._getLinkURL(aTarget);
@@ -7123,33 +7123,33 @@ var WebappsUI = {
       case "webapps-ask-install":
         this.doInstall(data);
         break;
       case "webapps-launch":
         this.openURL(data.manifestURL, data.origin);
         break;
       case "webapps-uninstall":
         sendMessageToJava({
-          type: "WebApps:Uninstall",
+          type: "Webapps:Uninstall",
           origin: data.origin
         });
         break;
     }
   },
 
   doInstall: function doInstall(aData) {
     let jsonManifest = aData.isPackage ? aData.app.updateManifest : aData.app.manifest;
     let manifest = new ManifestHelper(jsonManifest, aData.app.origin);
     let showPrompt = true;
 
     if (!showPrompt || Services.prompt.confirm(null, Strings.browser.GetStringFromName("webapps.installTitle"), manifest.name + "\n" + aData.app.origin)) {
       // Get a profile for the app to be installed in. We'll download everything before creating the icons.
       let origin = aData.app.origin;
       let profilePath = sendMessageToJava({
-        type: "WebApps:PreInstall",
+        type: "Webapps:Preinstall",
         name: manifest.name,
         manifestURL: aData.app.manifestURL,
         origin: origin
       });
       if (profilePath) {
         let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
         file.initWithPath(profilePath);
 
@@ -7171,17 +7171,17 @@ var WebappsUI = {
                   persist.persistFlags = Ci.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
                   persist.persistFlags |= Ci.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
 
                   let source = Services.io.newURI(fullsizeIcon, "UTF8", null);
                   persist.saveURI(source, null, null, null, null, iconFile, null);
 
                   // aData.app.origin may now point to the app: url that hosts this app
                   sendMessageToJava({
-                    type: "WebApps:PostInstall",
+                    type: "Webapps:Postinstall",
                     name: localeManifest.name,
                     manifestURL: aData.app.manifestURL,
                     originalOrigin: origin,
                     origin: aData.app.origin,
                     iconURL: fullsizeIcon
                   });
                   if (!!aData.isPackage) {
                     // For packaged apps, put a notification in the notification bar.
@@ -7239,17 +7239,17 @@ var WebappsUI = {
       OS.File.writeAtomic(aFile.path, array, { tmpPath: aFile.path + ".tmp" }).then(null, function onError(reason) {
         console.log("Error writing default prefs: " + reason);
       });
     }
   },
 
   openURL: function openURL(aManifestURL, aOrigin) {
     sendMessageToJava({
-      type: "WebApps:Open",
+      type: "Webapps:Open",
       manifestURL: aManifestURL,
       origin: aOrigin
     });
   },
 
   get iconSize() {
     let iconSize = 64;
     try {
--- a/mobile/android/chrome/jar.mn
+++ b/mobile/android/chrome/jar.mn
@@ -34,17 +34,17 @@ chrome.jar:
 * content/browser.js                   (content/browser.js)
   content/bindings/checkbox.xml        (content/bindings/checkbox.xml)
   content/bindings/settings.xml        (content/bindings/settings.xml)
   content/downloads.js                 (content/downloads.js)
   content/netError.xhtml               (content/netError.xhtml)
   content/SelectHelper.js              (content/SelectHelper.js)
   content/SelectionHandler.js          (content/SelectionHandler.js)
   content/dbg-browser-actors.js        (content/dbg-browser-actors.js)
-* content/WebAppRT.js                  (content/WebAppRT.js)
+* content/WebappRT.js                  (content/WebappRT.js)
   content/InputWidgetHelper.js         (content/InputWidgetHelper.js)
   content/WebrtcUI.js                  (content/WebrtcUI.js)
   content/MemoryObserver.js            (content/MemoryObserver.js)
   content/ConsoleAPI.js                (content/ConsoleAPI.js)
   content/PluginHelper.js              (content/PluginHelper.js)
   content/OfflineApps.js               (content/OfflineApps.js)
   content/MasterPassword.js            (content/MasterPassword.js)
   content/FindHelper.js                (content/FindHelper.js)
--- a/mobile/android/modules/WebappManager.jsm
+++ b/mobile/android/modules/WebappManager.jsm
@@ -80,17 +80,17 @@ this.WebappManager = {
     } catch(ex) {
       aMessage.error = ex;
       aMessageManager.sendAsyncMessage("Webapps:Install:Return:KO", aMessage);
       log("error downloading APK: " + ex);
       return;
     }
 
     sendMessageToJava({
-      type: "WebApps:InstallApk",
+      type: "Webapps:InstallApk",
       filePath: filePath,
       data: JSON.stringify(aMessage),
     });
   }).bind(this)); },
 
   _downloadApk: function(aManifestUrl) {
     log("_downloadApk for " + aManifestUrl);
     let deferred = Promise.defer();
@@ -152,31 +152,31 @@ this.WebappManager = {
     }
 
     DOMApplicationRegistry.registryReady.then(() => {
       DOMApplicationRegistry.confirmInstall(aData, file, (function(aManifest) {
         let localeManifest = new ManifestHelper(aManifest, aData.app.origin);
 
         // aData.app.origin may now point to the app: url that hosts this app.
         sendMessageToJava({
-          type: "WebApps:PostInstall",
+          type: "Webapps:Postinstall",
           apkPackageName: aData.app.apkPackageName,
           origin: aData.app.origin,
         });
 
         this.writeDefaultPrefs(file, localeManifest);
       }).bind(this));
     });
   },
 
   launch: function({ manifestURL, origin }) {
     log("launchWebapp: " + manifestURL);
 
     sendMessageToJava({
-      type: "WebApps:Open",
+      type: "Webapps:Open",
       manifestURL: manifestURL,
       origin: origin
     });
   },
 
   uninstall: function(aData) {
     log("uninstall: " + aData.manifestURL);
 
@@ -280,17 +280,17 @@ this.WebappManager = {
     try {
       let installedApps = yield this._getInstalledApps();
       if (installedApps.length === 0) {
         return;
       }
 
       // Map APK names to APK versions.
       let apkNameToVersion = JSON.parse(sendMessageToJava({
-        type: "WebApps:GetApkVersions",
+        type: "Webapps:GetApkVersions",
         packageNames: installedApps.map(app => app.packageName).filter(packageName => !!packageName)
       }));
 
       // Map manifest URLs to APK versions, which is what the service needs
       // in order to tell us which apps are outdated; and also map them to app
       // objects, which the downloader/installer uses to download/install APKs.
       // XXX Will this cause us to update apps without packages, and if so,
       // does that satisfy the legacy migration story?
@@ -445,21 +445,21 @@ this.WebappManager = {
       icon: "drawable://alert_app",
     }).dismissed;
 
     if (accepted) {
       // The user accepted the notification, so install the downloaded APKs.
       for (let apk of downloadedApks) {
         let msg = {
           app: apk.app,
-          // TODO: figure out why WebApps:InstallApk needs the "from" property.
+          // TODO: figure out why Webapps:InstallApk needs the "from" property.
           from: apk.app.installOrigin,
         };
         sendMessageToJava({
-          type: "WebApps:InstallApk",
+          type: "Webapps:InstallApk",
           filePath: apk.filePath,
           data: JSON.stringify(msg),
         });
       }
     } else {
       // The user cancelled the notification, so remove the downloaded APKs.
       for (let apk of downloadedApks) {
         try {
@@ -525,17 +525,21 @@ this.WebappManager = {
       }
     });
   },
 
   writeDefaultPrefs: function(aProfile, aManifest) {
       // build any app specific default prefs
       let prefs = [];
       if (aManifest.orientation) {
-        prefs.push({name:"app.orientation.default", value: aManifest.orientation.join(",") });
+        let orientation = aManifest.orientation;
+        if (Array.isArray(orientation)) {
+          orientation = orientation.join(",");
+        }
+        prefs.push({ name: "app.orientation.default", value: orientation });
       }
 
       // write them into the app profile
       let defaultPrefsFile = aProfile.clone();
       defaultPrefsFile.append(this.DEFAULT_PREFS_FILENAME);
       this._writeData(defaultPrefsFile, prefs);
   },
 
--- a/netwerk/ipc/RemoteOpenFileChild.cpp
+++ b/netwerk/ipc/RemoteOpenFileChild.cpp
@@ -553,16 +553,22 @@ RemoteOpenFileChild::MoveTo(nsIFile *new
 
 NS_IMETHODIMP
 RemoteOpenFileChild::MoveToNative(nsIFile *newParent, const nsACString &newName)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+RemoteOpenFileChild::RenameTo(nsIFile *newParentDir, const nsAString &newName)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 RemoteOpenFileChild::Remove(bool recursive)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 RemoteOpenFileChild::GetPermissions(uint32_t *aPermissions)
 {
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -659,16 +659,21 @@ class RecursiveMakeBackend(CommonBackend
                     '#error "%(cppfile)s uses PL_ARENA_CONST_ALIGN_MASK, '
                     'so it cannot be built in unified mode."\n'
                     '#undef PL_ARENA_CONST_ALIGN_MASK\n'
                     '#endif\n'
                     '#ifdef FORCE_PR_LOG\n'
                     '#error "%(cppfile)s forces NSPR logging, '
                     'so it cannot be built in unified mode."\n'
                     '#undef FORCE_PR_LOG\n'
+                    '#endif\n'
+                    '#ifdef INITGUID\n'
+                    '#error "%(cppfile)s defines INITGUID, '
+                    'so it cannot be built in unified mode."\n'
+                    '#undef INITGUID\n'
                     '#endif')
                 f.write('\n'.join(includeTemplate % { "cppfile": s } for
                                   s in source_filenames))
 
         if include_curdir_build_rules:
             makefile.add_statement('\n'
                 '# Make sometimes gets confused between "foo" and "$(CURDIR)/foo".\n'
                 '# Help it out by explicitly specifiying dependencies.')
--- a/security/manager/ssl/tests/unit/test_cert_signatures.js
+++ b/security/manager/ssl/tests/unit/test_cert_signatures.js
@@ -19,68 +19,89 @@
  * Check in the generated files. These steps are not done as part of the build
  * because we do not want to add a build-time dependency on the OpenSSL or NSS
  * tools or libraries built for the host platform.
  */
 
 do_get_profile(); // must be called before getting nsIX509CertDB
 const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(Ci.nsIX509CertDB);
 
-const ca_usage = 'SSL CA';
-const int_usage = 'Client,Server,Sign,Encrypt,SSL CA,Status Responder';
-const ee_usage = 'Client,Server,Sign,Encrypt';
-
-const cert2usage = {
-  // certs without the "int" prefix are end entity certs.
-  'int-rsa-valid': int_usage,
-  'rsa-valid': ee_usage,
-  'int-p384-valid': int_usage,
-  'p384-valid': ee_usage,
-  'int-dsa-valid': int_usage,
-  'dsa-valid': ee_usage,
-
-  'rsa-valid-int-tampered-ee': "",
-  'p384-valid-int-tampered-ee': "",
-  'dsa-valid-int-tampered-ee': "",
-
-  'int-rsa-tampered': "",
-  'rsa-tampered-int-valid-ee': "",
-  'int-p384-tampered': "",
-  'p384-tampered-int-valid-ee': "",
-  'int-dsa-tampered': "",
-  'dsa-tampered-int-valid-ee': "",
-
-};
-
 function load_ca(ca_name) {
   let ca_filename = ca_name + ".der";
   addCertFromFile(certdb, "test_cert_signatures/" + ca_filename, 'CTu,CTu,CTu');
+}
 
+function check_ca(ca_name) {
   do_print("ca_name=" + ca_name);
   let cert = certdb.findCertByNickname(null, ca_name);
 
   let verified = {};
   let usages = {};
   cert.getUsagesString(true, verified, usages);
-  do_check_eq(ca_usage, usages.value);
+  do_check_eq('SSL CA', usages.value);
 }
 
 function run_test() {
   // Load the ca into mem
   load_ca("ca-rsa");
   load_ca("ca-p384");
   load_ca("ca-dsa");
 
+  run_test_in_mode(true);
+  run_test_in_mode(false);
+}
+
+function run_test_in_mode(useInsanity) {
+  Services.prefs.setBoolPref("security.use_insanity_verification", useInsanity);
+  clearOCSPCache();
+  clearSessionCache();
+
+  check_ca("ca-rsa");
+  check_ca("ca-p384");
+  check_ca("ca-dsa");
+
+  // insanity::pkix does not allow CA certs to be validated for end-entity
+  // usages.
+  let int_usage = useInsanity
+                ? 'SSL CA'
+                : 'Client,Server,Sign,Encrypt,SSL CA,Status Responder';
+
+  // insanity::pkix doesn't implement the Netscape Object Signer restriction.
+  const ee_usage = useInsanity
+                 ? 'Client,Server,Sign,Encrypt,Object Signer'
+                 : 'Client,Server,Sign,Encrypt';
+
+  let cert2usage = {
+    // certs without the "int" prefix are end entity certs.
+    'int-rsa-valid': int_usage,
+    'rsa-valid': ee_usage,
+    'int-p384-valid': int_usage,
+    'p384-valid': ee_usage,
+    'int-dsa-valid': int_usage,
+    'dsa-valid': ee_usage,
+
+    'rsa-valid-int-tampered-ee': "",
+    'p384-valid-int-tampered-ee': "",
+    'dsa-valid-int-tampered-ee': "",
+
+    'int-rsa-tampered': "",
+    'rsa-tampered-int-valid-ee': "",
+    'int-p384-tampered': "",
+    'p384-tampered-int-valid-ee': "",
+    'int-dsa-tampered': "",
+    'dsa-tampered-int-valid-ee': "",
+
+  };
+
   // Load certs first
   for (let cert_name in cert2usage) {
     let cert_filename = cert_name + ".der";
     addCertFromFile(certdb, "test_cert_signatures/" + cert_filename, ',,');
   }
 
-  // Now do the checks
   for (let cert_name in cert2usage) {
     do_print("cert_name=" + cert_name);
 
     let cert = certdb.findCertByNickname(null, cert_name);
 
     let verified = {};
     let usages = {};
     cert.getUsagesString(true, verified, usages);
--- a/security/manager/ssl/tests/unit/test_certificate_usages.js
+++ b/security/manager/ssl/tests/unit/test_certificate_usages.js
@@ -14,99 +14,118 @@
    Check in the generated files. These steps are not done as part of the build
    because we do not want to add a build-time dependency on the OpenSSL or NSS
    tools or libraries built for the host platform.
 */
 
 do_get_profile(); // must be called before getting nsIX509CertDB
 const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(Ci.nsIX509CertDB);
 
-var ca_usages = ['Client,Server,Sign,Encrypt,SSL CA,Status Responder',
-                 'SSL CA',
-                 'Client,Server,Sign,Encrypt,SSL CA,Status Responder',
-
-/* XXX
-  When using PKIX the usage for the fourth CA (key usage= all but certsigning) the
-  usage returned is 'Status Responder' only. (no SSL CA)
-  Thus (self-consistently) the ee_usages are all empty.
-
-  Reading rfc 5280 the combination of basic contraints+usages is not clear:
-   - Asserted key usage keyCertSign MUST have CA basic contraints.
-   - CA NOT asserted => keyCertSignt MUST NOT be asserted.
-
-  But the tests include -> basic CA asserted and Keyusage NOT asserted.
-  In this case, the 'classic' mode uses the 'union' of the capabilites ->
-  the cert is considered a CA. libpkix uses the 'intersection' of
-  capabilites, the cert is NOT considered a CA.
-
-  I think the intersection is a better way to interpret this as the extension
-  is marked as critical.
-
-  This should be: 'Status Responder'
-
-*/
-                 'Client,Server,Sign,Encrypt,Status Responder'];
-
-var ee_usages = [
-                  ['Client,Server,Sign,Encrypt',
-                   'Client,Server,Sign,Encrypt',
-                   'Client,Server,Sign,Encrypt',
-                   '',
-                   'Client,Server,Sign,Encrypt,Object Signer,Status Responder',
-                   'Client,Server',
-                   'Sign,Encrypt,Object Signer',
-                   'Server,Status Responder'
-                   ],
-                  ['Client,Server,Sign,Encrypt',
-                   'Client,Server,Sign,Encrypt',
-                   'Client,Server,Sign,Encrypt',
-                   '',
-                   'Client,Server,Sign,Encrypt,Object Signer,Status Responder',
-                   'Client,Server',
-                   'Sign,Encrypt,Object Signer',
-                   'Server,Status Responder'
-                   ],
-                  ['Client,Server,Sign,Encrypt',
-                   'Client,Server,Sign,Encrypt',
-                   'Client,Server,Sign,Encrypt',
-                   '',
-                   'Client,Server,Sign,Encrypt,Object Signer,Status Responder',
-                   'Client,Server',
-                   'Sign,Encrypt,Object Signer',
-                   'Server,Status Responder'
-                  ],
-
-/* XXX
-  The values for the following block of tests should all be empty
-  */
-
-                  ['Client,Server,Sign,Encrypt',
-                   'Client,Server,Sign,Encrypt',
-                   'Client,Server,Sign,Encrypt',
-                   '',
-                   'Client,Server,Sign,Encrypt,Object Signer,Status Responder',
-                   'Client,Server',
-                   'Sign,Encrypt,Object Signer',
-                   'Server,Status Responder'
-                  ]
-                ];
-
+const gNumCAs = 4;
 
 function run_test() {
   //ca's are one based!
-  for (var i = 0; i < ca_usages.length; i++) {
+  for (var i = 0; i < gNumCAs; i++) {
     var ca_name = "ca-" + (i + 1);
     var ca_filename = ca_name + ".der";
     addCertFromFile(certdb, "test_certificate_usages/" + ca_filename, "CTu,CTu,CTu");
     do_print("ca_name=" + ca_name);
-    var cert;
-    cert = certdb.findCertByNickname(null, ca_name);
+    var cert = certdb.findCertByNickname(null, ca_name);
+  }
+
+  run_test_in_mode(true);
+  run_test_in_mode(false);
+}
+
+function run_test_in_mode(useInsanity) {
+  Services.prefs.setBoolPref("security.use_insanity_verification", useInsanity);
+  clearOCSPCache();
+  clearSessionCache();
+
+  // insanity::pkix does not allow CA certs to be validated for non-CA usages.
+  var allCAUsages = useInsanity
+                  ? 'SSL CA'
+                  : 'Client,Server,Sign,Encrypt,SSL CA,Status Responder';
+
+  // insanity::pkix doesn't allow CA certificates to have the Status Responder
+  // EKU.
+  var ca_usages = [allCAUsages,
+                   'SSL CA',
+                   allCAUsages,
+                   useInsanity ? ''
+                               : 'Client,Server,Sign,Encrypt,Status Responder'];
+
+  // insanity::pkix doesn't implement the Netscape Object Signer restriction.
+  var basicEndEntityUsages = useInsanity
+                           ? 'Client,Server,Sign,Encrypt,Object Signer'
+                           : 'Client,Server,Sign,Encrypt';
+  var basicEndEntityUsagesWithObjectSigner = basicEndEntityUsages + ",Object Signer"
+
+  // insanity::pkix won't let a certificate with the "Status Responder" EKU get
+  // validated for any other usage.
+  var statusResponderUsages = (useInsanity ? "" : "Server,") + "Status Responder";
+  var statusResponderUsagesFull
+      = useInsanity ? statusResponderUsages
+                    : basicEndEntityUsages + ',Object Signer,Status Responder';
 
+  var ee_usages = [
+    [ basicEndEntityUsages,
+      basicEndEntityUsages,
+      basicEndEntityUsages,
+      '',
+      statusResponderUsagesFull,
+      'Client,Server',
+      'Sign,Encrypt,Object Signer',
+      statusResponderUsages
+    ],
+
+    [ basicEndEntityUsages,
+      basicEndEntityUsages,
+      basicEndEntityUsages,
+      '',
+      statusResponderUsagesFull,
+      'Client,Server',
+      'Sign,Encrypt,Object Signer',
+      statusResponderUsages
+    ],
+
+    [ basicEndEntityUsages,
+      basicEndEntityUsages,
+      basicEndEntityUsages,
+      '',
+      statusResponderUsagesFull,
+      'Client,Server',
+      'Sign,Encrypt,Object Signer',
+      statusResponderUsages
+    ],
+
+    // The CA has isCA=true without keyCertSign.
+    //
+    // The 'classic' NSS mode uses the 'union' of the
+    // capabilites so the cert is considered a CA.
+    // insanity::pkix and libpkix use the intersection of
+    // capabilites, so the cert is NOT considered a CA.
+    [ useInsanity ? '' : basicEndEntityUsages,
+      useInsanity ? '' : basicEndEntityUsages,
+      useInsanity ? '' : basicEndEntityUsages,
+      '',
+      useInsanity ? '' : statusResponderUsagesFull,
+      useInsanity ? '' : 'Client,Server',
+      useInsanity ? '' : 'Sign,Encrypt,Object Signer',
+      useInsanity ? '' : 'Server,Status Responder'
+     ]
+  ];
+
+  do_check_eq(gNumCAs, ca_usages.length);
+
+  for (var i = 0; i < gNumCAs; i++) {
+    var ca_name = "ca-" + (i + 1);
     var verified = {};
     var usages = {};
+    var cert = certdb.findCertByNickname(null, ca_name);
     cert.getUsagesString(true, verified, usages);
     do_print("usages.value=" + usages.value);
     do_check_eq(ca_usages[i], usages.value);
 
     //now the ee, names also one based
     for (var j = 0; j < ee_usages[i].length; j++) {
       var ee_name = "ee-" + (j + 1) + "-" + ca_name;
       var ee_filename = ee_name + ".der";
@@ -115,12 +134,10 @@ function run_test() {
       var ee_cert;
       ee_cert = certdb.findCertByNickname(null, ee_name);
       var verified = {};
       var usages = {};
       ee_cert.getUsagesString(true, verified, usages);
       do_print("cert usages.value=" + usages.value);
       do_check_eq(ee_usages[i][j], usages.value);
     }
-
   }
-
 }
--- a/security/manager/ssl/tests/unit/test_getchain.js
+++ b/security/manager/ssl/tests/unit/test_getchain.js
@@ -65,25 +65,31 @@ function check_getchain(ee_cert, ssl_ca,
   certdb.setCertTrust(ssl_ca, nsIX509Cert.CA_CERT, 0);
   check_matching_issuer_and_getchain(email_ca.serialNumber, ee_cert);
   certdb.setCertTrust(email_ca, nsIX509Cert.CA_CERT, 0);
   // Do a final test on the case of no trust. The results must
   // be cosistent (the actual value is non-deterministic).
   check_matching_issuer_and_getchain(ee_cert.issuer.serialNumber, ee_cert);
 }
 
-function run_test() {
+function run_test_in_mode(useInsanity) {
+  Services.prefs.setBoolPref("security.use_insanity_verification", useInsanity);
+  clearOCSPCache();
+  clearSessionCache();
+
   for (let i = 0 ; i < certList.length; i++) {
     load_cert(certList[i], ',,');
   }
 
   let ee_cert = certdb.findCertByNickname(null, 'ee');
   do_check_false(!ee_cert);
 
   let ca = get_ca_array();
 
   check_getchain(ee_cert, ca[1], ca[2]);
   // Swap ca certs to deal alternate trust settings.
   check_getchain(ee_cert, ca[2], ca[1]);
-
-  run_next_test();
 }
 
+function run_test() {
+  run_test_in_mode(true);
+  run_test_in_mode(false);
+}
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_intermediate_basic_usage_constraints.js
@@ -0,0 +1,139 @@
+"use strict";
+/* To regenerate the certificates for this test:
+ *
+ *      cd security/manager/ssl/tests/unit/test_intermediate_basic_usage_constraints
+ *      ./generate.py
+ *      cd ../../../../../..
+ *      make -C $OBJDIR/security/manager/ssl/tests
+ *
+ * Check in the generated files. These steps are not done as part of the build
+ * because we do not want to add a build-time dependency on the OpenSSL or NSS
+ * tools or libraries built for the host platform.
+ */
+
+do_get_profile(); // must be called before getting nsIX509CertDB
+const certdb = Cc["@mozilla.org/security/x509certdb;1"]
+                 .getService(Ci.nsIX509CertDB);
+
+function load_cert(name, trust) {
+  let filename = "test_intermediate_basic_usage_constraints/" + name + ".der";
+  addCertFromFile(certdb, filename, trust);
+}
+
+function test_cert_for_usages(certChainNicks, expected_usages_string) {
+  let certs = [];
+  for (let i in certChainNicks) {
+    let certNick = certChainNicks[i];
+    let certDER = readFile(do_get_file(
+                             "test_intermediate_basic_usage_constraints/"
+                                + certNick + ".der"), false);
+    certs.push(certdb.constructX509(certDER, certDER.length));
+  }
+
+  let cert = certs[0];
+  let verified = {};
+  let usages = {};
+  cert.getUsagesString(true, verified, usages);
+  do_print("usages.value = " + usages.value);
+  do_check_eq(expected_usages_string, usages.value);
+}
+
+function run_test_in_mode(useInsanity) {
+  Services.prefs.setBoolPref("security.use_insanity_verification", useInsanity);
+
+  // insanity::pkix doesn't support the obsolete Netscape object signing
+  // extension, but NSS does.
+  let ee_usage1 = useInsanity
+                ? 'Client,Server,Sign,Encrypt,Object Signer'
+                : 'Client,Server,Sign,Encrypt'
+
+  // insanity::pkix doesn't validate CA certificates for non-CA uses, but
+  // NSS does.
+  let ca_usage1 = useInsanity
+                ? "SSL CA"
+                : 'Client,Server,Sign,Encrypt,SSL CA,Status Responder';
+
+  // Load the ca into mem
+  let ca_name = "ca";
+  load_cert(ca_name, "CTu,CTu,CTu");
+  do_print("ca_name = " + ca_name);
+  test_cert_for_usages([ca_name], ca_usage1);
+
+  // A certificate with no basicConstraints extension is considered an EE.
+  test_cert_for_usages(["int-no-extensions"], ee_usage1);
+
+  // int-no-extensions is an EE (see previous case), so no certs can chain to
+  // it.
+  test_cert_for_usages(["ee-int-no-extensions", "int-no-extensions"], "");
+
+  // a certificate with bsaicConstraints.cA==false is considered an EE.
+  test_cert_for_usages(["int-not-a-ca"], ee_usage1);
+
+  // int-not-a-ca is an EE (see previous case), so no certs can chain to it.
+  test_cert_for_usages(["ee-int-not-a-ca", "int-not-a-ca"], "");
+
+  // int-limited-depth has cA==true and a path length constraint of zero.
+  test_cert_for_usages(["int-limited-depth"], ca_usage1);
+
+  // path length constraints do not affect the ability of a non-CA cert to
+  // chain to to the CA cert.
+  test_cert_for_usages(["ee-int-limited-depth", "int-limited-depth"],
+                       ee_usage1);
+
+  // ca
+  //   int-limited-depth (cA==true, pathLenConstraint==0)
+  //      int-limited-depth-invalid (cA==true)
+  //
+  // XXX: It seems the NSS code does not consider the path length of the
+  // certificate we're validating, but insanity::pkix does. insanity::pkix's
+  // behavior is correct.
+  test_cert_for_usages(["int-limited-depth-invalid", "int-limited-depth"],
+                       useInsanity ? "" : ca_usage1);
+  test_cert_for_usages(["ee-int-limited-depth-invalid",
+                        "int-limited-depth-invalid",
+                        "int-limited-depth"],
+                       "");
+
+  // int-valid-ku-no-eku has keyCertSign
+  test_cert_for_usages(["int-valid-ku-no-eku"], "SSL CA");
+  test_cert_for_usages(["ee-int-valid-ku-no-eku", "int-valid-ku-no-eku"],
+                       ee_usage1);
+
+  // int-bad-ku-no-eku has basicConstraints.cA==true and has a KU extension
+  // but the KU extension is missing keyCertSign. Note that insanity::pkix
+  // doesn't validate certificates with basicConstraints.Ca==true for non-CA
+  // uses, but NSS does.
+  test_cert_for_usages(["int-bad-ku-no-eku"],
+                       useInsanity
+                          ? ""
+                          : 'Client,Server,Sign,Encrypt,Status Responder');
+  test_cert_for_usages(["ee-int-bad-ku-no-eku", "int-bad-ku-no-eku"], "");
+
+  // int-no-ku-no-eku has basicConstraints.cA==true and no KU extension.
+  // We treat a missing KU as "any key usage is OK".
+  test_cert_for_usages(["int-no-ku-no-eku"], ca_usage1);
+  test_cert_for_usages(["ee-int-no-ku-no-eku", "int-no-ku-no-eku"], ee_usage1);
+
+  // int-valid-ku-server-eku has basicConstraints.cA==true, keyCertSign in KU,
+  // and EKU=={id-kp-serverAuth,id-kp-clientAuth}.
+  test_cert_for_usages(["int-valid-ku-server-eku"], "SSL CA");
+  test_cert_for_usages(["ee-int-valid-ku-server-eku",
+                        "int-valid-ku-server-eku"], "Client,Server");
+
+  // int-bad-ku-server-eku has basicConstraints.cA==true, a KU without
+  // keyCertSign, and EKU=={id-kp-serverAuth,id-kp-clientAuth}.
+  test_cert_for_usages(["int-bad-ku-server-eku"], "");
+  test_cert_for_usages(["ee-int-bad-ku-server-eku", "int-bad-ku-server-eku"],
+                       "");
+
+  // int-bad-ku-server-eku has basicConstraints.cA==true, no KU, and
+  // EKU=={id-kp-serverAuth,id-kp-clientAuth}.
+  test_cert_for_usages(["int-no-ku-server-eku"], "SSL CA");
+  test_cert_for_usages(["ee-int-no-ku-server-eku", "int-no-ku-server-eku"],
+                       "Client,Server");
+}
+
+function run_test() {
+  run_test_in_mode(true);
+  run_test_in_mode(false);
+}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ef708fb1329dea256faeff5cc76d4e2e7628a7b9
GIT binary patch
literal 684
zc$_n6Vp?I)#5iFAGZP~d6C<MmFB_*;n@8JsUPeZ4Rt5uJLv903Hs(+kW*(;GL<2c-
zUPEI;BLhn#Lt}Ge!zgiHBM{dd%0*Y+#HfU9AR{XSa}y&!15licsfm%1;Y><uiqMYs
zJy#8vznWU){C@tmWtqPw2T%1hj4z$l^l=i?WO4T-XVZ#T@h8{i$^14-PxX9waOV1_
z?QZ$SzIyy6Th`8(Hr)P;i#xvN(-JwWwkOBBPHLoS6bJS8OZIv0E@GU0+vCH{8I{Gt
zrkkb-Y&g&|xo+J&Np+uz#ha#WP)mr~F8q1F;*@jcruqi1MGszdI>>#$@8p;FgD>Ys
z-(#UN8U6{Aq>>gXh&|WS_$==kd#!Mtx~gGX-ot}cOh&)wnZ7bsbWk>`_`33^#GZR?
z!5@7sIv;3rBuG>qY0oz?TK+*|)r}bKOaJana@`U0f#<Hn1}+!j?!!}_<;1E~H_6_x
zI?BY%$iTQ**g(*L9~fw|!i<dnSy&C2ffQOiFoQxXeU(kh?0d6+q+Rg%TA5VjyO5)s
zAzi;A?a%b)&0Xb(*Q9-SY)e<#E9k8j?^l_T>1S2^CHJz!pL6TAw*0m-5pVqF{v+^j
z`nvxgn6sqKLtTPp&ENM_O1Lh&e`0mLNYqxf_JoZ^EY6QUN2W+_w3TLLPWxAL)APl9
zJ@vk(o3l0qrCIsDKmS;`*OzC?R?hNOVte~swBH|PdG&m`?3cE=j%v<&;*woQ3X|fd
zWzG0tAXSs~u29VTpitVxr_(;gz9>9g6cX{{&UbD0(;agRPCXW^sGRsj@{KrC$t9kk
t{)x4#J9QVS*!+5ONLI7s#gBt?#W~hoD874Z+H%A6txL~Zbx&Qp5&(BB7KH!+
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..43e2acf2d35958d51e508a7b76b5e018a25be809
GIT binary patch
literal 726
zc$_n6V!C9|#JFn#GZP~d6SMc56a!v1POUbNw(q=*jNGgY1~P_H1`=${p)AZif|+?G
zx=D#Cy4j_=dHK4j*`)?@;=G2&hDHXKMux`b#zs-%yhb3dIh1Q4ZzyXZ4bd%<nyQOw
zKog@9vW<+a49rc8{0u;GE~X|%MurWZ{4dWx?A-UO^KsLJ4=HK8oMKbEX4$AV+-vEX
zqM9{Lp+iP;$ysamn?HYT{$V-0JZ|&4%MEp@w=eIsZ_l#2m*LN4Rk-wuaO!jsjfr*&
z8*M!nn5)LWx#%`MV&?Q7M{ASfElTwgjjEAXWMX#D@;!9Fn8RX~(PP~=|F<yr{y2A;
z!`i6vb+oae>CyHMvu@!-eQOU!IIjDXvS#h{2Pq#jmhEuberbuTW?GavpV!ANipD4H
zrylb!+0uJb&+XYs`^9rhOq^0&Br>MlSzh;V$v>?<hvQ9t|2t>x!sNcNEUYQb>B0V=
zs}r9c*f48Nw&CgR8?>I!JoI>p!pi7gCyumjUB>sanV1<F7#9Phz<?7NjIzQkOa=@F
z+#n`D3kx$7^AEK6Vg?0T((Jq2^qHCbXRnZYvaPyEcXQ~JHj`s7W^Y`~{O4)+3I(N)
zp&JXoMzs{3aysa@&8g_6#L{O4!eu;Hxn8e&&~Q1e^~{2(EfX2nPuqAh@NlE6xzF0H
z36+6)0uS$p{Zl*dCGt^l(&8^1cZ>wt=52aAYr=l%nA)f3Qwy(HyjY{;rfB~?Jn`P~
zc;kb;4;ELvs__l&oSs>+aiWsV)Px16{brn4XkU_j)3SHN>%Tz}Yp2`m>&>tJB6?-|
zvL7>RH2aFf&dPZ)_8J-~Os-~|xi;-k{<>KEnooR>dsuF8<vnUXz5nzoZu2??sSxP`
f^T?UmnTu3R9!UNylimAbgZJS8Y56C!)>#1nn>{R#
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..80c041ec1f5ce64db3e5ddefe78cd829d4239bc1
GIT binary patch
literal 735
zc$_n6V!Cb6#CUiCGZP~d6AQ!NXdMGyHcqWJkGAi;jEvl@3<e5@at1PN%%LpIJffL-
zCAvw8DZ1IEy2YtQWvNBFsoA9la^k#(#)d`)mPUrg=ElZR;=D#6t~r!zplqmUAP+G?
zA~jVPyCF@CO2{@dvNA9?G4eA2#krW87#SH3g{ACY{HO5i-J^%Pia(lM4E%TNeevl_
z_Os)s&CrltqvU6w`tZzag+m(~-afSyp6I!e&+T62RgPCzcFi#RAyY7M-F91rJIBJ!
zb@Gc#byxh$uWC3T7hSa3_Sw?HX8rKYx%Z|0bY*z86f<t$UGv|>oinb>siW9ocM(q)
z=h+#Rn;wTwX`F2FNT}?>l-0s=@d3&wp5L9SV7D*sx816lNiXm3XY0_sq$HQw+;0CR
z#<HSp!eMT^m0l{&xo3;kJo4sCycolKt=aU`UxzPGcWvKX856^P`@HA#a?w-fv;Ny2
zKOhk=()0Tfk9W{A!HDkpDiXr`w^d$Xsb<{iIju|FbEYo$RVHRe2FArw1`-CGz@U^B
zW??d5FyIC;`B_+)nV5f|#Tzpy&@7}_%%$hsg^D+_ALahyskrYQcelFm=lfh?)eaN&
zvdSK|%nwzlDB+*CO?%om-_!F>&G^3Z`Qzm?f8SZ?yHX%p_HCHl@mD3~@uw@>vrWD#
zck)#)eQ-&kHtI^p%jH{ca!BsB57YXdp%%#|^mbniU)c-hr0&86k!y5RW=|47Z@g8X
zt+&F|=RLE3WbS$4^9+|_z8opBz0<h%sLqKNSz*hz-FKQ<q@+K)-^%w{t!ebp+`RXY
zcJ_%mO0(KF_BR@+e&Y$8XZqyLhJ`AT(X(pw|8oi6f8#ajZh6u7ycc|47o2vu7<CIp
i&Ak$RcTFs_+m*S-0$qoHw+b&hvP54=lr8s=?r#83EG4-B
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ba301ad01642b05535c0b77a86517f8db55589d2
GIT binary patch
literal 743
zc$_n6VtQ=Q#CUoEGZP~d6AR<C_jLxmY@Awc9&O)w85y}*84Oeml?)Wvm_u2Zc_cIQ
zN_2BFb2Cd)Q*={O3raF{GxN$4b23v5<ivRmjSY<qER76}&5ezs#CeTCTyrSbK;2N)
zKpA3+OlqnwZiAW_m5^P)$jZRn#K_M86z5`UVq|1Er@c&R#_i9HC*RyOKWpsUy-fF{
zy>rXn%cbSP_s+IA#m|jRyRoKS?fQWd&O0LWxfA>vFJ3?L=dtRUke<g98}sT8y-E{q
zTlvJiDOlZUuAgd!@0`q<%|2UrPR=UG>36*;Gu7;}W`j=T60r$&zr0U*M^CFblK6AC
zp-4N|gw3yAIF7ozM=so$s`_!3*7})ZUVGM0@7rCv^XyTdZnHDR#VI=PqbJqxO?>~r
zde;=@YN>K(SNnu@QyAB3Un|}%c|31<PyW2KBH<IB&s{UKknt|Bgj@IQXB$Mdw2qd&
z%e`&&`({Pq>i07xbenB#%6yf(JhtiUyPdAh{d2B)qhr>JFDDs<;+dEk85kE!8Aup#
z0)taln1#uJ!GIgY<Y!@FW@7$<7Jtm3K+~=+wQh5tcOq=M*4!h!i@v^Yjd-qWyu0nX
z!0Oxi{`|Jg3M_{MBD`-2a{b%8`P^eGiA{&{R)y`XyyX9?i2vcn?Kd{+HB^1?n&4)2
z)lcL^z@J>@)vu3dJeh4ct#{L-1@*6Xg|l~b2JZU2?RamhRinT+<H`l0O@H+at*pE|
zE|`Cf+#Txi?c$Fg-Y@k#vxDDEo4R|$c}4S(Y6n@(x|bHVk6(zl@6nzA_E~d^=Kh>G
zu`-#R5BG1mm+aEH-f(v8uct{JLL2zXnM)j8H|$}VWNUp|aZ8cBSMZg|tMyjh6kBpy
o>CoEz*g4wsFZ)W(+}-ykv??j+a<awBNl)LKuD-T-VmnU^02&E2RR910
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3b40ea44a3e350eafc0b64401f2e77a2fd78ded6
GIT binary patch
literal 727
zc$_n6V!CY5#JGC_GZP~d6AM#td7S|-8>d#AN85K^Mn-N{1_K#GDFX>M=1>-99>L7K
z65X84+{}{H6y226f|3jaIdNV?V?!eYOCv*Lb7P|@ab6=3*Br_<kT;YykcQ|MNln$o
zG@yx53E4(QRtDxKMt%mMI2ThBBO}AnBt8wE&0;}2^`C{L72UPTa!@q7W~nG3rr)f>
z)M8WIv{6oNQ@i5<w-$3}ov{6)1$C=~pKLafImP?&rMOn~Q`hFVbN-r4*fpg>ob5gT
z#HQ`1f5gSD*<2fTwpTO8aE*6&pZE3CU#%BS6j-exH@`mld=Agu(<1Ddr5>?|W7{J$
zCGMFVIO)+Y$#hhqeU)fQki()>E=`9SVjG3;xWD#uX_;v(EvwoYfBs48TA#_D{_K^j
z+e59_9(~Cyelu)J>oU(*lUC(+l}S(i5ygL`{J`z6ZA#BAr^(B^=CrD>QPX&LY(mtA
zpTC4|9Wp#2(LP7m>-6m9`wr<z7Bp9Cd(G{7o{`GL%*epF7#IZxoWNj|6=q>FU@+hY
zG5J|on3<S=pv4z6D9|REuYI2S{OY2D#d}^P-9IZF(Q&bUn$1y_Zp)ReHz)DGT)f%X
zNc-7a1@}#+kCPuBur084*{dJQ9D6f|=Yg=`#<W`}Wv3MwY%Mf=IWu^t+M!9NnZDMo
zcPyT;$1nsHU7CDJYW~sx2V5@&3*;2*uRgdos<{63@+Dh!9i%QBI4qx>o!@!FJA&&B
z7t@&ule`}!y|7fhFUWVPXUWQluYV=3JY9YAl+44om)GTdP=90>u;gMc(*wuC2UoK8
zr=Qq7+3-=|`fK_AYdcwI9N2n9_3pxoZU3hjTv}n*xhn5wX4X!Jr*VO1rh8xNzHr%k
edB54+z-;Eu(hX+0ZXPz7;!FJR<QU9a7ytlrP9rY>
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5a2a5f41dad970722cf239d41a0a757ba4e47f30
GIT binary patch
literal 727
zc$_n6V!CY5#JGC_GZP~d6AQzQ;uZs5HcqWJkGAi;jEvl@3<ffWQU(%i%%LpIJc5~d
zCAxX}x~UZ<sd>ej`FX_#a^k#(#)d`)mPUrg=EjCm;=D#6t~r!zAa5vZAPvzilA5ZE
zX+RUB60(hqtPIRejQk8haW1ANMn;Au$Cx=DEwc4GaOZ1-a)tBPCBNr>OW*tLPuK&Q
z#xr$3zYOk2RxDCq`}lKF$;SxK1fk8TdO{7$#gsmr61LyU{BgyaD}PPq+}!`LPE=Yc
zOD%Fv`|m3mDz0Aj1$p~*d8Z#JN#^?ed6~-kBR-y!%d(z+JQ}@x(nPPThpKlPM7(^u
z?yQPi!0%eyh0i&YPcFD^$)7J=yVRXs{s?btXJ{Ue`ucc{2hz8zB5gbReb&lH*mBmf
zGo{*Er=8%)U#*jLJ3f<*SL4-dMJ;Cm7Os1F6Cb>vZMCC+i~1z<wQ`S3r!SZy?{Zc3
z!Wr><bH1K5K9sh&@&Kpn>KmD_S{bcBf12WEyenT}GZQl-1LI;~6c}&<gHcwPg~@=y
zfE&c*XJKJxV*Y^^U(BFD>oDB6=+5>7QMaw+wyMng-gU~8YijeVgWvhqXuMBfGqEpT
z`ssw}M;HERWlt%ti9T2s>fKe*Vf<m6L)W}7zX}|pJ3_lOTr0LLzGF4BPF70z>-C*I
zKc8C^hRdm%nI+Z9oSs;_A+`7f+w_c=3D&*G9?#CmSNZgBMY%&~vV_5h_noc>?gp;B
zG~;uh=BsDob}1b}Q?@q7{7QdfC-7^7jNYqAwaK%u&Oa~TaqKAb)P>f&UoQGl)a>uI
zl;>1<be5;7{Dmc522$Lm66VjNH_rTg^6i;k&N)G*?HPBEJwG2OAn{4kidAu!_XFqR
eyPLnwnWS~{m-hNBX2ELq+GQ%|D{Hu{g}eX|hAMOb
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e7199a844291d53b556d157a7acf5c6801230d56
GIT binary patch
literal 725
zc$_n6V!CM1#JF<-GZP~d6AQ!ore_AcY@Awc9&O)w85y}*84RQiB@M*cm_u2Zc?2@^
zN_6w`b+b!BWNLP)ft)z6p|PQnfu)h5vAMBvlsK;uh-(hz8ps*S7)U`h3#X>)V(4#T
zR6@3ok(GhDiIJZHD9**y#K_37Q$)Msjohlm7XBi-KaPEPlKQNeYi8xmW9r69Ui($W
z_#}3x9^(Ifu6F&uSvQ(gI)(ivbL}kSUBvj~zrPb-<$2{!t*boWy(?{}w(I{rAt)`Y
z?l3F3V~?ARp0MHNch}haeg*uQ^(Fby8P8L@D>a_w*=rqLR(?-R@cT!JvqlalzQ?>;
zS$XqT%e3XJ?4thv-+r8bHslbKr1%d*#os$@dtS-&3rzgH%yhxjUyAvMFQ)abp1iyx
z+A4CJxoJkDXu4<O1hF&Ld^PtYm!_u|ep_z1s-Z#XLVWD^ayyGt-jk;HE|a-_{`O}F
zmHSnD1^gvudD`DOeeZ3~jgr}ds@=bP_a@)>Yh_|)WMEt@Wgua|2@FM9VHPF>1_N#o
zlb?l!nTh!aT5K_c0<CJU_s-7A7iYxGkjcB+)?sq*--EeYhurj@hZfvFSTJc0|BmV@
z3wL!ss+s+^-S(-|hmhZsgABgxFOT{0K1D%(_rG7OJ=dpn3eJo95MJc>zwX|YPcyB&
z+f5THmG3@cK6Y!F)O{brm}3W4t>1F@*Y*hvDoGlS$`!)9SF;Jn8nQnwWMFhws5O(D
z5uc)<$hN}xr)%!?h1|X`FMV}B{PpdGt=jgYGwj1I_bgU8H0Sm6QzeVN&tJGPTjK4W
zU+iktE6*+X&$2d<^>~z&{VB)LMZ6J)F?|KI>Ygb__RdKaQ+CzL;rBJ)ea%5C%|PxQ
cqpXyA-8*r!ds;fo4kclxb7Yo^Tv2TR0A?j5$^ZZW
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..90aff830418d4ef76eee4fedbed526c1abbb1fd5
GIT binary patch
literal 732
zc$_n6V!C0_#CTu<GZP~d6LV6RwgE32r&gOs+jm|@Ms8LH19?MP18FwqP!?t$k<7dj
z-MoC=>{8w0)S|M~BHh&NQUf`0UPEI;BLhn#Lt}Ge<0x@nBM{dd$~90jR4|Z(7$BaS
zs*BZ(CPpP>dl^|7n41{+8GzzkOihf83>S|+>Cu&cvd3qktYY`Scl)le%I-P3b-h-2
z@9WE(4k}jMd$m#A@2+szgg06z8Ux=ex&6^&nEcdLacV`;Q#V<kNeb(>GEIE*^5LZU
zKR(6k#H#J{n-H)s=a<fe<=*mdUp%>{@JKeNVYM#<<CDOq|Ig0|-)8?R+2Zr?)#06)
zw$B(YNfq5{c<*8VH1yfC{d<{%&-=e#CcNs1QX2PTEsHt*ffDP~FY0<c@w~sJ^lgpY
z#TSt^D!qGtzB`uBJty+C{A2c5|GN{Hc)Ty^>0S5JRLIg)RR283@<qJv7EI3T{ui+B
ziEp^bIH&gGWEpXzYtk{rhRf{!MS9E@6ImDE<+vjC_+&PDCT2zk#>G+w5(b>Wkdzf>
zVKQJa;07`ISy-5vn17(f8Z#)+CaIauFZ#DauQTuIPUeG+Iz{d#YrXc}^w^W7mGty!
zbhEt1vP<lH&9-?~KGJNnYV=;YDoV`ySKgvE4!zf2>|LffZ%2oZ))pbV$p^3HzfUap
zo$A8wv9EDfX>p?bmm>lZOMDpg?@bkx`IpzhbvS6^nhg1rs--5sKF(V%cIC6T61T~r
zlMK6J#qNbRu{1y4J$>oHvW$<1EWU2ZxqdW{_oOMmo)h27DL)<DEx0znVtN%6cj4!+
zHTQyTuQC5-klSn@F#W_LuhKvA+vCoLbTKTi;WJ$(Z_Mc%c4oWqyAqBWdsY=x)utb>
iYn>8ieCUX<z<<4t&XRovD=tT_S?)jWSH$H8k%a&a<SM%W
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cc4e018df32d336d2ece9989ec2be1a4cfa58a39
GIT binary patch
literal 717
zc$_n6VmfKi#JF(*GZP~d6ANRgY>xpi8>d#AN85K^Mn-N{1_N<JQ3GK%=1>-99-hp+
z65YJ~65T}I<U|8Gab81XLn8xABST|zW5XzMULz3K9LhD2GL$e7gJ|SWP1Qxw+r+4Z
zY!4$V19KB2KLb#li>Zl`kzwERee;u<p1l9Bw8r5^>wS*w<+FGSJ8XJ{o`fvqT7CH3
zPk--;^FJERE{?U(|2B93jP;wQxJ^1%{Gj3W#Hp?kVvD~$U9=#<*ZBC?%gWC<7X68O
zk~i&Fi23o~t@GXIHMViOiCT6nYqXPgSDD$#b-X8CX-!Mfo|YX4`y^k=pVzINvfxr-
z;^!5~LV3(z-j*m#d3IsGMP#9p(l$A<oq2C$yLxBIx@9KquM11P5+eEf?!24XZ=>>8
z<*S=CEt4@9zN@pUA$(a#_7xj7+33?eHWN#ux70q5+`9h)*Tc@mLGP~4Q2zZ-&g`36
zLH6dg-(n<lbTW;;d=`xNWInS=?tV>%VvJBY6Eh<N<6<cT2?I`G2+9hxFc~lyaD$lq
zEG*1S%s<d#i5V1VGxCGmqSgPaKiNFtephs}k<6J8{<+V;<=Ni!iB&gCR1GwA^qjr4
zvq{mZnPr0Bvc7AZcTY+@q`fx4VA02)>p$Av4bPrnFXV9bx=-$h?`Nw5*48-BEfWvj
zQe*vu!|L71Yo+Vfr)u2YDY;K)=G2XeH4A_Do_w)(={9rQQ|GM2i+pvoL>sOBRi>@K
zDX-?4`dKlm{hr4L?-`Ds9cvC0T2yYa+W%)0|Dp?NF1y~WXf{>kx%+$RA&pmGxA3f%
z_LSyUF*xU*AfMX6yW4P&xqg`WwnFjuwdcH(A5UDk(B=N*gL4jTiF#Y6GShG7q<~et
a8(Ryy^b7@`8l_$D`)4ks9k`IaO9ud}l_F{Y
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0d68232515268aeeea8c1862ba1225fef133d3b0
GIT binary patch
literal 731
zc$_n6V!Ce7#JGO}GZP~d6APoqj8g`@Y@Awc9&O)w85y}*84TnMWelX)m_u2Zd4x0b
zN_5K-b23wOvrBdJ@^w?QOAX}2c@2#XjSMV}42{i=jiSVPjX+#;DAz#IP~JcmqF*dE
zRTrBPO^iy&wlcCZFgG#sGXTZ8n3@<F8ID_pwej3!V|mk*+V{gtF?Plr->VuE)Fp((
z+KL}#Cnhevnc92inoh}fu60#`43A=}W<Ql>;o^M7nVU4jB=X18sduiXo@I4^{cyg{
z&#!0Sys1sno5?EqJ6x36V*lwkE_ZHo%(`?sZ%bU9NRZ0s*lzK^{x1||jaJoG?75dJ
zp!IoC|J{4s?{6+ylv`4ldx)2N69>bUgU7l8-zT>!%Q15KrLL_Dx?HwH_?NMPcgVt7
z7yrEySP}U9P)l&r<l|cJjYFiRqm!nxs)?_x^ek^Y>h!7Ba<7wk)$vW;_6I6dPPV^L
zm=omEB=p+n@4>{$kN%%EVm4gg$RK0d>-~52X5qz8UY%xQW@KPoEM*{JzzGaUSz#6?
z0|o<b5R;#Ug_()@2U?slg91%--%N#CRhyYcGp;z4)~}rP!u_<AiHeEwg$HI5AGXcd
zUU}BtsN(L9lXaUnufE@v?tHuTR-*5-Xix2_g0G)GzH((l`^ULC+A<CYm+a|TzQUiy
zQSesq(HFlsCI#IP5uIoL?Ty5~tR&sPTEAXRdizq?KzH}l1;X*mg8zNH{p``Chx!|C
zCp3ThA8~eqhh<Wo^JRv40{x6XAN*PVYp#WMeS!4~4Xfks;@+pd`tqu@j<s{o+4o`R
zgq59NWY^xc?K-_AB02I&#7?*Fmy5r%sh<y&(_FQ4(J?KVY|ei{y){+)%;!BXJ@s(f
iccvufuh)W#7n^RX%ke7fUHhZs&%BEG=1)P1wLJigFEH2u
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..abbb478310525735e4f493a9ddf8796e3cdf79ea
GIT binary patch
literal 739
zc$_n6V!Ch8#CUuGGZP~d6AR<MI1vM0HcqWJkGAi;jEvl@3<gSu3I=j)%%LpIJmQ&o
zCAwvaIhiTC*`>P0sYPX}MY^fkr3P~1yoSbxMh2EfhQ{W`#!=$DMj);^lxv`BsBEAJ
zF+(afRTq~rO^iy&wllIaFgG#sGXTZ8n3@<F8IEu;wQM{7>-f4mnG)syZB`xnaa5>|
zQ7L=v+IuU-8<fq1tAiJ7*YC2DWnZm3vo!2R<>aJ_7Dhjwgr8Bo>zis=&wi|So%j6u
zyI_Xw2VA?AQ{RcO7hP(1x^Px~=d&Yn1+7oCItvquqgM6&=1a0Usk?)xU}EwtuSvnH
zc8P^P`W|~JwPGW4SA*1wv_%uM{bll%c^}>A7W>r1BKJM*j%Y=tVenDSgxyN74mtig
zdtUSJ`!|Q1-mn%_wRZ&y7*_9|_4~`u_f3uc$8YVqx`nOx>%TG%-DNYs3H9BzJ+ypE
z$&bCCXE1VK{J^<bXZ4Y^vpX+8H+6ISv|H}LrNAX(?CNFl+-KJ_F*7nSE|xNoFyI6R
zrmQdvlL3PPH;Bp4!otkN`~xlSm_dQ2vrSPfS5e40XRGze6qaWPk1)5+-t##2z#laR
z4~a(~d{<mie4v?@u*78T?q+3;TSumE4rg4R9<)q&!kkle79VQvtX-zQr_X3Za`*GR
z`?a3w461#RXKc=WijCA|_B>^->Khr-m9rqGa_h0(2eQv_${K9-S@~9T*BREW0`GRn
z9DFhPME2ghdp^$G`Y~i-pr`06N2BSdBA-;-@+Z#D*<<H5u_X7_lC@X68k#qio;q7P
z)s4f?uk#$6kV@Vh@jC*ELL8ORuXY$Jo^}<wy{qbh$A<|o=O&(xP1e2rd*O{YMw;r{
l=CVA}Cz2)i3GTC1I_)45#>C|v;=<bOB=~+>bxE1p6#&)SD$D=?
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_intermediate_basic_usage_constraints/generate.py
@@ -0,0 +1,99 @@
+#!/usr/bin/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/.
+
+# requires openssl >= 1.0.0
+
+import tempfile, os, sys, random
+libpath = os.path.abspath('../psm_common_py')
+
+sys.path.append(libpath)
+
+import CertUtils
+
+
+srcdir = os.getcwd()
+db = tempfile.mkdtemp()
+
+CA_basic_constraints = "basicConstraints = critical, CA:TRUE\n"
+CA_limited_basic_constraints = "basicConstraints = critical,CA:TRUE, pathlen:0\n"
+EE_basic_constraints = "basicConstraints = CA:FALSE\n"
+
+CA_min_ku = "keyUsage = critical, keyCertSign\n"
+CA_bad_ku = "keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, cRLSign\n"
+EE_full_ku ="keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement\n"
+
+Server_eku = "extendedKeyUsage = critical, serverAuth, clientAuth\n "
+
+key_type = 'rsa'
+
+def generate_int_and_ee2(ca_key, ca_cert, suffix, int_ext_text, ee_ext_text):
+    int_name = "int-" + suffix;
+    ee_name  = "ee-int-" + suffix;
+    int_serial = random.randint(100, 40000000);
+    ee_serial = random.randint(100, 40000000);
+    [int_key, int_cert] = CertUtils.generate_cert_generic(db,
+                                                        srcdir,
+                                                        int_serial,
+                                                        key_type,
+                                                        int_name,
+                                                        int_ext_text,
+                                                        ca_key,
+                                                        ca_cert);
+    [ee_key, ee_cert] = CertUtils.generate_cert_generic(db,
+                                                        srcdir,
+                                                        ee_serial,
+                                                        key_type,
+                                                        ee_name,
+                                                        ee_ext_text,
+                                                        int_key,
+                                                        int_cert);
+    return [int_key, int_cert, ee_key, ee_cert]
+
+def generate_certs():
+    ca_name = "ca"
+    [ca_key, ca_cert ] = CertUtils.generate_cert_generic(db,
+                                                        srcdir,
+                                                        1,
+                                                        key_type,
+                                                        ca_name,
+                                                        CA_basic_constraints)
+    ee_ext_text = EE_basic_constraints + EE_full_ku
+
+    #now the intermediates
+    generate_int_and_ee2(ca_key, ca_cert, "no-extensions", "", ee_ext_text)
+    generate_int_and_ee2(ca_key, ca_cert, "not-a-ca", EE_basic_constraints,
+                         ee_ext_text)
+
+    [int_key, int_cert, a, b] = generate_int_and_ee2(ca_key, ca_cert,
+                                                     "limited-depth",
+                                                     CA_limited_basic_constraints,
+                                                     ee_ext_text);
+    #and a child using this one
+    generate_int_and_ee2(int_key, int_cert, "limited-depth-invalid",
+                         CA_basic_constraints, ee_ext_text);
+
+    # now we do it again for valid basic constraints but strange eku/ku at the
+    # intermediate layer
+    generate_int_and_ee2(ca_key, ca_cert, "valid-ku-no-eku",
+                         CA_basic_constraints + CA_min_ku, ee_ext_text);
+    generate_int_and_ee2(ca_key, ca_cert, "bad-ku-no-eku",
+                         CA_basic_constraints + CA_bad_ku, ee_ext_text);
+    generate_int_and_ee2(ca_key, ca_cert, "no-ku-no-eku",
+                         CA_basic_constraints, ee_ext_text);
+
+    generate_int_and_ee2(ca_key, ca_cert, "valid-ku-server-eku",
+                         CA_basic_constraints +  CA_min_ku + Server_eku,
+                         ee_ext_text);
+    generate_int_and_ee2(ca_key, ca_cert, "bad-ku-server-eku",
+                         CA_basic_constraints +  CA_bad_ku + Server_eku,
+                         ee_ext_text);
+    generate_int_and_ee2(ca_key, ca_cert, "no-ku-server-eku",
+                         CA_basic_constraints  + Server_eku, ee_ext_text);
+
+
+generate_certs()
+
+
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0dbed201b568594ddad3b207d7a048e8bc9835bd
GIT binary patch
literal 715
zc$_n6VmfZn#JGL|GZP~d6AL4++iwG2HcqWJkGAi;jEvl@3<kW0+y<O%%%LpIJWR=n
z26E!OhQ@|Q29`#K#^%OGQR2KtAg(!-YanANWgr1jE|{5DqMMYMqMKc+o0qSfnq3OC
zN(tF~Mpg#qCPsb+pg0#(6C)$ThG`#H{>uyfP+$A;@Wa!+>V-D>QGI@Eo_?Ha_D^R{
z&NkCUEjt^kc=SKr`_;WPkJ;>VXK;Z)<YrU7r`d`|(P9xdTQe55zRW(+H09Xpgjnkw
z_2lCg?&@719Jbmz%;i<}`4}FszOA^TL#}j9?&&?|o7dmY`4X&nuh!e}?3JQB2EFsb
zGIn#6F{<rgYkyGmP&xEa=8T%g8;Zv+`St8Qa9EymtHIy@(;sd7ur_Du>fc8Nte#tP
zF8D0->~UVOuupqbgHQ3tr)rl!x&QvP!Q<oXFZHb(uPnaqn$9(=Mt5S4!P_pgrS``e
zwAbtoSNJ*aLqFS(6~2`{ZTD7WEV!$?eP6-Bw(U&Jj0}v66%6DI_<><4E6m9FpM}+c
z8Aus$g9P|lSb#D03oVYAK|vR+{O098(}n8w&D;0ezVCT*^86;&WSJS~qtB(BR{E$c
z{q(4gz|tT5G3V8in(r50UH|^;-8D7Z*%ABRbAP&ech&_TqkmdV2X-&XpQO|jQc_vN
z9sYTHd!*3Z_gdTi)%P^(r*50AAY$Z{!2RpW_4^E8pTw!Ik~{VM)f6X>J^nZTE>HZi
z@y_H>wr{52&F;UHKDR37$^ZL{uk4ku+ILXw<l?W{yJzLgA6~D`C$Qu9dXY`{51w4q
zA>uk`=g)O-cI=-KKjrhZhkI3{V;zIkw_LlZd}8IX?>4)br<w65-(i~(U=n&X;D0=m
k=oR;<`Ig0#;uhuzU%s>Z^30aa-@Q&Lh(&O{d$ag50AWKn00000
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8957ccf7b6b454023c0a14187dbd9a482bab28b6
GIT binary patch
literal 753
zc$_n6VtQ-P#CUZ9GZP~d6APosm1qNAHcqWJkGAi;jEvl@3<kW0+y<O%%%LpIJWR=n
z26E!OhQ@|Q29`#K#^%PxQR2KtAg(!-YoK5#XCMPnE}EHFqMMYMqMKc+Tbx={mRh8n
znq3OCP6^o#Mpg#qCPsb+pg0#(6C)$Ts|_M1j{G4z4j*3H9KfTnoptuVty`x2ycd=A
z?N)U5>4WmGd&B2{{c!eMjcV|1*OEKY=1Qi|_ibBl_`y?I>-C-f`)P0HrE<#&MeTk*
zV@IY?!OY0|{e_c_T@?=NG@H67cZ95H`yKbzk|*%*_m|TrvlTTl#A)QuRF?gB@}TD%
zro~Z<&fn7dc*n%KL4V@Se1}&@HeP=%-x_E*byw-(;5{pTyWEyCYJ9z#amuIakFHlF
zzop)47yj9kS9(4~=H%%N{)s1--Oiga`&Gqn2^rbytfvpef8Xqgf4B0PXG`9nT`afS
z_RhPzkiqHY&9_|}4h5=+KM0-pqwxLPUg=$oFT0eg&zm_iF*7nSE_O0-FyIG<qpUC^
z<9`-b17;v)zzq`MXJG-x)-MAE5JwdxD`p_V#-Yu|$jZvj%m`;Op~WOKC~%qlif4q%
zC3}Tfc^_;`SbSVhN`?24myJPq*M@&r@A}WpQQ#=5(*3=<KZ$8h>yPrUXTuWgBmy!y
z7G3+37RDq0&t81(Ph<V)53e4GEtd=}Wmq;ZtBT=N$o3y^PYBn!{FPkuF=u{oj#*=4
zt&rKa_{`gnoH^fJ^!WUDkDGwyPRBiucg0){apDXU$m33Y66iSpTKKmj(+U^yQ*S<Y
zSzC6Owi&-|z46McGb4K6o6SOE6DI4Qb8(JJU9*2}(~jW8?Kw_$oga_qdUMI$4A|uS
zc&gHs%dsJ~I=4F9&N%G9bmZTwh}p-|)#sjCSF-=y^;0~nq<aDbUwaGRzp^3y2Gh3h
H6*bxboN+Tr
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bd9b6d8828a72ea2900723e72dd4e44b1b9682ee
GIT binary patch
literal 725
zc$_n6V!CM1#JF<-GZP~d6AKg9>!}93Y@Awc9&O)w85y}*84P3$r3@t4m_u2Zc?2`_
zN_2BFb2Cd)Q*={O3raE!<ivRmjSY<qER76}&5ezs#CeTCTyrSbK*dnWKmnp#5<|Cc
zW?orhPG$<w1xm=)GO{u-H!<=v0L8hOniv@wF8Uh(=r?iT@U7Z7%Z0hTdVkVw`=f7{
zg-LB_k=*z0(Fwtd+tJoVk^c8B;yhxy=e_1qS~_)`)AG8#9bX^+-q~#b<m~Mj>4KK0
zdrma%{+25t#?j39F#O~~5iglPf#-_L`#PNOvj654WRvXgyRH7;?<_;?8;<;yOAS<m
z^_yk5lA<%dz3T~Qjpxt)@^FI+zi(v1yt0XsY_AnEJm!a-zy9c#N!B_q-o7Kh7Jqk`
zQ2+8%F2C)Av|xz<nO!_bu6r_6PP0-mEZ#55vqIy?RN1~@&3y0h-S>Pp*i2yjbmQZ`
z>OW_1@0G3nEFGHti9b*GRmFz9{n0$04E6?h-1p3l`k`(!pNW}~fpM|0fuI3DFf3(-
z85#exuo^G}DYV#P28GtT-j9sh9Zs7i-xxF1N(8KGES9^s+irE`5BA;?lb2b4--+bC
zT(VsLfunA0G}n``YKE?r?^zUiBpT0i2Y!=_|FVJA#eRk0;#JBA>sRR9vQ>WXR{G|y
z>XWOFZLRm^)`?6%-K_VbL1)7(jkQ%pZt`!ECKT?xkaf%N-kojFa-xq<p7iyX5euVa
ze!_z9c?F_e?^oa7&pLV0Ea$D8jl@iKk1jl&)8Y8}y=|%Us+uki&J|y)l0%sm?&tO2
zq@{d1l-0O+?}V(kHhnWV=j=FWwWQ&=;Op73>)Bdv=7d!<2CepvWl#=n=GS=nM~yWv
cJMN0p&)>#v@2i8vG+&*XE?_3&bYg-k0A$-DA^-pY
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..078ad25c703f04cfb2ab93e448f6476bc936ea29
GIT binary patch
literal 705
zc$_n6V%lra#JF?;GZP~d6AP2?1TF(!HcqWJkGAi;jEvl@3<kW0+y<O%%%LpIJWR=n
z26E!OhQ@|Q29`#K#^%O`QR2KtAg(!-YanANWgr1jE|{5DqMMVMn^}^YqMMRhP?7<(
zN(tF~Mpg#qCPsb+pg0#(6C)$Txmh*8OwxUC)l@8<_)#JGNYlYRUJYVbW^#A-{!L>(
zzqm5DGqGuv=FXLTQKx>dI3;1-@N-eg3_(|wripo-S2qOO%hoq(ME?yh4`17)yKRxY
z!p9qII(|GRPj-A0Qa)aK^h!R@oehU3J=9*^f6jkLZE8O6zf*_amuYAT`_A=T+-)&|
zd7HCCcK5$2j<&mQTve#3ZJqjKg;(eTuC6IJb-DK}Vlh*c(pXUQEd9@iKJ}wTp7jUh
zdZ#=zKX7YSjp39pI@y7&->0m8%Cvey|MLY!d--_;!^AsSl&;FetaP5!k??j_m#I3(
z^?P$g(nPz%{{?^2zGt>nc|!26*6PO|+qUhKYGz_)WMEt@W*}l91Pnu2VMfOPEF1=G
zK#GZx0WD^jK>>D1)IV}tj_W2a>+sGK=l<s0R@@|T)$7@Jp?&`+@|65u$k6n21&a`S
zqTYgxJ)-?jdU<<hNyZjeerw^~_xXhFk99hi8f^n}pZ9lJ9*Ehr{7dJ<6}G3Rn0>Uo
z;33~qK9hGv#p0^f0+vylf6Quq)>cj|67}8tXzHewSGYpf{oZo=;kB!I2Yp>_-iL{Q
z)waFPP&&7O#qacq-e~FPx)a#F%z~c^e^OoeIzeOli7>Y*TPEm!Gs$tz?fQMz)#|-V
zcDUCnv)B9qk<Ql=<lfJFareZAxi<xF@;?;0lF4&p(knjOaK?n+LcSY(S2{fSDY#ZD
Z<Fa5g+hMDjWhJw(tgR@Cdtds*6#$soA>04}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..458272a20bb4bfb57ba81381e53c0b44b048b747
GIT binary patch
literal 681
zc$_n6Vp?j@#MrxlnTe5!iG@jYlC%LY8>d#AN85K^Mn-N{1_NG0ZUas>=1>-99;W0(
z137VCLt{fD14|=AV{>D}C~;mR5Z4^aHIOlsGLV2M7tG8n(ap=(O|2+N%`48#&npI6
zrG#ugBP#=Q6C*zZP@IdYiII`v=u6v8tslxP@>HHN&bz!rT3helo(^_fw|tXkkGQ!^
z1sj-Lf1RCjb<@)xBkqnT|K~598gt$E{84?^bdk$_cCDQk)sDNU%y~aQNPoj@O`*=C
z2~3Z_{*cyxJT1<>W?k$)(;Ix1JKBs>W=(J3cx{h`b+l0Q=kwp^{4<ETAzc0;?6<Re
z&~0HS*;KA_L5&Fx0iq7aB&s9Db&gE2ZMKWp*zzHzWUkEd_s6;8U;BQ&aMP2AN%uAz
z(?-k7?RRCix^EF@=qeIbzV6O-VDX37C3Z}#R{u6EIly%PTlHeinMDa--oLbY@Nc$l
z{9J{DlVe+#AF5%m{rRe5b)|R1>G%5ePvah~EM{V6WMD*#0cKFZWL?PXkG62hz4PRl
zXGJ#i(pU$z_j{#GQ%m>{hR$s*elaJHkB7JA8<()q!Q8$7jvC%`^5KX(d~#!zOhdhI
z8jp6GqvVmP^-rqV9uzM;rG52cc!^5uk21HfvHo2P-rbbUUz6Epa-_g=udZR{;kVbf
z7#yh*KWV6|=c+BF>*27-HmCm(PyZSBwJY3`8vd4Zp4jp6>7BLTU%vV`=gBTc$y;fY
zSNAeY@|ifzxqpve@BY7!QzdUt>t1$nbKHi7oXc&0yO^3YpY%K^aVFsJ?1UYUSH>OM
z@UY{e#!{!XOHcp#wu6_|azgv!w1-KX7O%?nSgtZfBP;aQ@o&@bXPkdu92RNrl{FCn
DtH~c_
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8cb3b6134b8f8257e18bd8ce4fe9ec3c43dc8a7b
GIT binary patch
literal 700
zc$_n6V%lNQ#JFGqGZP~d6SG$LH3MEYPOUbNw(q=*jNGgY2E2yc2Apinp)AZiOv#A`
za^k#(#)d`)mPUrg=ElZR;=D#6t~r!zAZ;jVAP!M3keOGao0qSfT?!&ovrB;%DIpur
z$jZRn#K_M86z5`UVq|1Ecp{<N`_K%7Kf?R2*mu>=5_&XS{nECmB*9&O*X-@tesjU)
zlB6A9^%ZQE*9X^WE({24ylcB=?xigo?JOpCbj4-;>v`pT<$URK{%0lg9#x-MKAo|+
zC^WvN^7MwEH5Y8T?k)CHme=IZDd<y-a<8qf&^Mf{tj=cAzuxGV+l~3pr!Y+qJ5lO0
z`QGulzowp8+p>D2WQ!cH>Fe)bVkWj^Ykjl&eSU&()tT=*rnoK$>6TyW_?S8W*30|F
z2Zf@tI{R*2e0%O$fO2<LrPLBZHH9Or+t<9^$#_rHIeXdGH#}eG1<YbN5@2C%W2nf-
zRQXdp|BH*Rj`^QA>~pSeD~YQR&1`nh=wxDMWMEt@Y#?aB4-7(CVMfOPEUX61Kng8Z
zm_ebXC;x_B%}_`;;;dy{sffDk>&M&`2^!xPxAJXk_;b|vM9u-x5AQj)>?-y1<`6o@
zrN}zD>ReX%R;LREN1w;+7umQ_<n`HF%c#jeW`)l_b0+>&;EQ>FF$}xny){4FoOk)j
zo^`AjW%7lc94q`pm#<xa;(q$#xkXG5BrBqx{4abqb4{PLtw_}ApxGKn0+nvJ`fRD>
zzsDms<Er$x$NPJ?Utz50Ggi&6ne=8?Xc>cg?$7mkLU*HN?|J>Sh@0_lMa}C^zG=mY
zogU#o)+BPt6uEBwr*^t!r&1x$9GMT7?JFx!vt3~~>$bkSLTck|C(~k?J4vgZBc3k(
SIiX_f2B#|hr%4?P{r~`e_96HH
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..303f64241c4566277a9ae8c336ae0cf013678386
GIT binary patch
literal 738
zc$_n6V!CJ0#CU80GZP~d6Eo}Eg$BHAoLX%jZQpqr8M#>*40sK>4LI4DLs^)4n359>
z<ivRmjSY<qER76}&5ezt#CeTCTyrSbK;BT+KpLW4Br~r>H!oi|yHvM0wWut$NH;aR
z6lj?evK5T149rc8{0u;GE~X|%MuzKCSFSEDI5WXxrT(I{rLCssiC-si&iPks&~ZWI
zXs=#H@V-ys7Jm;~9A2yc^J%4E(}8=}gAc29v!vX4CNELw@=mO-<-@n!g^^0!3&Za*
zUiRM^knPyDXkM^o<m@B^>zz&qufL6Ncy`9CeMY>8$3^vg`;;lW_P%=Z_t2u>p$UrB
zoLA3GpBA&>-dU~Jz9J8nvYwp0*mbL|sGe`VgZIVG3x>=}4H2>20W!vG7zFNyI7qbK
z*f5XDWP<H;i`}>H9?^R8RVkq2{6W_59y=Fx9Gtvd(WL6p_q#_bRKKjAu+-N*t@7rx
z`FTbMBQ5!6#OlPBPMhcFc>MzFCizRVG?nZ>h9A9mo{5=}fpM{^fw2KUFc@Wp85#ex
zuo^G}DFX$NfGS8p%s_;VLz|6}m6e^D5zb;li#ujec<$K6o8K(6>}AdR5DoG6oJp@8
zx@}7e#gFC8*HkQ;aYwd|TYD4dYSXI3BLzy6)VhBrT)NL?vbFF)#;KO=%v%&&{s*R8
z-JIv3+z@C}uq5D4(WZGHYZrXGv2(%c@D#E2ZEdpQ`feRYOJ16soW67an=`6Y&Fpq?
zbGJO=buS2G3=ds(XGVg$NA&savWrd5{#avp`|zsIa;tq*Tgpt&fAq0`&M#IW#QCzx
zPVvZ+e-R!tW^B^_P^E3UI!31<n`y-kL-BuVUz>lp^UE=K1g5=_T=C5HLc|8aeVx|7
uw(zZG7Jl$|zT)Lajk}Krf0((-y~|uMF88%%>jcHSl}2nrtiA5S(=-7$ej>^M
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..76914ec4702a515c3738d85c2bdb8539c1ccb22c
GIT binary patch
literal 691
zc$_n6Vp?y|#5jEcGZP~d6AQ!5<DU$8**LY@JlekVGBR?rG8ph0avN~6F^94+^DreR
z8pw(B8X6lK8CV(_8k-v%Mv3zpfw<;Su7S9rsDUs<IZtL@iEdtgiEg4UP-7FL60*^Z
ztPIRejQk8haW1ANMn;CSlVm%NZS(%Vrr;EF^iQ|oJRz~=>3>X1t)IqNZk6?2J(FXe
z=V851ld7K_(+$&GvP`fzWDmo)J#mw^t(#&W-umHyrK|fY_fy@rcci;EPxw=L|GH1A
zLV;B0A;y`F-9nmb?6*$uDVVD{YmL>}@RIvmEVnkD&j^WIs+#KMGU1~?vxzMG{=e(r
zs5rJbbS7BDOykHp*ckidxX8ITs~Z{XDr#O!{5<C*IL(#Wdvj&`>|eQOns!CaKh06T
z+S5I?x>(@h@kyI_7PWti;>bLDo#p?+qi1rrr*eCqQ@FyY`N2_5ymn%E$DI(bK6T0M
z?|z&rkoW#rbYwmEgGx=Mc_QD#N-Q^uGBGnUFfQgbfP}WJFbk6b16o`#gTiU$?=Cr^
z7Kc|WmH2O8DwI@kDPGK2_4TH9m2hurzSyQl(>EXZmfc-^Txsq^-KURd<bQh=Ir(hd
zd*@>{jQ`Tb9x5r#W!}ac+Ia5gm*9YzT9f~BZ%#9NnC%f^Y&1E_^6bCZfLHS-K0o+G
zN8m22L&<Y%_q3kbKi11H`eJ9G6Za}+vhXdnGnKE^;w!ttV#F6ouXRf5Q%PDFy#00<
z_w(GtV!po@E<L*@SuNqhbgLc<x8wY!rxhQoBv-I{OY}GM?MY#*^?bsq;bv}h?AUys
zg&x&Yx#rDCvs~m-r9biL&2Ni#b-#Wr-{f49`t$_HabNMRRRLFAH*xace&^fSAL;Y(
IYI;N_059JdX8-^I
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9b000a6f4f13d0aa503f203a4b72279ded8fc7e7
GIT binary patch
literal 719
zc$_n6VmfWm#JG6@GZP~d6SL1^HUnNZPOUbNw(q=*jNGgY2E2yc2Apinp)AZiOv#A`
za^k#(#)d`)mPUrg=Eg=*;=D#6t~r!zAZI9JAO%q_oS9dmTb7uUnWCFrs+*Uuo0?q;
zv`Y!u21Zr}<|amd2B0_>QxhX2!`=<%+wNXTk^I5Gwd=WYx?t<kqp{_D_p*1#3oet6
zSuU}d>5!kv4Hw@>cMo6PpV(CJV{?@FKk24wJ&tYHzCJU5(j8oIc5cF_efy4Zc6+tG
zJbQ29Y5iO8w;S51pEUjbjVUeYgU5!eHCZPbD#czJ?fodq^0Kf!zc6uOlem=knk%cD
zwdOf~-uLX(N9~gt2G9K(zNYfH1~Gieei1w6jCYWE-BF&^f!cp!n=|rGdoRE3s>r)%
z(|d+c#hwl4Z2g{pdb2dULHs-K55{8|dq0F;pA_!F&$D8GxlqSz%Ns0P{A~nW{ley-
zt*y27h+N_>uqe2_`c+>rw;78DlWe-D`UIXL?r0`vMh3>k$_9!C{J>C@6=r1o&%$cJ
z45SSBKmz<A0TyN^CKj}aVg`ktyU3%ivk8YMPY=#L*}(JgYe1Me)7+c?rz$O6wDoPo
zB8O`~!#}mIWj-*=wOn=DEj9hV75^%<L^L^dnaW#OO(o_{vC$QB&~-HWz%9~mB{l7)
zRLk=Bw|_1Ab=k0PmC+gx<qDl7J}m(=gQ<VSidWA+FJV^u_1&}im)88y{P*t8_OI<J
zJd0};ewmqsPyZ0*J^S3la>Z#zKl{J!%KXKrD{?7syC3ViRc2dy$~2d8mAy6Deanx-
zuHCU|U6A3gp7-*3tW!g7E84CyInJkXj!%3_;g8qVKQon2CZ}`QbQ<q2lbE7){_*nt
i0#y@dSHD`Nc6rq)-#_7cCrf9k#csc{a>3@uZI=N~+9Kot
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..63d1563e0ea824b6ce84fef1f430b4fda8326b3e
GIT binary patch
literal 757
zc$_n6V)|&%#CUT7GZP~d6LZA<a06a8POUbNw(q=*jNGgY2E2yc2Apinp)AZiOv#A`
za^k#(#)d`)mPUrg=ElZR;=D#6t~r!zpk%0EAO}${o|#voTb7uUnWCFrs#}~|RF+z#
zo0?q;v`-1y7DiSE<|amd2B0_>QxhX2!)D&++cNef?kfqpkU5(-{r)S50-qz+4t>eC
zf_v&XHF<aakj|W~{mv@nLg8(tBBP4sTZOmuy!cqe%wWERqvBqk`Q90x5r>0awl6x(
zK1-*uZGCd|_v(8(eSV90ud*0b6+dnKd4BWRbyFR0_ssm#-XH$`97DY27Ne!Lae>co
z?DzBEELNAzw}N}NSX7d|Q_bRgE{k7Zx7ROTH&2MQ<^GO%wOKs#E^PF0GUT6W^+@ei
zX{t%kvM;xOcl5VB=eTYkxv3=MM%!s#86S&3vpa-MzNJ{~?KCw#_42&WqL-F0A1ZvA
zoAB)-lhEmY)u~f9-LcYCUDvnN@L}^zF7JXT|G%Btu{D>8nUR5Uv8#cz0Y5M#WrZ0T
z|Ff_fFas$AK9B%ENPvZziHXHP0mN4Y@x=^8*f_M=7+G1_nHk|MCbZ~e28D0gk*PfV
z8hMrHpNbm!*s5C2-MjkK`XCieFJ)o*Z*P{RrCi;A%Ic<&(NBwsT+ORaZG0437b{xQ
zot^#DZ~op)E;F9eqO)m7jI}O&eY4M@Q6%lhwOOUd7x`~7ndTPDxm)_c_psdidXhX@
zC!hM*UP<?KJzw?nH@nmfZI<s}nJ(@vnOK@X<)_K+hrEl=I~=sIw$3oR%K2<UU(H5$
zy<6Std-oYK$$M#6=?kv$;Ew;?J+FF$8fSp@JkhUOQD5?;jwkNim&j2kvj2X7^HI@H
zJpRdT;Ws_lo;kCp)kiznXHC*_ZM}R?=wi;ceIh^Px3%oaT{Qc}nTQKd4cBg)`9AU5
I(cTVr0PO1~;s5{u
--- a/security/manager/ssl/tests/unit/xpcshell.ini
+++ b/security/manager/ssl/tests/unit/xpcshell.ini
@@ -3,16 +3,17 @@ head = head_psm.js
 tail =
 support-files =
   test_certificate_usages/**
   test_signed_apps/**
   tlsserver/**
   test_cert_signatures/**
   test_ev_certs/**
   test_getchain/**
+  test_intermediate_basic_usage_constraints/**
 
 [test_certificate_usages.js]
 # Bug 676972: test fails consistently on Android
 fail-if = os == "android"
 [test_signed_apps.js]
 # Bug 676972: test fails consistently on Android
 fail-if = os == "android"
 [test_signed_apps-marketplace.js]
@@ -55,8 +56,12 @@ fail-if = os == "android"
 # Bug 676972: test fails consistently on Android
 fail-if = os == "android"
 [test_ev_certs.js]
 # Bug 676972: test fails consistently on Android
 fail-if = os == "android"
 [test_getchain.js]
 # Bug 676972: test fails consistently on Android
 fail-if = os == "android"
+[test_intermediate_basic_usage_constraints.js]
+# Bug 676972: test hangs consistently on Android
+skip-if = os == "android"
+
--- a/storage/src/mozStorageStatementRow.cpp
+++ b/storage/src/mozStorageStatementRow.cpp
@@ -81,17 +81,17 @@ StatementRow::GetProperty(nsIXPConnectWr
         return NS_OK;
       }
       *_vp = STRING_TO_JSVAL(str);
     }
     else if (type == mozIStorageValueArray::VALUE_TYPE_BLOB) {
       uint32_t length;
       const uint8_t *blob = static_cast<mozIStorageStatement *>(mStatement)->
         AsSharedBlob(idx, &length);
-      JSObject *obj = ::JS_NewArrayObject(aCtx, length, nullptr);
+      JSObject *obj = ::JS_NewArrayObject(aCtx, length);
       if (!obj) {
         *_retval = false;
         return NS_OK;
       }
       *_vp = OBJECT_TO_JSVAL(obj);
 
       // Copy the blob over to the JS array.
       for (uint32_t i = 0; i < length; i++) {
--- a/testing/marionette/client/marionette/tests/unit-tests.ini
+++ b/testing/marionette/client/marionette/tests/unit-tests.ini
@@ -19,8 +19,9 @@ skip = false
 [include:../../../../../dom/telephony/test/marionette/manifest.ini]
 [include:../../../../../dom/voicemail/test/marionette/manifest.ini]
 [include:../../../../../dom/battery/test/marionette/manifest.ini]
 [include:../../../../../dom/mobilemessage/tests/marionette/manifest.ini]
 [include:../../../../../dom/mobileconnection/tests/marionette/manifest.ini]
 [include:../../../../../dom/system/gonk/tests/marionette/manifest.ini]
 [include:../../../../../dom/icc/tests/marionette/manifest.ini]
 [include:../../../../../dom/system/tests/marionette/manifest.ini]
+[include:../../../../../dom/nfc/tests/marionette/manifest.ini]
--- a/testing/mochitest/mochitest_options.py
+++ b/testing/mochitest/mochitest_options.py
@@ -378,16 +378,24 @@ class MochitestOptions(optparse.OptionPa
         }],
         [["--dump-dmd-after-test"],
          { "action": "store_true",
            "default": False,
            "dest": "dumpDMDAfterTest",
            "help": "Produce a DMD dump after each test in the directory specified "
                   "by --dump-output-directory."
         }],
+        [["--slowscript"],
+         { "action": "store_true",
+           "default": False,
+           "dest": "slowscript",
+           "help": "Do not set the JS_DISABLE_SLOW_SCRIPT_SIGNALS env variable; "
+                   "when not set, recoverable but misleading SIGSEGV instances "
+                   "may occur in Ion/Odin JIT code."
+        }],
     ]
 
     def __init__(self, **kwargs):
 
         optparse.OptionParser.__init__(self, **kwargs)
         for option, value in self.mochitest_options:
             self.add_option(*option, **value)
         addCommonOptions(self)
--- a/toolkit/components/downloads/nsDownloadScanner.h
+++ b/toolkit/components/downloads/nsDownloadScanner.h
@@ -6,17 +6,16 @@
 /* vim: se cin sw=2 ts=2 et : */
 
 #ifndef nsDownloadScanner_h_
 #define nsDownloadScanner_h_
 
 #ifdef WIN32_LEAN_AND_MEAN
 #undef WIN32_LEAN_AND_MEAN
 #endif
-#define INITGUID
 #include <windows.h>
 #define AVVENDOR
 #include <objidl.h>
 #include <msoav.h>
 #include <shlobj.h>
 
 #include "nsAutoPtr.h"
 #include "nsThreadUtils.h"
--- a/toolkit/components/places/History.cpp
+++ b/toolkit/components/places/History.cpp
@@ -243,17 +243,17 @@ GetJSArrayFromJSValue(JS::Handle<JS::Val
       NS_ENSURE_ARG(*_arrayLength > 0);
       return NS_OK;
     }
   }
 
   // Build a temporary array to store this one item so the code below can
   // just loop.
   *_arrayLength = 1;
-  _array.set(JS_NewArrayObject(aCtx, 0, nullptr));
+  _array.set(JS_NewArrayObject(aCtx, 0));
   NS_ENSURE_TRUE(_array, NS_ERROR_OUT_OF_MEMORY);
 
   bool rc = JS_DefineElement(aCtx, _array, 0, aValue, nullptr, nullptr, 0);
   NS_ENSURE_TRUE(rc, NS_ERROR_UNEXPECTED);
   return NS_OK;
 }
 
 /**
--- a/toolkit/components/places/PlaceInfo.cpp
+++ b/toolkit/components/places/PlaceInfo.cpp
@@ -96,17 +96,17 @@ PlaceInfo::GetVisits(JSContext* aContext
   if (!mVisitsAvailable) {
     _visits.setNull();
     return NS_OK;
   }
 
   // TODO bug 625913 when we use this in situations that have more than one
   // visit here, we will likely want to make this cache the value.
   JS::Rooted<JSObject*> visits(aContext,
-                               JS_NewArrayObject(aContext, 0, nullptr));
+                               JS_NewArrayObject(aContext, 0));
   NS_ENSURE_TRUE(visits, NS_ERROR_OUT_OF_MEMORY);
 
   JS::Rooted<JSObject*> global(aContext, JS::CurrentGlobalOrNull(aContext));
   NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
 
   nsCOMPtr<nsIXPConnect> xpc = mozilla::services::GetXPConnect();
 
   for (VisitsArray::size_type idx = 0; idx < mVisits.Length(); idx++) {
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -453,27 +453,26 @@ bool TelemetryIOInterposeObserver::Refle
   // Let's not report arrays containing [0, 0, 0, 0, 0, 0]
   if (entry->mData.totalTime == 0 && entry->mData.creates == 0 &&
       entry->mData.reads == 0 && entry->mData.writes == 0 &&
       entry->mData.fsyncs == 0 && entry->mData.stats == 0) {
     return true;
   }
 
   // Array we want to report
-  jsval stats[] = {
-    JS_NumberValue(entry->mData.totalTime),
-    UINT_TO_JSVAL(entry->mData.creates),
-    UINT_TO_JSVAL(entry->mData.reads),
-    UINT_TO_JSVAL(entry->mData.writes),
-    UINT_TO_JSVAL(entry->mData.fsyncs),
-    UINT_TO_JSVAL(entry->mData.stats)
-  };
+  JS::AutoValueArray<6> stats(cx);
+  stats[0].setNumber(entry->mData.totalTime);
+  stats[1].setNumber(entry->mData.creates);
+  stats[2].setNumber(entry->mData.reads);
+  stats[3].setNumber(entry->mData.writes);
+  stats[4].setNumber(entry->mData.fsyncs);
+  stats[5].setNumber(entry->mData.stats);
 
   // Create jsEntry as array of elements above
-  JS::RootedObject jsEntry(cx, JS_NewArrayObject(cx, ArrayLength(stats), stats));
+  JS::RootedObject jsEntry(cx, JS_NewArrayObject(cx, stats));
   if (!jsEntry) {
     return false;
   }
 
   // Add jsEntry to top-level dictionary
   const nsAString& key = entry->GetKey();
   return JS_DefineUCProperty(cx, obj, key.Data(), key.Length(),
                              OBJECT_TO_JSVAL(jsEntry), NULL, NULL,
@@ -799,27 +798,27 @@ ReflectHistogramAndSamples(JSContext *cx
     uint32_t hi = static_cast<uint32_t>(sum_squares >> 32);
     if (!(JS_DefineProperty(cx, obj, "sum_squares_lo", INT_TO_JSVAL(lo), nullptr, nullptr, JSPROP_ENUMERATE)
           && JS_DefineProperty(cx, obj, "sum_squares_hi", INT_TO_JSVAL(hi), nullptr, nullptr, JSPROP_ENUMERATE))) {
       return REFLECT_FAILURE;
     }
   }
 
   const size_t count = h->bucket_count();
-  JS::Rooted<JSObject*> rarray(cx, JS_NewArrayObject(cx, count, nullptr));
+  JS::Rooted<JSObject*> rarray(cx, JS_NewArrayObject(cx, count));
   if (!rarray) {
     return REFLECT_FAILURE;
   }
   if (!(FillRanges(cx, rarray, h)
         && JS_DefineProperty(cx, obj, "ranges", OBJECT_TO_JSVAL(rarray),
                              nullptr, nullptr, JSPROP_ENUMERATE))) {
     return REFLECT_FAILURE;
   }
 
-  JS::Rooted<JSObject*> counts_array(cx, JS_NewArrayObject(cx, count, nullptr));
+  JS::Rooted<JSObject*> counts_array(cx, JS_NewArrayObject(cx, count));
   if (!counts_array) {
     return REFLECT_FAILURE;
   }
   if (!JS_DefineProperty(cx, obj, "counts", OBJECT_TO_JSVAL(counts_array),
                          nullptr, nullptr, JSPROP_ENUMERATE)) {
     return REFLECT_FAILURE;
   }
   for (size_t i = 0; i < count; i++) {
@@ -1240,17 +1239,17 @@ TelemetryImpl::ReflectSQL(const SlowSQLE
                           JSContext *cx,
                           JS::Handle<JSObject*> obj)
 {
   if (stat->hitCount == 0)
     return true;
 
   const nsACString &sql = entry->GetKey();
 
-  JS::Rooted<JSObject*> arrayObj(cx, JS_NewArrayObject(cx, 0, nullptr));
+  JS::Rooted<JSObject*> arrayObj(cx, JS_NewArrayObject(cx, 0));
   if (!arrayObj) {
     return false;
   }
   return (JS_SetElement(cx, arrayObj, 0, stat->hitCount)
           && JS_SetElement(cx, arrayObj, 1, stat->totalTime)
           && JS_DefineProperty(cx, obj,
                                sql.BeginReading(),
                                OBJECT_TO_JSVAL(arrayObj),
@@ -1734,19 +1733,19 @@ TelemetryImpl::GetChromeHangs(JSContext 
   const CombinedStacks& stacks = mHangReports.GetStacks();
   JS::Rooted<JSObject*> fullReportObj(cx, CreateJSStackObject(cx, stacks));
   if (!fullReportObj) {
     return NS_ERROR_FAILURE;
   }
 
   ret.setObject(*fullReportObj);
 
-  JS::Rooted<JSObject*> durationArray(cx, JS_NewArrayObject(cx, 0, nullptr));
-  JS::Rooted<JSObject*> systemUptimeArray(cx, JS_NewArrayObject(cx, 0, nullptr));
-  JS::Rooted<JSObject*> firefoxUptimeArray(cx, JS_NewArrayObject(cx, 0, nullptr));
+  JS::Rooted<JSObject*> durationArray(cx, JS_NewArrayObject(cx, 0));
+  JS::Rooted<JSObject*> systemUptimeArray(cx, JS_NewArrayObject(cx, 0));
+  JS::Rooted<JSObject*> firefoxUptimeArray(cx, JS_NewArrayObject(cx, 0));
   if (!durationArray || !systemUptimeArray || !firefoxUptimeArray) {
     return NS_ERROR_FAILURE;
   }
 
   bool ok = JS_DefineProperty(cx, fullReportObj, "durations",
                               OBJECT_TO_JSVAL(durationArray),
                               nullptr, nullptr, JSPROP_ENUMERATE);
   if (!ok) {
@@ -1785,34 +1784,34 @@ TelemetryImpl::GetChromeHangs(JSContext 
 
 static JSObject *
 CreateJSStackObject(JSContext *cx, const CombinedStacks &stacks) {