Merge m-c to fx-team. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 22 Dec 2014 17:59:25 -0500
changeset 220972 b85f2f139c4d86f7b0f5eb366c646299246353cd
parent 220971 32b3c028d71b3df0528662d0a14d66090fb1aa39 (current diff)
parent 220949 f6d10f05f6e9f0631267d5c426e523fb525dd451 (diff)
child 220973 e9b0a695aa9d424334242eb93d8f6488e295c8ff
push id28008
push usercbook@mozilla.com
push dateTue, 23 Dec 2014 15:05:07 +0000
treeherdermozilla-central@1813b5782036 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fx-team. a=merge
dom/mobileconnection/tests/marionette/test_mobile_mmi.js
dom/mobileconnection/tests/marionette/test_mobile_mmi_call_forwarding.js
dom/mobileconnection/tests/marionette/test_mobile_mmi_change_pin.js
dom/xul/nsIXULContextMenuBuilder.idl
dom/xul/nsXULContextMenuBuilder.cpp
dom/xul/nsXULContextMenuBuilder.h
js/xpconnect/tests/idl/Makefile.in
widget/gonk/nativewindow/GonkBufferQueue.h
widget/gonk/nativewindow/GonkBufferQueueJB.cpp
widget/gonk/nativewindow/GonkBufferQueueJB.h
widget/gonk/nativewindow/GonkConsumerBaseJB.cpp
widget/gonk/nativewindow/GonkConsumerBaseJB.h
widget/gonk/nativewindow/GonkNativeWindowClientJB.cpp
widget/gonk/nativewindow/GonkNativeWindowClientJB.h
widget/gonk/nativewindow/GonkNativeWindowJB.cpp
widget/gonk/nativewindow/GonkNativeWindowJB.h
widget/gonk/nativewindow/IGonkGraphicBufferConsumer.cpp
widget/gonk/nativewindow/IGonkGraphicBufferConsumer.h
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,14 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1105308 - Cleanup BluetoothUtils.{cpp,h}
-
-This patch set moves some files around and requires a rebuild
-of the build system's dependency information.
-
-Merge day clobber
+Bug 1066383 - Clobber needed due to build system not reliably picking up an IDL removal.
--- a/b2g/components/LogShake.jsm
+++ b/b2g/components/LogShake.jsm
@@ -257,68 +257,79 @@ function getLogFilename(logLocation) {
   }
   return logName + '.log';
 }
 
 function getSdcardPrefix() {
   return volumeService.getVolumeByName('sdcard').mountPoint;
 }
 
+function getLogDirectoryRoot() {
+  return 'logs';
+}
+
 function getLogDirectory() {
   let d = new Date();
   d = new Date(d.getTime() - d.getTimezoneOffset() * 60000);
   let timestamp = d.toISOString().slice(0, -5).replace(/[:T]/g, '-');
   // return directory name of format 'logs/timestamp/'
-  return OS.Path.join('logs', timestamp);
+  return timestamp;
 }
 
 /**
  * Save the formatted arrays of log files to an sdcard if available
  */
 function saveLogs(logArrays) {
   if (!logArrays || Object.keys(logArrays).length === 0) {
     return Promise.resolve({
       logFilenames: [],
       logPrefix: ''
     });
   }
 
-  let sdcardPrefix, dirName;
+  let sdcardPrefix, dirNameRoot, dirName;
   try {
     sdcardPrefix = getSdcardPrefix();
+    dirNameRoot = getLogDirectoryRoot();
     dirName = getLogDirectory();
   } catch(e) {
     // Return promise failed with exception e
     // Handles missing sdcard
     return Promise.reject(e);
   }
 
-  debug('making a directory all the way from '+sdcardPrefix+' to '+(sdcardPrefix + '/' + dirName));
-  return OS.File.makeDir(OS.Path.join(sdcardPrefix, dirName), {from: sdcardPrefix})
-    .then(function() {
-    // Now the directory is guaranteed to exist, save the logs
-    let logFilenames = [];
-    let saveRequests = [];
+  debug('making a directory all the way from '+sdcardPrefix+' to '+(sdcardPrefix + '/' + dirNameRoot + '/' + dirName));
+  let logsRoot = OS.Path.join(sdcardPrefix, dirNameRoot);
+  return OS.File.makeDir(logsRoot, {from: sdcardPrefix}).then(
+    function() {
+      let logsDir = OS.Path.join(logsRoot, dirName);
+      return OS.File.makeDir(logsDir, {ignoreExisting: false}).then(
+        function() {
+          // Now the directory is guaranteed to exist, save the logs
+          let logFilenames = [];
+          let saveRequests = [];
 
-    for (let logLocation in logArrays) {
-      debug('requesting save of ' + logLocation);
-      let logArray = logArrays[logLocation];
-      // The filename represents the relative path within the SD card, not the
-      // absolute path because Gaia will refer to it using the DeviceStorage
-      // API
-      let filename = OS.Path.join(dirName, getLogFilename(logLocation));
-      logFilenames.push(filename);
-      let saveRequest = OS.File.writeAtomic(OS.Path.join(sdcardPrefix, filename), logArray);
-      saveRequests.push(saveRequest);
-    }
+          for (let logLocation in logArrays) {
+            debug('requesting save of ' + logLocation);
+            let logArray = logArrays[logLocation];
+            // The filename represents the relative path within the SD card, not the
+            // absolute path because Gaia will refer to it using the DeviceStorage
+            // API
+            let filename = OS.Path.join(dirNameRoot, dirName, getLogFilename(logLocation));
+            logFilenames.push(filename);
+            let saveRequest = OS.File.writeAtomic(OS.Path.join(sdcardPrefix, filename), logArray);
+            saveRequests.push(saveRequest);
+          }
 
-    return Promise.all(saveRequests).then(function() {
-      debug('returning logfilenames: '+logFilenames.toSource());
-      return {
-        logFilenames: logFilenames,
-        logPrefix: dirName
-      };
+          return Promise.all(saveRequests).then(
+            function() {
+              debug('returning logfilenames: '+logFilenames.toSource());
+              return {
+                logFilenames: logFilenames,
+                logPrefix: OS.Path.join(dirNameRoot, dirName)
+              };
+            });
+        });
     });
-  });
 }
 
 LogShake.init();
 this.LogShake = LogShake;
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -7,20 +7,20 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
+  <project name="platform_build" path="build" remote="b2g" revision="e0c735ec89df011ea7dd435087a9045ecff9ff9e">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5b03a9b40a37947d44a71eccd9017e76632f796"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c2da2bafd4e809317e2ca70c9bf5c11136a32818"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f11d3c6500659e3232fbe6fe7ea0204c40ab7fdd"/>
@@ -108,17 +108,17 @@
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="aac6c4bb59a6577c97cbda68699829b507b7490d"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="fbeca55f4695dd07c0291213403533b8fbca4885"/>
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="a8449b1de00c313a4ca90d55af44c9b706b17926"/>
   <project name="platform/libcore" path="libcore" revision="e195beab082c09217318fc19250caeaf4c1bd800"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="feeb36c2bd4adfe285f98f5de92e0f3771b2c115"/>
   <project name="platform/ndk" path="ndk" revision="e58ef003be4306bb53a8c11331146f39e4eab31f"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="0e7c060db684b409616fe67ea433ef19f5634c60"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="c792f0bd9fff7aea2887c60bbb3a9bbdb534ffa3"/>
-  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="c24c8871173bf6aedcf236cab075edf092a7015c"/>
+  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="cfcef469537869947abb9aa1d656774cc2678d4c"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
   <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="288db53ad77084bd44791add5e3a4c266a6e9c60"/>
   <project name="platform/system/extras" path="system/extras" revision="10e78a05252b3de785f88c2d0b9ea8a428009c50"/>
   <project name="platform/system/media" path="system/media" revision="7ff72c2ea2496fa50b5e8a915e56e901c3ccd240"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="fe95bc6f83af5c18a73aa86c96e7fa7f79b91477"/>
   <project name="platform/system/netd" path="system/netd" revision="3ae56364946d4a5bf5a5f83f12f9a45a30398e33"/>
   <project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c5b03a9b40a37947d44a71eccd9017e76632f796"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c2da2bafd4e809317e2ca70c9bf5c11136a32818"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="6fa7a4936414ceb4055fd27f7a30e76790f834fb"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f11d3c6500659e3232fbe6fe7ea0204c40ab7fdd"/>
   <!-- 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
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5b03a9b40a37947d44a71eccd9017e76632f796"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c2da2bafd4e809317e2ca70c9bf5c11136a32818"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f11d3c6500659e3232fbe6fe7ea0204c40ab7fdd"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -7,20 +7,20 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
+  <project name="platform_build" path="build" remote="b2g" revision="e0c735ec89df011ea7dd435087a9045ecff9ff9e">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5b03a9b40a37947d44a71eccd9017e76632f796"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c2da2bafd4e809317e2ca70c9bf5c11136a32818"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f11d3c6500659e3232fbe6fe7ea0204c40ab7fdd"/>
@@ -108,32 +108,32 @@
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="eb6077f10ae6255a72337124188f0e08dcd10e3e"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="3b80c725cea54132df05d208930d91e00d19f999"/>
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="01f436c51dc68aec7cc1c85fda6e6792b2a95066"/>
   <project name="platform/libcore" path="libcore" revision="9877ade9617bb0db6e59aa2a54719a9bc92600f3"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="46c96ace65eb1ccab05bf15b9bf8e53e443039af"/>
   <project name="platform/ndk" path="ndk" revision="cb5519af32ae7b4a9c334913a612462ecd04c5d0"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="0e7c060db684b409616fe67ea433ef19f5634c60"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="6aa61f8557a22039a30b42b7f283996381fd625d"/>
-  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="c24c8871173bf6aedcf236cab075edf092a7015c"/>
+  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="b562b01c93de9578d5db537b6a602a38e1aaa0ce"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="387f03e815f57d536dd922706db1622bddba8d81"/>
   <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="288db53ad77084bd44791add5e3a4c266a6e9c60"/>
   <project name="platform/system/extras" path="system/extras" revision="5356165f67f4a81c2ef28671c13697f1657590df"/>
   <project name="platform/system/media" path="system/media" revision="be0e2fe59a8043fa5200f75697df9220a99abe9d"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="fe95bc6f83af5c18a73aa86c96e7fa7f79b91477"/>
   <project name="platform/system/netd" path="system/netd" revision="36704b0da24debcab8090156568ac236315036bb"/>
   <project name="platform/system/security" path="system/security" revision="583374f69f531ba68fc3dcbff1f74893d2a96406"/>
   <project name="platform/system/vold" path="system/vold" revision="d4455b8cf361f8353e8aebac15ffd64b4aedd2b9"/>
   <project name="platform/external/icu4c" path="external/icu4c" remote="aosp" revision="b4c6379528887dc25ca9991a535a8d92a61ad6b6"/>
   <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="614747e5e6755ffcdb36156ea82d8b5c1609a3af"/>
   <project name="platform_system_core" path="system/core" remote="b2g" revision="9395eb5aa885cf6d305a202de6e9694a58a89717"/>
   <default remote="caf" revision="refs/tags/android-4.4.2_r1" sync-j="4"/>
   <!-- Emulator specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="c0e0019a6ec1a6199a9c7bc4ace041259f3b8512"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="615f94d1fb5a75211485a81fcaa8baed7731bfb7"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a510f2d2d579e76421b0c84cd225c249b2da6f8a"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="694cecf256122d0cb3b6a1a4efb4b5c7401db223"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="97d63c256a047b491565d624aea1dd5f1f8593ea"/>
   <project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
   <project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
 </manifest>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c5b03a9b40a37947d44a71eccd9017e76632f796"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c2da2bafd4e809317e2ca70c9bf5c11136a32818"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="6fa7a4936414ceb4055fd27f7a30e76790f834fb"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f11d3c6500659e3232fbe6fe7ea0204c40ab7fdd"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -7,20 +7,20 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
+  <project name="platform_build" path="build" remote="b2g" revision="e0c735ec89df011ea7dd435087a9045ecff9ff9e">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5b03a9b40a37947d44a71eccd9017e76632f796"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c2da2bafd4e809317e2ca70c9bf5c11136a32818"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f11d3c6500659e3232fbe6fe7ea0204c40ab7fdd"/>
@@ -108,17 +108,17 @@
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="f0c3b4edf597c40aae4ea311575f39c8bcf203df"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="9a60e685a9fb38a716f18a89cd872942f75b4706"/>
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="adb52b35ecb523bd332854945c09828ee887e575"/>
   <project name="platform/libcore" path="libcore" revision="baf7d8068dd501cfa338d3a8b1b87216d6ce0571"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="50c4430e32849530ced32680fd6ee98963b3f7ac"/>
   <project name="platform/ndk" path="ndk" revision="e58ef003be4306bb53a8c11331146f39e4eab31f"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="0e7c060db684b409616fe67ea433ef19f5634c60"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="c792f0bd9fff7aea2887c60bbb3a9bbdb534ffa3"/>
-  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="c24c8871173bf6aedcf236cab075edf092a7015c"/>
+  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="69d524e80cdf3981006627c65ac85f3a871238a3"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
   <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="288db53ad77084bd44791add5e3a4c266a6e9c60"/>
   <project name="platform/system/extras" path="system/extras" revision="576f57b6510de59c08568b53c0fb60588be8689e"/>
   <project name="platform/system/media" path="system/media" revision="20c2fb4c896aa59f2e8379d755f439dc59a5cf9b"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="fe95bc6f83af5c18a73aa86c96e7fa7f79b91477"/>
   <project name="platform/system/netd" path="system/netd" revision="a6531f7befb49b1c81bc0de7e51c5482b308e1c5"/>
   <project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
@@ -132,19 +132,21 @@
   <remove-project name="platform/system/media"/>
   <project name="platform/system/media" path="system/media" revision="c1332c21c608f4932a6d7e83450411cde53315ef"/>
   <!--original fetch url was git://github.com/t2m-foxfone/-->
   <remote fetch="https://git.mozilla.org/external/t2m-foxfone" name="t2m"/>
   <default remote="caf" revision="LNX.LA.3.5.2.1.1" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="54c32c2ddef066fbdf611d29e4b7c47e0363599e"/>
-  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="e5c6b275d77ca95fb0f2051c3d2242e6e0d0e442"/>
+  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="a814b2e2dfdda7140cb3a357617dc4fbb1435e76"/>
   <project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="48b6a2c9fde18f2f7d9abddf05261c498c2bb2ba"/>
   <project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="fda40423ffa573dc6cafd3780515010cb2a086be"/>
+  <remove-project name="platform/bootable/recovery"/>
+  <project name="platform_bootable_recovery" path="bootable/recovery" remote="b2g" revision="26e78a979f3090dc196219e268467620b6c40ec5"/>
   <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="30b96dfca99cb384bf520a16b81f3aba56f09907"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="5b71e40213f650459e95d35b6f14af7e88d8ab62"/>
   <project name="platform_external_libnfc-nci" path="external/libnfc-nci" remote="t2m" revision="4186bdecb4dae911b39a8202252cc2310d91b0be"/>
   <project name="platform/frameworks/av" path="frameworks/av" revision="c00de33ebfad57ae79ad5f93c2819ee2c40c8bcd"/>
   <project name="platform/frameworks/base" path="frameworks/base" revision="6b58ab45e3e56c1fc20708cc39fa2264c52558df"/>
   <project name="platform/frameworks/native" path="frameworks/native" revision="a46a9f1ac0ed5662d614c277cbb14eb3f332f365"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="7196881a0e9dd7bfbbcf0af64c8064e70f0fa094"/>
   <project name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="8d7676dfb68ee0cd069affedd5d1e97316a184ba"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5b03a9b40a37947d44a71eccd9017e76632f796"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c2da2bafd4e809317e2ca70c9bf5c11136a32818"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f11d3c6500659e3232fbe6fe7ea0204c40ab7fdd"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "24f27472ae6ddb6c819227cb3b7d398a6925ef86", 
+    "revision": "b60aedd37a5ccdb71893d31761988bcc17a82676", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c5b03a9b40a37947d44a71eccd9017e76632f796"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c2da2bafd4e809317e2ca70c9bf5c11136a32818"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f11d3c6500659e3232fbe6fe7ea0204c40ab7fdd"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c5b03a9b40a37947d44a71eccd9017e76632f796"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c2da2bafd4e809317e2ca70c9bf5c11136a32818"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="c5b03a9b40a37947d44a71eccd9017e76632f796"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c2da2bafd4e809317e2ca70c9bf5c11136a32818"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f11d3c6500659e3232fbe6fe7ea0204c40ab7fdd"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c5b03a9b40a37947d44a71eccd9017e76632f796"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c2da2bafd4e809317e2ca70c9bf5c11136a32818"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f11d3c6500659e3232fbe6fe7ea0204c40ab7fdd"/>
   <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/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -396,16 +396,18 @@
 @BINPATH@/components/nsDownloadManagerUI.manifest
 @BINPATH@/components/nsDownloadManagerUI.js
 @BINPATH@/components/Downloads.manifest
 @BINPATH@/components/DownloadLegacy.js
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
 @BINPATH@/components/nsAsyncShutdown.manifest
 @BINPATH@/components/nsAsyncShutdown.js
+@BINPATH@/components/htmlMenuBuilder.js
+@BINPATH@/components/htmlMenuBuilder.manifest
 
 ; WiFi, NetworkManager, NetworkStats
 #ifdef MOZ_WIDGET_GONK
 @BINPATH@/components/DOMWifiManager.js
 @BINPATH@/components/DOMWifiManager.manifest
 @BINPATH@/components/DOMWifiP2pManager.js
 @BINPATH@/components/DOMWifiP2pManager.manifest
 @BINPATH@/components/NetworkInterfaceListService.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -254,20 +254,20 @@ XPCOMUtils.defineLazyGetter(this, "Win7F
 });
 
 #ifdef MOZ_CRASHREPORTER
 XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter",
                                    "@mozilla.org/xre/app-info;1",
                                    "nsICrashReporter");
 #endif
 
-XPCOMUtils.defineLazyGetter(this, "PageMenu", function() {
+XPCOMUtils.defineLazyGetter(this, "PageMenuParent", function() {
   let tmp = {};
   Cu.import("resource://gre/modules/PageMenu.jsm", tmp);
-  return new tmp.PageMenu();
+  return new tmp.PageMenuParent();
 });
 
 /**
 * We can avoid adding multiple load event listeners and save some time by adding
 * one listener that calls all real handlers.
 */
 function pageShowEventHandlers(persisted) {
   XULBrowserWindow.asyncUpdateUI();
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -38,16 +38,21 @@ XPCOMUtils.defineLazyGetter(this, "Simpl
       return new RokuApp(aService);
     },
     mirror: true,
     types: ["video/mp4"],
     extensions: ["mp4"]
   });
   return ssdp;
 });
+XPCOMUtils.defineLazyGetter(this, "PageMenuChild", function() {
+  let tmp = {};
+  Cu.import("resource://gre/modules/PageMenu.jsm", tmp);
+  return new tmp.PageMenuChild();
+});
 
 // TabChildGlobal
 var global = this;
 
 // Load the form validation popup handler
 var formSubmitObserver = new FormSubmitObserver(content, this);
 
 addMessageListener("Browser:HideSessionRestoreButton", function (message) {
@@ -97,16 +102,20 @@ addMessageListener("SecondScreen:tab-mir
   if (app) {
     let width = content.innerWidth;
     let height = content.innerHeight;
     let viewport = {cssWidth: width, cssHeight: height, width: width, height: height};
     app.mirror(function() {}, content, viewport, function() {}, content);
   }
 });
 
+addMessageListener("ContextMenu:DoCustomCommand", function(message) {
+  PageMenuChild.executeMenu(message.data);
+});
+
 addEventListener("DOMFormHasPassword", function(event) {
   InsecurePasswordUtils.checkForInsecurePasswords(event.target);
   LoginManagerContent.onFormPassword(event);
 });
 addEventListener("DOMAutoComplete", function(event) {
   LoginManagerContent.onUsernameInput(event);
 });
 addEventListener("blur", function(event) {
@@ -143,17 +152,18 @@ let handleContentContextMenu = function 
     let editFlags = SpellCheckHelper.isEditable(event.target, content);
     let spellInfo;
     if (editFlags &
         (SpellCheckHelper.EDITABLE | SpellCheckHelper.CONTENTEDITABLE)) {
       spellInfo =
         InlineSpellCheckerContent.initContextMenu(event, editFlags, this);
     }
 
-    sendSyncMessage("contextmenu", { editFlags, spellInfo, addonInfo }, { event, popupNode: event.target });
+    let customMenuItems = PageMenuChild.build(event.target);
+    sendSyncMessage("contextmenu", { editFlags, spellInfo, customMenuItems, addonInfo }, { event, popupNode: event.target });
   }
   else {
     // Break out to the parent window and pass the add-on info along
     let browser = docShell.chromeEventHandler;
     let mainWin = browser.ownerDocument.defaultView;
     mainWin.gContextMenuContentData = {
       isRemote: false,
       event: event,
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -19,20 +19,25 @@ nsContextMenu.prototype = {
   initMenu: function CM_initMenu(aXulMenu, aIsShift) {
     // Get contextual info.
     this.setTarget(document.popupNode, document.popupRangeParent,
                    document.popupRangeOffset);
     if (!this.shouldDisplay)
       return;
 
     this.hasPageMenu = false;
-    // FIXME (bug 1047751) - The page menu is disabled in e10s.
-    if (!aIsShift && !this.isRemote) {
-      this.hasPageMenu = PageMenu.maybeBuildAndAttachMenu(this.target,
-                                                          aXulMenu);
+    if (!aIsShift) {
+      if (this.isRemote) {
+        this.hasPageMenu =
+          PageMenuParent.addToPopup(gContextMenuContentData.customMenuItems,
+                                    this.browser, aXulMenu);
+      }
+      else {
+        this.hasPageMenu = PageMenuParent.buildAndAddToPopup(this.target, aXulMenu);
+      }
     }
 
     this.isFrameImage = document.getElementById("isFrameImage");
     this.ellipsis = "\u2026";
     try {
       this.ellipsis = gPrefService.getComplexValue("intl.ellipsis",
                                                    Ci.nsIPrefLocalizedString).data;
     } catch (e) { }
@@ -1761,17 +1766,17 @@ nsContextMenu.prototype = {
       }
       // Target should be in the menu (this catches using shortcuts for items
       // not in the menu while the menu is up)
       if (!aXulMenu.contains(e.target)) {
         return;
       }
 
       // Check if this is a page menu item:
-      if (e.target.hasAttribute(PageMenu.GENERATEDITEMID_ATTR)) {
+      if (e.target.hasAttribute(PageMenuParent.GENERATEDITEMID_ATTR)) {
         this._telemetryClickID = "custom-page-item";
       } else {
         this._telemetryClickID = (e.target.id || "unknown").replace(/^context-/i, "");
       }
     };
     aXulMenu.ownerDocument.addEventListener("command", activationHandler, true);
     aXulMenu.addEventListener("popuphiding", this._onPopupHiding, true);
   },
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3170,16 +3170,17 @@
               if (spellInfo)
                 spellInfo.target = aMessage.target.messageManager;
               gContextMenuContentData = { isRemote: true,
                                           event: aMessage.objects.event,
                                           popupNode: aMessage.objects.popupNode,
                                           browser: browser,
                                           editFlags: aMessage.data.editFlags,
                                           spellInfo: spellInfo,
+                                          customMenuItems: aMessage.data.customMenuItems,
                                           addonInfo: aMessage.data.addonInfo };
               let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
               let event = gContextMenuContentData.event;
               let pos = browser.mapScreenCoordinatesFromContent(event.screenX, event.screenY);
               popup.openPopupAtScreen(pos.x, pos.y, true);
               break;
             }
             case "DOMWebNotificationClicked": {
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -67,16 +67,17 @@ support-files =
   parsingTestHelpers.jsm
   pinning_headers.sjs
   pinning_reports.sjs
   popup_blocker.html
   print_postdata.sjs
   redirect_bug623155.sjs
   searchSuggestionEngine.sjs
   searchSuggestionEngine.xml
+  subtst_contextmenu.html
   test-mixedcontent-securityerrors.html
   test_bug435035.html
   test_bug462673.html
   test_bug628179.html
   test_bug839103.html
   test_bug959531.html
   test_wyciwyg_copying.html
   title_test.svg
@@ -481,9 +482,10 @@ skip-if = e10s
 skip-if = e10s # Bug 1100687 - test directly manipulates content (content.document.getElementById)
 [browser_bug1045809.js]
 [browser_e10s_switchbrowser.js]
 [browser_blockHPKP.js]
 skip-if = e10s # bug 1100687 - test directly manipulates content (content.document.getElementById)
 [browser_mcb_redirect.js]
 skip-if = e10s # bug 1084504 - [e10s] Mixed content detection does not take redirection into account
 [browser_windowactivation.js]
+[browser_contextmenu_childprocess.js]
 [browser_bug963945.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_contextmenu_childprocess.js
@@ -0,0 +1,87 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const gBaseURL = "https://example.com/browser/browser/base/content/test/general/";
+
+add_task(function *() {
+  let tab = gBrowser.addTab();
+  let browser = gBrowser.getBrowserForTab(tab);
+
+  gBrowser.selectedTab = tab;
+  yield promiseTabLoadEvent(tab, gBaseURL + "subtst_contextmenu.html");
+
+  let popupShownPromise = promiseWaitForEvent(window, "popupshown", true);
+
+  // Get the point of the element with the page menu (test-pagemenu) and
+  // synthesize a right mouse click there.
+  let eventDetails = { type : "contextmenu", button : 2 };
+  let rect = browser.contentWindow.document.getElementById("test-pagemenu").getBoundingClientRect();
+  EventUtils.synthesizeMouse(browser, rect.x + rect.width / 2, rect.y + rect.height / 2, eventDetails, window);
+
+  let event = yield popupShownPromise;
+
+  let contextMenu = document.getElementById("contentAreaContextMenu");
+  checkMenu(contextMenu);
+  contextMenu.hidePopup();
+  gBrowser.removeCurrentTab();
+});
+
+function checkItems(menuitem, arr)
+{
+  for (let i = 0; i < arr.length; i += 2) {
+    let str = arr[i];
+    let details = arr[i + 1];
+    if (str == "---") {
+      is(menuitem.localName, "menuseparator", "menuseparator");
+    }
+    else if ("children" in details) {
+      is(menuitem.localName, "menu", "submenu");
+      is(menuitem.getAttribute("label"), str, str + " label");
+      checkItems(menuitem.firstChild.firstChild, details.children);
+    }
+    else {
+      is(menuitem.localName, "menuitem", str + " menuitem");
+
+      is(menuitem.getAttribute("label"), str, str + " label");
+      is(menuitem.getAttribute("type"), details.type, str + " type");
+      is(menuitem.getAttribute("image"), details.icon ? gBaseURL + details.icon : "", str + " icon");
+
+      if (details.checked)
+        is(menuitem.getAttribute("checked"), "true", str + " checked");
+      else
+        ok(!menuitem.hasAttribute("checked"), str + " checked");
+
+      if (details.disabled)
+        is(menuitem.getAttribute("disabled"), "true", str + " disabled");
+      else
+        ok(!menuitem.hasAttribute("disabled"), str + " disabled");
+    }
+
+    menuitem = menuitem.nextSibling;
+  }
+}
+
+function checkMenu(contextMenu)
+{
+  let items = [ "Plain item",          {type: "", icon: "", checked: false, disabled: false},
+                "Disabled item",       {type: "", icon: "", checked: false, disabled: true},
+                "Item w/ textContent", {type: "", icon: "", checked: false, disabled: false},
+                "---",                  null,
+                "Checkbox",            {type: "checkbox", icon: "", checked: true, disabled: false},
+                "---",                  null,
+                "Radio1",              {type: "checkbox", icon: "", checked: true, disabled: false},
+                "Radio2",              {type: "checkbox", icon: "", checked: false, disabled: false},
+                "Radio3",              {type: "checkbox", icon: "", checked: false, disabled: false},
+                "---",                  null,
+                "Item w/ icon",        {type: "", icon: "favicon.ico", checked: false, disabled: false},
+                "Item w/ bad icon",    {type: "", icon: "", checked: false, disabled: false},
+                "---",                  null,
+                "Submenu",  { children:
+                  ["Radio1",             {type: "checkbox", icon: "", checked: false, disabled: false},
+                   "Radio2",             {type: "checkbox", icon: "", checked: true, disabled: false},
+                   "Radio3",             {type: "checkbox", icon: "", checked: false, disabled: false},
+                   "---",                 null,
+                   "Checkbox",           {type: "checkbox", icon: "", checked: false, disabled: false}] }
+               ];
+  checkItems(contextMenu.childNodes[2], items);
+}
--- a/browser/base/content/test/general/test_contextmenu.html
+++ b/browser/base/content/test/general/test_contextmenu.html
@@ -490,17 +490,17 @@ function runTest(testNum) {
                           "---",                  null,
                           "context-viewbgimage",  false,
                           "context-selectall",    true,
                           "---",                  null,
                           "context-viewsource",   true,
                           "context-viewinfo",     true
                          ].concat(inspectItems));
 
-        invokeItemAction("0");
+        invokeItemAction("1");
         closeContextMenu();
 
         // run mozRequestFullScreen on the element we're testing
         var full_screen_element = subwindow.document.getElementById("test-dom-full-screen");
         var openDomFullScreen = function() {
             subwindow.removeEventListener("mozfullscreenchange", openDomFullScreen, false);
             openContextMenuFor(dom_full_screen, true); // Invoke context menu for next test.
         }
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -537,16 +537,18 @@
 @RESPATH@/components/Webapps.manifest
 @RESPATH@/components/AppsService.js
 @RESPATH@/components/AppsService.manifest
 @RESPATH@/components/nsDOMIdentity.js
 @RESPATH@/components/nsIDService.js
 @RESPATH@/components/Identity.manifest
 @RESPATH@/components/recording-cmdline.js
 @RESPATH@/components/recording-cmdline.manifest
+@RESPATH@/components/htmlMenuBuilder.js
+@RESPATH@/components/htmlMenuBuilder.manifest
 
 @RESPATH@/components/PermissionSettings.js
 @RESPATH@/components/PermissionSettings.manifest
 @RESPATH@/components/ContactManager.js
 @RESPATH@/components/ContactManager.manifest
 @RESPATH@/components/PhoneNumberService.js
 @RESPATH@/components/PhoneNumberService.manifest
 @RESPATH@/components/NotificationStorage.js
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -72,17 +72,17 @@ ifeq ($(MOZ_WIDGET_TOOLKIT) $(DIST_SUBDI
 SEARCHPLUGINS_NAMES = $(shell cat $(call MERGE_FILE,/searchplugins/metrolist.txt))
 else
 SEARCHPLUGINS_NAMES = $(shell cat $(call MERGE_FILE,/searchplugins/list.txt)) ddg
 endif
 SEARCHPLUGINS_PATH := $(FINAL_TARGET)/searchplugins
 # metro build call a searchplugins target for search engine plugins
 .PHONY: searchplugins
 SEARCHPLUGINS_TARGET := libs searchplugins
-SEARCHPLUGINS := $(foreach plugin,$(addsuffix .xml,$(SEARCHPLUGINS_NAMES)),$(or $(wildcard $(call MERGE_FILE,searchplugins/$(plugin))),$(info Missing searchplugin: $(plugin))))
+SEARCHPLUGINS := $(foreach plugin,$(addsuffix .xml,$(SEARCHPLUGINS_NAMES)),$(or $(wildcard $(call EN_US_OR_L10N_FILE,searchplugins/$(plugin))),$(info Missing searchplugin: $(plugin))))
 # Some locale-specific search plugins may have preprocessor directives, but the
 # default en-US ones do not.
 SEARCHPLUGINS_FLAGS := --silence-missing-directive-warnings
 PP_TARGETS += SEARCHPLUGINS
 
 # Required for l10n.mk - defines a list of app sub dirs that should
 # be included in langpack xpis.
 ifdef MOZ_METRO
--- a/config/config.mk
+++ b/config/config.mk
@@ -609,16 +609,23 @@ MERGE_FILE = $(firstword \
   $(wildcard $(LOCALE_MERGEDIR)/$(subst /locales,,$(relativesrcdir))/$(1)) \
   $(wildcard $(LOCALE_SRCDIR)/$(1)) \
   $(srcdir)/en-US/$(1) )
 else
 MERGE_FILE = $(LOCALE_SRCDIR)/$(1)
 endif
 MERGE_FILES = $(foreach f,$(1),$(call MERGE_FILE,$(f)))
 
+# These marcros are similar to MERGE_FILE, but no merging, and en-US first.
+# They're used for searchplugins, for example.
+EN_US_OR_L10N_FILE = $(firstword \
+  $(wildcard $(srcdir)/en-US/$(1)) \
+  $(LOCALE_SRCDIR)/$(1) )
+EN_US_OR_L10N_FILES = $(foreach f,$(1),$(call EN_US_OR_L10N_FILE,$(f)))
+
 ifneq (WINNT,$(OS_ARCH))
 RUN_TEST_PROGRAM = $(LIBXUL_DIST)/bin/run-mozilla.sh
 endif # ! WINNT
 
 #
 # Java macros
 #
 
--- a/config/makefiles/xpidl/Makefile.in
+++ b/config/makefiles/xpidl/Makefile.in
@@ -17,54 +17,45 @@ include $(topsrcdir)/config/rules.mk
 #
 # XPIDL files are logically grouped together by modules. The typelib
 # information for all XPIDLs in the same module is linked together into
 # an .xpt file having the name of the module.
 #
 # As an optimization to reduce overall CPU usage, we process all .idl
 # belonging to a module with a single command invocation. This prevents
 # redundant parsing of .idl files and significantly reduces CPU cycles.
-#
-# Future improvement: Headers are currently written to a local directory then
-# installed in the distribution directory. It is preferable to write headers
-# directly into the distribution directory. However, PGO builds remove the dist
-# directory via rm -rf (with no regards to manifests). Since the cost of
-# processing XPIDL files is not trivial, it is preferrable to cache the headers
-# and reinstall them rather than regenerate them. Ideally the dist pruning is
-# performed with manifests. At that time we can write headers directly to the
-# dist directory.
 
 # For dependency files.
 idl_deps_dir := .deps
 
-# Where we put our final, linked .xpt files.
-idl_xpt_dir := xpt
-
 dist_idl_dir := $(DIST)/idl
 dist_include_dir := $(DIST)/include
 process_py := $(topsrcdir)/python/mozbuild/mozbuild/action/xpidl-process.py
 
+ifdef LIBXUL_SDK
+libxul_sdk_includes := -I$(LIBXUL_SDK)/idl
+endif
+
 # TODO we should use py_action, but that would require extra directories to be
 # in the virtualenv.
-idlprocess := $(PYTHON_PATH) $(PLY_INCLUDE) -I$(IDL_PARSER_DIR) -I$(IDL_PARSER_CACHE_DIR) \
-    $(process_py) --cache-dir $(IDL_PARSER_CACHE_DIR) $(dist_idl_dir) \
-        $(dist_include_dir) $(idl_xpt_dir) $(idl_deps_dir)
-
-ifdef LIBXUL_SDK
-idlprocess += -I$(LIBXUL_SDK)/idl
-endif
+%.xpt:
+	@echo "$(@F)"
+	$(PYTHON_PATH) $(PLY_INCLUDE) -I$(IDL_PARSER_DIR) -I$(IDL_PARSER_CACHE_DIR) \
+		$(process_py) --cache-dir $(IDL_PARSER_CACHE_DIR) $(dist_idl_dir) \
+		$(dist_include_dir) $(@D) $(idl_deps_dir) $(libxul_sdk_includes) \
+		$(basename $(notdir $@ $(filter %.idl,$^)))
 
 xpidl_modules := @xpidl_modules@
+xpt_files := @xpt_files@
 
 @xpidl_rules@
 
-linked_xpt_files := $(addprefix $(idl_xpt_dir)/,$(addsuffix .xpt,$(xpidl_modules)))
 depends_files := $(foreach root,$(xpidl_modules),$(idl_deps_dir)/$(root).pp)
 
-GARBAGE += $(linked_xpt_files) $(depends_files)
+GARBAGE += $(xpt_files) $(depends_files)
 
-xpidl:: $(linked_xpt_files)
+xpidl:: $(xpt_files)
 
-$(linked_xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir) $(idl_xpt_dir))
+$(xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir))
 
 $(call include_deps,$(depends_files))
 
 .PHONY: xpidl
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1152,21 +1152,16 @@ endif
 endif
 
 ################################################################################
 # Install a linked .xpt into the appropriate place.
 # This should ideally be performed by the non-recursive idl make file. Some day.
 ifdef XPT_NAME #{
 
 ifndef NO_DIST_INSTALL
-_XPT_NAME_FILES := $(DEPTH)/config/makefiles/xpidl/xpt/$(XPT_NAME)
-_XPT_NAME_DEST := $(FINAL_TARGET)/components
-_XPT_NAME_TARGET := misc
-INSTALL_TARGETS += _XPT_NAME
-
 ifndef NO_INTERFACES_MANIFEST
 misc:: $(call mkdir_deps,$(FINAL_TARGET)/components)
 	$(call py_action,buildlist,$(FINAL_TARGET)/components/interfaces.manifest 'interfaces $(XPT_NAME)')
 	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest 'manifest components/interfaces.manifest')
 endif
 endif
 
 endif #} XPT_NAME
--- a/configure.in
+++ b/configure.in
@@ -281,16 +281,17 @@ if test -n "$gonkdir" ; then
         MOZ_AUDIO_OFFLOAD=1
         AC_SUBST(MOZ_AUDIO_OFFLOAD)
         AC_DEFINE(MOZ_AUDIO_OFFLOAD)
         MOZ_FMP4=1
         ;;
     21)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
         MOZ_AUDIO_OFFLOAD=1
+        MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_AUDIO_OFFLOAD)
         AC_DEFINE(MOZ_AUDIO_OFFLOAD)
         MOZ_FMP4=
         ;;
     *)
         AC_MSG_ERROR([Unsupported platform version: $ANDROID_VERSION])
         ;;
     esac
--- a/dom/base/nsScriptLoader.cpp
+++ b/dom/base/nsScriptLoader.cpp
@@ -814,17 +814,22 @@ nsScriptLoader::ProcessOffThreadRequest(
   return rv;
 }
 
 NS_IMETHODIMP
 NotifyOffThreadScriptLoadCompletedRunnable::Run()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsresult rv = mLoader->ProcessOffThreadRequest(mRequest, &mToken);
+  // We want these to be dropped on the main thread, once we return from this
+  // function.
+  nsRefPtr<nsScriptLoadRequest> request = mRequest.forget();
+  nsRefPtr<nsScriptLoader> loader = mLoader.forget();
+
+  nsresult rv = loader->ProcessOffThreadRequest(request, &mToken);
 
   if (mToken) {
     // The result of the off thread parse was not actually needed to process
     // the request (disappearing window, some other error, ...). Finish the
     // request to avoid leaks in the JS engine.
     nsCOMPtr<nsIJSRuntimeService> svc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
     NS_ENSURE_TRUE(svc, NS_ERROR_FAILURE);
     JSRuntime *rt;
--- a/dom/bluetooth/BluetoothRilListener.cpp
+++ b/dom/bluetooth/BluetoothRilListener.cpp
@@ -97,23 +97,16 @@ MobileConnectionListener::NotifyVoiceCha
 
 NS_IMETHODIMP
 MobileConnectionListener::NotifyDataChanged()
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
-MobileConnectionListener::NotifyUssdReceived(const nsAString & message,
-                                             bool sessionEnded)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 MobileConnectionListener::NotifyDataError(const nsAString & message)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MobileConnectionListener::NotifyCFStateChanged(uint16_t action,
                                                uint16_t reason,
--- a/dom/bluetooth2/BluetoothRilListener.cpp
+++ b/dom/bluetooth2/BluetoothRilListener.cpp
@@ -97,23 +97,16 @@ MobileConnectionListener::NotifyVoiceCha
 
 NS_IMETHODIMP
 MobileConnectionListener::NotifyDataChanged()
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
-MobileConnectionListener::NotifyUssdReceived(const nsAString & message,
-                                             bool sessionEnded)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 MobileConnectionListener::NotifyDataError(const nsAString & message)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MobileConnectionListener::NotifyCFStateChanged(uint16_t action,
                                                uint16_t reason,
--- a/dom/html/HTMLMenuElement.cpp
+++ b/dom/html/HTMLMenuElement.cpp
@@ -4,21 +4,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/HTMLMenuElement.h"
 
 #include "mozilla/BasicEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/dom/HTMLMenuElementBinding.h"
 #include "mozilla/dom/HTMLMenuItemElement.h"
+#include "nsIMenuBuilder.h"
 #include "nsAttrValueInlines.h"
 #include "nsContentUtils.h"
-#include "nsXULContextMenuBuilder.h"
 #include "nsIURI.h"
 
+#define HTMLMENUBUILDER_CONTRACTID "@mozilla.org/content/html-menu-builder;1"
+
 NS_IMPL_NS_NEW_HTML_ELEMENT(Menu)
 
 namespace mozilla {
 namespace dom {
 
 enum MenuType
 {
   MENU_TYPE_CONTEXT = 1,
@@ -92,34 +94,31 @@ HTMLMenuElement::SendShowEvent()
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLMenuElement::CreateBuilder(nsIMenuBuilder** _retval)
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
 
-  *_retval = nullptr;
-
-  if (mType == MENU_TYPE_CONTEXT) {
-    NS_ADDREF(*_retval = new nsXULContextMenuBuilder());
-  }
-
+  nsCOMPtr<nsIMenuBuilder> builder = CreateBuilder();
+  builder.swap(*_retval);
   return NS_OK;
 }
 
 already_AddRefed<nsIMenuBuilder>
 HTMLMenuElement::CreateBuilder()
 {
   if (mType != MENU_TYPE_CONTEXT) {
     return nullptr;
   }
 
-  nsCOMPtr<nsIMenuBuilder> ret = new nsXULContextMenuBuilder();
-  return ret.forget();
+  nsCOMPtr<nsIMenuBuilder> builder = do_CreateInstance(HTMLMENUBUILDER_CONTRACTID);
+  NS_WARN_IF(!builder);
+  return builder.forget();
 }
 
 NS_IMETHODIMP
 HTMLMenuElement::Build(nsIMenuBuilder* aBuilder)
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
 
   if (!aBuilder) {
new file mode 100644
--- /dev/null
+++ b/dom/html/htmlMenuBuilder.js
@@ -0,0 +1,132 @@
+/* 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/. */
+
+// This component is used to build the menus for the HTML contextmenu attribute.
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+// A global value that is used to identify each menu item. It is
+// incremented with each one that is found.
+var gGeneratedId = 1;
+
+function HTMLMenuBuilder() {
+  this.currentNode = null;
+  this.root = null;
+  this.items = {};
+  this.nestedStack = [];
+};
+
+// Building is done in two steps:
+// The first generates a hierarchical JS object that contains the menu structure.
+// This object is returned by toJSONString.
+//
+// The second step can take this structure and generate a XUL menu hierarchy or
+// other UI from this object. The default UI is done in PageMenu.jsm.
+//
+// When a multi-process browser is used, the first step is performed by the child
+// process and the second step is performed by the parent process.
+
+HTMLMenuBuilder.prototype =
+{
+  classID:        Components.ID("{51c65f5d-0de5-4edc-9058-60e50cef77f8}"),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIMenuBuilder]),
+
+  currentNode: null,
+  root: null,
+  items: {},
+  nestedStack: [],
+
+  toJSONString: function() {
+    return JSON.stringify(this.root);
+  },
+
+  openContainer: function(aLabel) {
+    if (!this.currentNode) {
+      this.root = {
+        type: "menu",
+        children: []
+      };
+      this.currentNode = this.root;
+    }
+    else {
+      let parent = this.currentNode;
+      this.currentNode = {
+        type: "menu",
+        label: aLabel,
+        children: []
+      };
+      parent.children.push(this.currentNode);
+      this.nestedStack.push(parent);
+    }
+  },
+
+  addItemFor: function(aElement, aCanLoadIcon) {
+    if (!("children" in this.currentNode)) {
+      return;
+    }
+
+    let item = {
+      type: "menuitem",
+      label: aElement.label
+    };
+
+    let elementType = aElement.type;
+    if (elementType == "checkbox" || elementType == "radio") {
+      item.checkbox = true;
+
+      if (aElement.checked) {
+        item.checked = true;
+      }
+    }
+
+    let icon = aElement.icon;
+    if (icon.length > 0 && aCanLoadIcon) {
+      item.icon = icon;
+    }
+
+    if (aElement.disabled) {
+      item.disabled = true;
+    }
+
+    item.id = gGeneratedId++;
+    this.currentNode.children.push(item);
+
+    this.items[item.id] = aElement;
+  },
+
+  addSeparator: function() {
+    if (!("children" in this.currentNode)) {
+      return;
+    }
+
+    this.currentNode.children.push({ type: "separator"});
+  },
+
+  undoAddSeparator: function() {
+    if (!("children" in this.currentNode)) {
+      return;
+    }
+
+    let children = this.currentNode.children;
+    if (children.length && children[children.length - 1].type == "separator") {
+      children.pop();
+    }
+  },
+
+  closeContainer: function() {
+    this.currentNode = this.nestedStack.length ? this.nestedStack.pop() : this.root;
+  },
+
+  click: function(id) {
+    let item = this.items[id];
+    if (item) {
+      item.click();
+    }
+  }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([HTMLMenuBuilder]);
new file mode 100644
--- /dev/null
+++ b/dom/html/htmlMenuBuilder.manifest
@@ -0,0 +1,3 @@
+component {51c65f5d-0de5-4edc-9058-60e50cef77f8} htmlMenuBuilder.js
+contract @mozilla.org/content/html-menu-builder;1 {51c65f5d-0de5-4edc-9058-60e50cef77f8}
+
--- a/dom/html/moz.build
+++ b/dom/html/moz.build
@@ -210,16 +210,21 @@ UNIFIED_SOURCES += [
     'VideoDocument.cpp',
 ]
 
 SOURCES += [
     # Includes npapi.h.
     'PluginDocument.cpp',
 ]
 
+EXTRA_COMPONENTS += [
+    'htmlMenuBuilder.js',
+    'htmlMenuBuilder.manifest'
+]
+
 FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/caps',
--- a/dom/html/nsIMenuBuilder.idl
+++ b/dom/html/nsIMenuBuilder.idl
@@ -6,17 +6,17 @@
 #include "nsISupports.idl"
 
 interface nsIDOMHTMLMenuItemElement;
 
 /**
  * An interface used to construct native toolbar or context menus from <menu>
  */
 
-[scriptable, uuid(12724737-f7db-43b4-94ab-708a7b86e115)]
+[scriptable, uuid(93F4A48F-D043-4F45-97FD-9771EA1AF976)]
 interface nsIMenuBuilder : nsISupports
 {
 
   /**
    * Create the top level menu or a submenu. The implementation should create
    * a new context for this menu, so all subsequent methods will add new items
    * to this newly created menu.
    */
@@ -44,9 +44,33 @@ interface nsIMenuBuilder : nsISupports
    */
   void undoAddSeparator();
 
   /**
    * Set the context to the parent menu.
    */
   void closeContainer();
 
+  /**
+   * Returns a JSON string representing the menu hierarchy. For a context menu,
+   * it will be of the form:
+   *  {
+   *    type: "menu",
+   *    children: [
+   *      {
+   *        type: "menuitem",
+   *        label: "label",
+   *        icon: "image.png"
+   *      },
+   *      {
+   *        type: "separator",
+   *      },
+   *    ];
+   */
+  AString toJSONString();
+
+  /**
+   * Invoke the action of the menuitem with assigned id aGeneratedItemId.
+   *
+   * @param aGeneratedItemId the menuitem id
+   */
+  void click(in DOMString aGeneratedItemId);
 };
--- a/dom/icc/Assertions.cpp
+++ b/dom/icc/Assertions.cpp
@@ -89,13 +89,25 @@ ASSERT_ICC_LOCK_TYPE_EQUALITY(Fdn, CARD_
   ASSERT_EQUALITY(IccContactType, webidlState, xpidlState)
 
 ASSERT_ICC_CONTACT_TYPE_EQUALITY(Adn, CARD_CONTACT_TYPE_ADN);
 ASSERT_ICC_CONTACT_TYPE_EQUALITY(Fdn, CARD_CONTACT_TYPE_FDN);
 ASSERT_ICC_CONTACT_TYPE_EQUALITY(Sdn, CARD_CONTACT_TYPE_SDN);
 
 #undef ASSERT_ICC_CONTACT_TYPE_EQUALITY
 
+/**
+ * Enum IccMvnoType
+ */
+#define ASSERT_ICC_MVNO_TYPE_EQUALITY(webidlState, xpidlState) \
+  ASSERT_EQUALITY(IccMvnoType, webidlState, xpidlState)
+
+ASSERT_ICC_MVNO_TYPE_EQUALITY(Imsi, CARD_MVNO_TYPE_IMSI);
+ASSERT_ICC_MVNO_TYPE_EQUALITY(Spn, CARD_MVNO_TYPE_SPN);
+ASSERT_ICC_MVNO_TYPE_EQUALITY(Gid, CARD_MVNO_TYPE_GID);
+
+#undef ASSERT_ICC_MVNO_TYPE_EQUALITY
+
 #undef ASSERT_EQUALITY
 
 } // namespace icc
 } // namespace dom
 } // namespace mozilla
--- a/dom/icc/Icc.cpp
+++ b/dom/icc/Icc.cpp
@@ -379,29 +379,28 @@ Icc::UpdateContact(const JSContext* aCx,
     aRv.Throw(rv);
     return nullptr;
   }
 
   return request.forget().downcast<DOMRequest>();
 }
 
 already_AddRefed<DOMRequest>
-Icc::MatchMvno(const nsAString& aMvnoType,
-               const nsAString& aMvnoData,
+Icc::MatchMvno(IccMvnoType aMvnoType, const nsAString& aMvnoData,
                ErrorResult& aRv)
 {
   if (!mProvider) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsRefPtr<nsIDOMDOMRequest> request;
   nsresult rv = mProvider->MatchMvno(mClientId, GetOwner(),
-                                     aMvnoType, aMvnoData,
-                                     getter_AddRefs(request));
+                                     static_cast<uint32_t>(aMvnoType),
+                                     aMvnoData, getter_AddRefs(request));
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
   return request.forget().downcast<DOMRequest>();
 }
 
--- a/dom/icc/Icc.h
+++ b/dom/icc/Icc.h
@@ -93,17 +93,17 @@ public:
   ReadContacts(IccContactType aContactType, ErrorResult& aRv);
 
   already_AddRefed<DOMRequest>
   UpdateContact(const JSContext* aCx, IccContactType aContactType,
                 JS::Handle<JS::Value> aContact, const nsAString& aPin2,
                 ErrorResult& aRv);
 
   already_AddRefed<DOMRequest>
-  MatchMvno(const nsAString& aMvnoType, const nsAString& aMatchData,
+  MatchMvno(IccMvnoType aMvnoType, const nsAString& aMatchData,
             ErrorResult& aRv);
 
   IMPL_EVENT_HANDLER(iccinfochange)
   IMPL_EVENT_HANDLER(cardstatechange)
   IMPL_EVENT_HANDLER(stkcommand)
   IMPL_EVENT_HANDLER(stksessionend)
 
 private:
--- a/dom/icc/interfaces/nsIIccProvider.idl
+++ b/dom/icc/interfaces/nsIIccProvider.idl
@@ -15,17 +15,17 @@ interface nsIIccListener : nsISupports
   void notifyStkSessionEnd();
   void notifyCardStateChanged();
   void notifyIccInfoChanged();
 };
 
 /**
  * XPCOM component (in the content process) that provides the ICC information.
  */
-[scriptable, uuid(937213c3-f64e-4f58-b4e0-3010f219d0c3)]
+[scriptable, uuid(c3e3c1a9-6ac4-4916-a777-7d49ffd89c46)]
 interface nsIIccProvider : nsISupports
 {
   // MUST match enum IccCardState in MozIcc.webidl!
   const unsigned long CARD_STATE_UNKNOWN = 0;
   const unsigned long CARD_STATE_READY = 1;
   const unsigned long CARD_STATE_PIN_REQUIRED = 2;
   const unsigned long CARD_STATE_PUK_REQUIRED = 3;
   const unsigned long CARD_STATE_PERMANENT_BLOCKED = 4;
@@ -80,16 +80,21 @@ interface nsIIccProvider : nsISupports
   const unsigned long CARD_LOCK_TYPE_RSPCK_PUK = 19;
   const unsigned long CARD_LOCK_TYPE_FDN = 20;
 
   // MUST match with enum IccContactType in MozIcc.webidl
   const unsigned long CARD_CONTACT_TYPE_ADN = 0;
   const unsigned long CARD_CONTACT_TYPE_FDN = 1;
   const unsigned long CARD_CONTACT_TYPE_SDN = 2;
 
+  // MUST match with enum IccMvnoType in MozIcc.webidl
+  const unsigned long CARD_MVNO_TYPE_IMSI = 0;
+  const unsigned long CARD_MVNO_TYPE_SPN = 1;
+  const unsigned long CARD_MVNO_TYPE_GID = 2;
+
   /**
    * Called when a content process registers receiving unsolicited messages from
    * RadioInterfaceLayer in the chrome process. Only a content process that has
    * the 'mobileconnection' permission is allowed to register.
    */
   void registerIccMsg(in unsigned long clientId, in nsIIccListener listener);
   void unregisterIccMsg(in unsigned long clientId, in nsIIccListener listener);
 
@@ -177,11 +182,11 @@ interface nsIIccProvider : nsISupports
                                    in nsIDOMWindow window,
                                    in long channel);
 
   /**
    * Helpers
    */
   nsIDOMDOMRequest matchMvno(in unsigned long clientId,
                              in nsIDOMWindow window,
-                             in DOMString mvnoType,
+                             in unsigned long mvnoType,
                              in DOMString mvnoData);
 };
--- a/dom/media/gstreamer/GStreamerReader.cpp
+++ b/dom/media/gstreamer/GStreamerReader.cpp
@@ -65,16 +65,17 @@ typedef enum {
   GST_PLAY_FLAG_SOFT_COLORBALANCE = (1 << 10)
 } PlayFlags;
 
 GStreamerReader::GStreamerReader(AbstractMediaDecoder* aDecoder)
   : MediaDecoderReader(aDecoder),
   mMP3FrameParser(aDecoder->GetResource()->GetLength()),
   mDataOffset(0),
   mUseParserDuration(false),
+  mLastParserDuration(-1),
 #if GST_VERSION_MAJOR >= 1
   mAllocator(nullptr),
   mBufferPool(nullptr),
 #endif
   mPlayBin(nullptr),
   mBus(nullptr),
   mSource(nullptr),
   mVideoSink(nullptr),
--- a/dom/media/omx/MediaCodecReader.cpp
+++ b/dom/media/omx/MediaCodecReader.cpp
@@ -1245,17 +1245,19 @@ MediaCodecReader::CreateMediaSources()
     (videoTrackIndex == invalidTrackIndex || mVideoTrack.mSource != nullptr);
 }
 
 void
 MediaCodecReader::DestroyMediaSources()
 {
   mAudioTrack.mSource = nullptr;
   mVideoTrack.mSource = nullptr;
+#if ANDROID_VERSION >= 21
   mAudioOffloadTrack.mSource = nullptr;
+#endif
 }
 
 void
 MediaCodecReader::ShutdownTaskQueues()
 {
   if(mAudioTrack.mTaskQueue) {
     mAudioTrack.mTaskQueue->BeginShutdown();
     mAudioTrack.mTaskQueue->AwaitShutdownAndIdle();
@@ -1322,17 +1324,25 @@ MediaCodecReader::CreateMediaCodec(sp<AL
     } else {
       aTrack.mInputCopier = new TrackInputCopier;
     }
 
     uint32_t capability = MediaCodecProxy::kEmptyCapability;
     if (aTrack.mType == Track::kVideo &&
         aTrack.mCodec->getCapability(&capability) == OK &&
         (capability & MediaCodecProxy::kCanExposeGraphicBuffer) == MediaCodecProxy::kCanExposeGraphicBuffer) {
+#if ANDROID_VERSION >= 21
+      android::sp<android::IGraphicBufferProducer> producer;
+      android::sp<android::IGonkGraphicBufferConsumer> consumer;
+      GonkBufferQueue::createBufferQueue(&producer, &consumer);
+      aTrack.mNativeWindow = new GonkNativeWindow(consumer);
+      aTrack.mGraphicBufferProducer = producer;
+#else
       aTrack.mNativeWindow = new GonkNativeWindow();
+#endif
     }
 
     if (!aAsync) {
       // Pending configure() and start() to codecReserved() if the creation
       // should be asynchronous.
       if (!aTrack.mCodec->allocated() || !ConfigureMediaCodec(aTrack)){
         NS_WARNING("Couldn't create and configure MediaCodec synchronously");
         DestroyMediaCodec(aTrack);
@@ -1349,17 +1359,21 @@ MediaCodecReader::ConfigureMediaCodec(Tr
 {
   if (aTrack.mSource != nullptr && aTrack.mCodec != nullptr) {
     if (!aTrack.mCodec->allocated()) {
       return false;
     }
 
     sp<Surface> surface;
     if (aTrack.mNativeWindow != nullptr) {
+#if ANDROID_VERSION >= 21
+      surface = new Surface(aTrack.mGraphicBufferProducer);
+#else
       surface = new Surface(aTrack.mNativeWindow->getBufferQueue());
+#endif
     }
 
     sp<MetaData> sourceFormat = aTrack.mSource->getFormat();
     sp<AMessage> codecFormat;
     convertMetaDataToMessage(sourceFormat, &codecFormat);
 
     bool allpass = true;
     if (allpass && aTrack.mCodec->configure(codecFormat, surface, nullptr, 0) != OK) {
@@ -1394,16 +1408,19 @@ MediaCodecReader::DestroyMediaCodecs()
   DestroyMediaCodec(mVideoTrack);
 }
 
 void
 MediaCodecReader::DestroyMediaCodec(Track& aTrack)
 {
   aTrack.mCodec = nullptr;
   aTrack.mNativeWindow = nullptr;
+#if ANDROID_VERSION >= 21
+  aTrack.mGraphicBufferProducer = nullptr;
+#endif
 }
 
 bool
 MediaCodecReader::TriggerIncrementalParser()
 {
   if (mMetaData == nullptr) {
     return false;
   }
--- a/dom/media/omx/MediaCodecReader.h
+++ b/dom/media/omx/MediaCodecReader.h
@@ -134,16 +134,19 @@ protected:
 
     // pipeline parameters
     android::sp<android::MediaSource> mSource;
     bool mSourceIsStopped;
     android::sp<android::MediaCodecProxy> mCodec;
     android::Vector<android::sp<android::ABuffer> > mInputBuffers;
     android::Vector<android::sp<android::ABuffer> > mOutputBuffers;
     android::sp<android::GonkNativeWindow> mNativeWindow;
+#if ANDROID_VERSION >= 21
+    android::sp<android::IGraphicBufferProducer> mGraphicBufferProducer;
+#endif
 
     // pipeline copier
     nsAutoPtr<TrackInputCopier> mInputCopier;
 
     // media parameters
     Mutex mDurationLock; // mDurationUs might be read or updated from multiple
                          // threads.
     int64_t mDurationUs;
--- a/dom/media/omx/MediaOmxReader.cpp
+++ b/dom/media/omx/MediaOmxReader.cpp
@@ -107,17 +107,17 @@ private:
       uint32_t length = std::min<uint64_t>(mLength, UINT32_MAX);
       mOmxReader->NotifyDataArrived(buffer, length,
                                     mOffset);
       buffer  += length;
       mLength -= length;
       mOffset += length;
     }
 
-    if (mOffset < mFullLength) {
+    if (static_cast<uint64_t>(mOffset) < mFullLength) {
       // We cannot read data in the main thread because it
       // might block for too long. Instead we post an IO task
       // to the IO thread if there is more data available.
       XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
           new OmxReaderProcessCachedDataTask(mOmxReader.get(), mOffset));
     }
   }
 
--- a/dom/media/omx/OmxDecoder.cpp
+++ b/dom/media/omx/OmxDecoder.cpp
@@ -249,18 +249,28 @@ bool OmxDecoder::AllocateMediaResources(
   if ((mVideoTrack != nullptr) && (mVideoSource == nullptr)) {
     // OMXClient::connect() always returns OK and abort's fatally if
     // it can't connect.
     OMXClient client;
     DebugOnly<status_t> err = client.connect();
     NS_ASSERTION(err == OK, "Failed to connect to OMX in mediaserver.");
     sp<IOMX> omx = client.interface();
 
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
+    sp<IGraphicBufferProducer> producer;
+    sp<IGonkGraphicBufferConsumer> consumer;
+    GonkBufferQueue::createBufferQueue(&producer, &consumer);
+    mNativeWindow = new GonkNativeWindow(consumer);
+#else
     mNativeWindow = new GonkNativeWindow();
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
+#endif
+
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
+    mNativeWindowClient = new GonkNativeWindowClient(producer);
+#elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
     mNativeWindowClient = new GonkNativeWindowClient(mNativeWindow->getBufferQueue());
 #else
     mNativeWindowClient = new GonkNativeWindowClient(mNativeWindow);
 #endif
 
     // Experience with OMX codecs is that only the HW decoders are
     // worth bothering with, at least on the platforms where this code
     // is currently used, and for formats this code is currently used
--- a/dom/media/webaudio/AudioBufferSourceNode.cpp
+++ b/dom/media/webaudio/AudioBufferSourceNode.cpp
@@ -2,16 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "AudioBufferSourceNode.h"
 #include "mozilla/dom/AudioBufferSourceNodeBinding.h"
 #include "mozilla/dom/AudioParam.h"
+#include "mozilla/FloatingPoint.h"
 #include "nsMathUtils.h"
 #include "AudioNodeEngine.h"
 #include "AudioNodeStream.h"
 #include "AudioDestinationNode.h"
 #include "AudioParamTimeline.h"
 #include <limits>
 
 namespace mozilla {
@@ -105,17 +106,17 @@ public:
     case AudioBufferSourceNode::START:
       MOZ_ASSERT(!mStart, "Another START?");
       mStart =
         mSource->FractionalTicksFromDestinationTime(mDestination, aParam);
       // Round to nearest
       mBeginProcessing = mStart + 0.5;
       break;
     case AudioBufferSourceNode::DOPPLERSHIFT:
-      mDopplerShift = aParam > 0 && aParam == aParam ? aParam : 1.0;
+      mDopplerShift = (aParam <= 0 || mozilla::IsNaN(aParam)) ? 1.0 : aParam;
       break;
     default:
       NS_ERROR("Bad AudioBufferSourceNodeEngine double parameter.");
     };
   }
   virtual void SetInt32Parameter(uint32_t aIndex, int32_t aParam)
   {
     switch (aIndex) {
@@ -410,17 +411,17 @@ public:
   {
     float playbackRate;
 
     if (mPlaybackRateTimeline.HasSimpleValue()) {
       playbackRate = mPlaybackRateTimeline.GetValue();
     } else {
       playbackRate = mPlaybackRateTimeline.GetValueAtTime(mSource->GetCurrentPosition());
     }
-    if (playbackRate <= 0 || playbackRate != playbackRate) {
+    if (playbackRate <= 0 || mozilla::IsNaN(playbackRate)) {
       playbackRate = 1.0f;
     }
 
     int32_t outRate = ComputeFinalOutSampleRate(playbackRate);
     UpdateResampler(outRate, aChannels);
   }
 
   virtual void ProcessBlock(AudioNodeStream* aStream,
--- a/dom/media/webaudio/WebAudioUtils.h
+++ b/dom/media/webaudio/WebAudioUtils.h
@@ -176,17 +176,17 @@ namespace WebAudioUtils {
   {
     using namespace std;
 
     static_assert(mozilla::IsIntegral<IntType>::value == true,
                   "IntType must be an integral type");
     static_assert(mozilla::IsFloatingPoint<FloatType>::value == true,
                   "FloatType must be a floating point type");
 
-    if (f != f) {
+    if (mozilla::IsNaN(f)) {
       // It is the responsibility of the caller to deal with NaN values.
       // If we ever get to this point, we have a serious bug to fix.
       NS_RUNTIMEABORT("We should never see a NaN here");
     }
 
     if (f > FloatType(numeric_limits<IntType>::max())) {
       // If the floating point value is outside of the range of maximum
       // integral value for this type, just clamp to the maximum value.
--- a/dom/media/webrtc/MediaEngineGonkVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineGonkVideoSource.cpp
@@ -686,50 +686,82 @@ MediaEngineGonkVideoSource::RotateImage(
   layers::GrallocImage* videoImage = static_cast<layers::GrallocImage*>(image.get());
   MOZ_ASSERT(mTextureClientAllocator);
   RefPtr<layers::TextureClient> textureClient
     = mTextureClientAllocator->CreateOrRecycleForDrawing(gfx::SurfaceFormat::YUV,
                                                          gfx::IntSize(dstWidth, dstHeight),
                                                          gfx::BackendType::NONE,
                                                          layers::TextureFlags::DEFAULT,
                                                          layers::ALLOC_DISALLOW_BUFFERTEXTURECLIENT);
-  if (!textureClient) {
-    return;
-  }
-  RefPtr<layers::GrallocTextureClientOGL> grallocTextureClient =
-    static_cast<layers::GrallocTextureClientOGL*>(textureClient.get());
+  if (textureClient) {
+    RefPtr<layers::GrallocTextureClientOGL> grallocTextureClient =
+      static_cast<layers::GrallocTextureClientOGL*>(textureClient.get());
 
-  android::sp<android::GraphicBuffer> destBuffer = grallocTextureClient->GetGraphicBuffer();
+    android::sp<android::GraphicBuffer> destBuffer = grallocTextureClient->GetGraphicBuffer();
+
+    void* destMem = nullptr;
+    destBuffer->lock(android::GraphicBuffer::USAGE_SW_WRITE_OFTEN, &destMem);
+    uint8_t* dstPtr = static_cast<uint8_t*>(destMem);
 
-  void* destMem = nullptr;
-  destBuffer->lock(android::GraphicBuffer::USAGE_SW_WRITE_OFTEN, &destMem);
-  uint8_t* dstPtr = static_cast<uint8_t*>(destMem);
+    int32_t yStride = destBuffer->getStride();
+    // Align to 16 bytes boundary
+    int32_t uvStride = ((yStride / 2) + 15) & ~0x0F;
 
-  int32_t yStride = destBuffer->getStride();
-  // Align to 16 bytes boundary
-  int32_t uvStride = ((yStride / 2) + 15) & ~0x0F;
+    libyuv::ConvertToI420(srcPtr, size,
+                          dstPtr, yStride,
+                          dstPtr + (yStride * dstHeight + (uvStride * dstHeight / 2)), uvStride,
+                          dstPtr + (yStride * dstHeight), uvStride,
+                          0, 0,
+                          aWidth, aHeight,
+                          aWidth, aHeight,
+                          static_cast<libyuv::RotationMode>(mRotation),
+                          libyuv::FOURCC_NV21);
+    destBuffer->unlock();
+
+    layers::GrallocImage::GrallocData data;
 
-  libyuv::ConvertToI420(srcPtr, size,
-                        dstPtr, yStride,
-                        dstPtr + (yStride * dstHeight + (uvStride * dstHeight / 2)), uvStride,
-                        dstPtr + (yStride * dstHeight), uvStride,
-                        0, 0,
-                        aWidth, aHeight,
-                        aWidth, aHeight,
-                        static_cast<libyuv::RotationMode>(mRotation),
-                        libyuv::FOURCC_NV21);
-  destBuffer->unlock();
+    data.mPicSize = gfx::IntSize(dstWidth, dstHeight);
+    data.mGraphicBuffer = textureClient;
+    videoImage->SetData(data);
+  } else {
+    // Handle out of gralloc case.
+    image = mImageContainer->CreateImage(ImageFormat::PLANAR_YCBCR);
+    layers::PlanarYCbCrImage* videoImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
+    uint8_t* dstPtr = videoImage->AllocateAndGetNewBuffer(size);
+
+    libyuv::ConvertToI420(srcPtr, size,
+                          dstPtr, dstWidth,
+                          dstPtr + (dstWidth * dstHeight), half_width,
+                          dstPtr + (dstWidth * dstHeight * 5 / 4), half_width,
+                          0, 0,
+                          aWidth, aHeight,
+                          aWidth, aHeight,
+                          static_cast<libyuv::RotationMode>(mRotation),
+                          ConvertPixelFormatToFOURCC(graphicBuffer->getPixelFormat()));
+
+    const uint8_t lumaBpp = 8;
+    const uint8_t chromaBpp = 4;
+
+    layers::PlanarYCbCrData data;
+    data.mYChannel = dstPtr;
+    data.mYSize = IntSize(dstWidth, dstHeight);
+    data.mYStride = dstWidth * lumaBpp / 8;
+    data.mCbCrStride = dstWidth * chromaBpp / 8;
+    data.mCbChannel = dstPtr + dstHeight * data.mYStride;
+    data.mCrChannel = data.mCbChannel + data.mCbCrStride * (dstHeight / 2);
+    data.mCbCrSize = IntSize(dstWidth / 2, dstHeight / 2);
+    data.mPicX = 0;
+    data.mPicY = 0;
+    data.mPicSize = IntSize(dstWidth, dstHeight);
+    data.mStereoMode = StereoMode::MONO;
+
+    videoImage->SetDataNoCopy(data);
+  }
   graphicBuffer->unlock();
 
-  layers::GrallocImage::GrallocData data;
-
-  data.mPicSize = gfx::IntSize(dstWidth, dstHeight);
-  data.mGraphicBuffer = textureClient;
-  videoImage->SetData(data);
-
   // Implicitly releases last preview image.
   mImage = image.forget();
 }
 
 bool
 MediaEngineGonkVideoSource::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) {
   {
     ReentrantMonitorAutoEnter sync(mCallbackMonitor);
@@ -762,33 +794,41 @@ MediaEngineGonkVideoSource::OnNewMediaBu
     ReentrantMonitorAutoEnter sync(mCallbackMonitor);
     if (mState == kStopped) {
       return NS_OK;
     }
   }
 
   MonitorAutoLock enter(mMonitor);
   if (mImage) {
-    GonkCameraImage* cameraImage = static_cast<GonkCameraImage*>(mImage.get());
-
-    cameraImage->SetBuffer(aBuffer);
+    if (mImage->AsGrallocImage()) {
+      // MediaEngineGonkVideoSource expects that GrallocImage is GonkCameraImage.
+      // See Bug 938034.
+      GonkCameraImage* cameraImage = static_cast<GonkCameraImage*>(mImage.get());
+      cameraImage->SetBuffer(aBuffer);
+    } else {
+      LOG(("mImage is non-GrallocImage"));
+    }
 
     uint32_t len = mSources.Length();
     for (uint32_t i = 0; i < len; i++) {
       if (mSources[i]) {
         // Duration is 1 here.
         // Ideally, it should be camera timestamp here and the MSG will have
         // enough sample duration without calling NotifyPull() anymore.
         // Unfortunately, clock in gonk camera looks like is a different one
         // comparing to MSG. As result, it causes time inaccurate. (frames be
         // queued in MSG longer and longer as time going by in device like Frame)
-        AppendToTrack(mSources[i], cameraImage, mTrackID, 1);
+        AppendToTrack(mSources[i], mImage, mTrackID, 1);
       }
     }
-    // Clear MediaBuffer immediately, it prevents MediaBuffer is kept in
-    // MediaStreamGraph thread.
-    cameraImage->ClearBuffer();
+    if (mImage->AsGrallocImage()) {
+      GonkCameraImage* cameraImage = static_cast<GonkCameraImage*>(mImage.get());
+      // Clear MediaBuffer immediately, it prevents MediaBuffer is kept in
+      // MediaStreamGraph thread.
+      cameraImage->ClearBuffer();
+    }
   }
 
   return NS_OK;
 }
 
 } // namespace mozilla
--- a/dom/mobileconnection/MobileConnection.cpp
+++ b/dom/mobileconnection/MobileConnection.cpp
@@ -6,17 +6,16 @@
 
 #include "MobileConnectionCallback.h"
 #include "mozilla/dom/CFStateChangeEvent.h"
 #include "mozilla/dom/DataErrorEvent.h"
 #include "mozilla/dom/MozClirModeEvent.h"
 #include "mozilla/dom/MozEmergencyCbModeEvent.h"
 #include "mozilla/dom/MozOtaStatusEvent.h"
 #include "mozilla/dom/ToJSValue.h"
-#include "mozilla/dom/USSDReceivedEvent.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "nsIDOMDOMRequest.h"
 #include "nsIPermissionManager.h"
 #include "nsIVariant.h"
 #include "nsJSON.h"
 #include "nsJSUtils.h"
 #include "nsServiceManagerUtils.h"
@@ -588,58 +587,16 @@ MobileConnection::GetVoicePrivacyMode(Er
     aRv.Throw(rv);
     return nullptr;
   }
 
   return request.forget();
 }
 
 already_AddRefed<DOMRequest>
-MobileConnection::SendMMI(const nsAString& aMMIString, ErrorResult& aRv)
-{
-  if (!mMobileConnection) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return nullptr;
-  }
-
-  nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
-  nsRefPtr<MobileConnectionCallback> requestCallback =
-    new MobileConnectionCallback(GetOwner(), request);
-
-  nsresult rv = mMobileConnection->SendMMI(aMMIString, requestCallback);
-  if (NS_FAILED(rv)) {
-    aRv.Throw(rv);
-    return nullptr;
-  }
-
-  return request.forget();
-}
-
-already_AddRefed<DOMRequest>
-MobileConnection::CancelMMI(ErrorResult& aRv)
-{
-  if (!mMobileConnection) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return nullptr;
-  }
-
-  nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
-  nsRefPtr<MobileConnectionCallback> requestCallback =
-    new MobileConnectionCallback(GetOwner(), request);
-
-  nsresult rv = mMobileConnection->CancelMMI(requestCallback);
-  if (NS_FAILED(rv)) {
-    aRv.Throw(rv);
-    return nullptr;
-  }
-
-  return request.forget();
-}
-
-already_AddRefed<DOMRequest>
 MobileConnection::GetCallForwardingOption(uint16_t aReason, ErrorResult& aRv)
 {
   if (!mMobileConnection) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
@@ -986,36 +943,16 @@ MobileConnection::NotifyDataChanged()
   }
 
   UpdateData();
 
   return DispatchTrustedEvent(NS_LITERAL_STRING("datachange"));
 }
 
 NS_IMETHODIMP
-MobileConnection::NotifyUssdReceived(const nsAString& aMessage,
-                                     bool aSessionEnded)
-{
-  if (!CheckPermission("mobileconnection")) {
-    return NS_OK;
-  }
-
-  USSDReceivedEventInit init;
-  init.mBubbles = false;
-  init.mCancelable = false;
-  init.mMessage = aMessage;
-  init.mSessionEnded = aSessionEnded;
-
-  nsRefPtr<USSDReceivedEvent> event =
-    USSDReceivedEvent::Constructor(this, NS_LITERAL_STRING("ussdreceived"), init);
-
-  return DispatchTrustedEvent(event);
-}
-
-NS_IMETHODIMP
 MobileConnection::NotifyDataError(const nsAString& aMessage)
 {
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   DataErrorEventInit init;
   init.mBubbles = false;
--- a/dom/mobileconnection/MobileConnection.h
+++ b/dom/mobileconnection/MobileConnection.h
@@ -103,22 +103,16 @@ public:
 
   already_AddRefed<DOMRequest>
   SetVoicePrivacyMode(bool aEnabled, ErrorResult& aRv);
 
   already_AddRefed<DOMRequest>
   GetVoicePrivacyMode(ErrorResult& aRv);
 
   already_AddRefed<DOMRequest>
-  SendMMI(const nsAString& aMmi, ErrorResult& aRv);
-
-  already_AddRefed<DOMRequest>
-  CancelMMI(ErrorResult& aRv);
-
-  already_AddRefed<DOMRequest>
   SetCallForwardingOption(const MozCallForwardingOptions& aOptions,
                           ErrorResult& aRv);
 
   already_AddRefed<DOMRequest>
   GetCallForwardingOption(uint16_t aReason, ErrorResult& aRv);
 
   already_AddRefed<DOMRequest>
   SetCallBarringOption(const MozCallBarringOptions& aOptions, ErrorResult& aRv);
@@ -145,17 +139,16 @@ public:
   already_AddRefed<DOMRequest>
   ExitEmergencyCbMode(ErrorResult& aRv);
 
   already_AddRefed<DOMRequest>
   SetRadioEnabled(bool aEnabled, ErrorResult& aRv);
 
   IMPL_EVENT_HANDLER(voicechange)
   IMPL_EVENT_HANDLER(datachange)
-  IMPL_EVENT_HANDLER(ussdreceived)
   IMPL_EVENT_HANDLER(dataerror)
   IMPL_EVENT_HANDLER(cfstatechange)
   IMPL_EVENT_HANDLER(emergencycbmodechange)
   IMPL_EVENT_HANDLER(otastatuschange)
   IMPL_EVENT_HANDLER(iccchange)
   IMPL_EVENT_HANDLER(radiostatechange)
   IMPL_EVENT_HANDLER(clirmodechange)
 
--- a/dom/mobileconnection/MobileConnectionCallback.cpp
+++ b/dom/mobileconnection/MobileConnectionCallback.cpp
@@ -1,15 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MobileConnectionCallback.h"
 
-#include "mozilla/dom/DOMMMIError.h"
 #include "mozilla/dom/MobileNetworkInfo.h"
 #include "mozilla/dom/MozMobileConnectionBinding.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "nsJSUtils.h"
 #include "nsServiceManagerUtils.h"
 
 namespace mozilla {
 namespace dom {
@@ -27,38 +26,16 @@ NS_IMPL_ISUPPORTS(MobileConnectionCallba
 MobileConnectionCallback::MobileConnectionCallback(nsPIDOMWindow* aWindow,
                                                    DOMRequest* aRequest)
   : mWindow(aWindow)
   , mRequest(aRequest)
 {
 }
 
 /**
- * Notify Success for Send/CancelMmi.
- */
-nsresult
-MobileConnectionCallback::NotifySendCancelMmiSuccess(const MozMMIResult& aResult)
-{
-  AutoJSAPI jsapi;
-  if (NS_WARN_IF(!jsapi.Init(mWindow))) {
-    return NS_ERROR_FAILURE;
-  }
-
-  JSContext* cx = jsapi.cx();
-  JS::Rooted<JS::Value> jsResult(cx);
-
-  if (!ToJSValue(cx, aResult, &jsResult)) {
-    JS_ClearPendingException(cx);
-    return NS_ERROR_TYPE_ERR;
-  }
-
-  return NotifySuccess(jsResult);
-}
-
-/**
  * Notify Success.
  */
 nsresult
 MobileConnectionCallback::NotifySuccess(JS::Handle<JS::Value> aResult)
 {
   nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
 
@@ -125,141 +102,16 @@ MobileConnectionCallback::NotifyGetNetwo
   if (!ToJSValue(cx, results, &jsResult)) {
     JS_ClearPendingException(cx);
     return NS_ERROR_TYPE_ERR;
   }
 
   return NotifySuccess(jsResult);
 }
 
-nsresult
-MobileConnectionCallback::NotifySendCancelMmiSuccess(const nsAString& aServiceCode,
-                                                     const nsAString& aStatusMessage)
-{
-  MozMMIResult result;
-  result.mServiceCode.Assign(aServiceCode);
-  result.mStatusMessage.Assign(aStatusMessage);
-
-  return NotifySendCancelMmiSuccess(result);
-}
-
-nsresult
-MobileConnectionCallback::NotifySendCancelMmiSuccessWithInteger(const nsAString& aServiceCode,
-                                                                const nsAString& aStatusMessage,
-                                                                uint16_t aAdditionalInformation)
-{
-  MozMMIResult result;
-  result.mServiceCode.Assign(aServiceCode);
-  result.mStatusMessage.Assign(aStatusMessage);
-  result.mAdditionalInformation.Construct().SetAsUnsignedShort() = aAdditionalInformation;
-
-  return NotifySendCancelMmiSuccess(result);
-}
-
-nsresult
-MobileConnectionCallback::NotifySendCancelMmiSuccessWithStrings(const nsAString& aServiceCode,
-                                                                const nsAString& aStatusMessage,
-                                                                uint32_t aCount,
-                                                                const char16_t** aAdditionalInformation)
-{
-  AutoJSAPI jsapi;
-  if (NS_WARN_IF(!jsapi.Init(mWindow))) {
-    return NS_ERROR_FAILURE;
-  }
-
-  JSContext* cx = jsapi.cx();
-  RootedDictionary<MozMMIResult> result(cx);
-
-  result.mServiceCode.Assign(aServiceCode);
-  result.mStatusMessage.Assign(aStatusMessage);
-
-  nsTArray<nsString> additionalInformation;
-  for (uint32_t i = 0; i < aCount; i++) {
-    additionalInformation.AppendElement(nsDependentString(aAdditionalInformation[i]));
-  }
-
-  JS::Rooted<JS::Value> jsAdditionalInformation(cx);
-  if (!ToJSValue(cx, additionalInformation, &jsAdditionalInformation)) {
-    JS_ClearPendingException(cx);
-    return NS_ERROR_TYPE_ERR;
-  }
-
-  result.mAdditionalInformation.Construct().SetAsObject() =
-    &jsAdditionalInformation.toObject();
-
-  return NotifySendCancelMmiSuccess(result);
-}
-
-nsresult
-MobileConnectionCallback::NotifySendCancelMmiSuccessWithCallForwardingOptions(
-                                                                const nsAString& aServiceCode,
-                                                                const nsAString& aStatusMessage,
-                                                                uint32_t aCount,
-                                                                nsIMobileCallForwardingOptions** aResults)
-{
-  AutoJSAPI jsapi;
-  if (NS_WARN_IF(!jsapi.Init(mWindow))) {
-    return NS_ERROR_FAILURE;
-  }
-
-  JSContext* cx = jsapi.cx();
-  RootedDictionary<MozMMIResult> result(cx);
-
-  result.mServiceCode.Assign(aServiceCode);
-  result.mStatusMessage.Assign(aStatusMessage);
-
-  nsTArray<MozCallForwardingOptions> additionalInformation;
-  for (uint32_t i = 0; i < aCount; i++)
-  {
-    MozCallForwardingOptions options;
-    int16_t pShort;
-    nsString pString;
-    bool pBool;
-
-    aResults[i]->GetActive(&pBool);
-    options.mActive.Construct(pBool);
-
-    aResults[i]->GetAction(&pShort);
-    if (pShort != nsIMobileConnection::CALL_FORWARD_ACTION_UNKNOWN) {
-      options.mAction.Construct(pShort);
-    }
-
-    aResults[i]->GetReason(&pShort);
-    if (pShort != nsIMobileConnection::CALL_FORWARD_REASON_UNKNOWN) {
-      options.mReason.Construct(pShort);
-    }
-
-    aResults[i]->GetNumber(pString);
-    options.mNumber.Construct(pString.get());
-
-    aResults[i]->GetTimeSeconds(&pShort);
-    if (pShort >= 0) {
-      options.mTimeSeconds.Construct(pShort);
-    }
-
-    aResults[i]->GetServiceClass(&pShort);
-    if (pShort != nsIMobileConnection::ICC_SERVICE_CLASS_NONE) {
-      options.mServiceClass.Construct(pShort);
-    }
-
-    additionalInformation.AppendElement(options);
-  }
-
-  JS::Rooted<JS::Value> jsAdditionalInformation(cx);
-  if (!ToJSValue(cx, additionalInformation, &jsAdditionalInformation)) {
-    JS_ClearPendingException(cx);
-    return NS_ERROR_TYPE_ERR;
-  }
-
-  result.mAdditionalInformation.Construct().SetAsObject() =
-    &jsAdditionalInformation.toObject();
-
-  return NotifySendCancelMmiSuccess(result);
-}
-
 NS_IMETHODIMP
 MobileConnectionCallback::NotifyGetCallForwardingSuccess(uint32_t aCount,
                                                          nsIMobileCallForwardingOptions** aResults)
 {
   nsTArray<MozCallForwardingOptions> results;
   for (uint32_t i = 0; i < aCount; i++)
   {
     MozCallForwardingOptions result;
@@ -379,41 +231,18 @@ MobileConnectionCallback::NotifyGetRoami
 
   nsAutoString modeString;
   CONVERT_ENUM_TO_STRING(MobileRoamingMode, mode, modeString);
 
   return NotifySuccessWithString(modeString);
 };
 
 NS_IMETHODIMP
-MobileConnectionCallback::NotifyError(const nsAString& aName,
-                                      const nsAString& aMessage,
-                                      const nsAString& aServiceCode,
-                                      uint16_t aInfo,
-                                      uint8_t aArgc)
+MobileConnectionCallback::NotifyError(const nsAString& aName)
 {
   nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
-
-  nsRefPtr<DOMError> error;
-  switch (aArgc) {
-    case 0:
-      return rs->FireErrorAsync(mRequest, aName);
-    case 1:
-      error = new DOMMMIError(mWindow, aName, aMessage, EmptyString(),
-                              Nullable<int16_t>());
-      return rs->FireDetailedError(mRequest, error);
-    case 2:
-      error = new DOMMMIError(mWindow, aName, aMessage, aServiceCode,
-                              Nullable<int16_t>());
-      return rs->FireDetailedError(mRequest, error);
-    case 3:
-      error = new DOMMMIError(mWindow, aName, aMessage, aServiceCode,
-                              Nullable<int16_t>(int16_t(aInfo)));
-      return rs->FireDetailedError(mRequest, error);
-  }
-
-  return NS_ERROR_FAILURE;
+  return rs->FireErrorAsync(mRequest, aName);
 }
 
 } // namespace mobileconnection
 } // namespace dom
 } // namespace mozilla
--- a/dom/mobileconnection/MobileConnectionCallback.h
+++ b/dom/mobileconnection/MobileConnectionCallback.h
@@ -36,19 +36,16 @@ private:
   ~MobileConnectionCallback() {}
 
   nsresult
   NotifySuccess(JS::Handle<JS::Value> aResult);
 
   nsresult
   NotifySuccessWithString(const nsAString& aResult);
 
-  nsresult
-  NotifySendCancelMmiSuccess(const MozMMIResult& aResult);
-
   nsCOMPtr<nsPIDOMWindow> mWindow;
   nsRefPtr<DOMRequest> mRequest;
 };
 
 } // namespace mobileconnection
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/mobileconnection/gonk/MobileConnectionService.js
+++ b/dom/mobileconnection/gonk/MobileConnectionService.js
@@ -22,18 +22,16 @@ const GONK_MOBILECONNECTIONSERVICE_CID =
 const MOBILECONNECTIONINFO_CID =
   Components.ID("{8162b3c0-664b-45f6-96cd-f07b4e193b0e}");
 const MOBILENETWORKINFO_CID =
   Components.ID("{a6c8416c-09b4-46d1-bf29-6520d677d085}");
 const MOBILECELLINFO_CID =
   Components.ID("{0635d9ab-997e-4cdf-84e7-c1883752dff3}");
 const MOBILECALLFORWARDINGOPTIONS_CID =
   Components.ID("{e0cf4463-ee63-4b05-ab2e-d94bf764836c}");
-const TELEPHONYDIALCALLBACK_CID =
-  Components.ID("{c2af1a5d-3649-44ef-a1ff-18e9ac1dec51}");
 const NEIGHBORINGCELLINFO_CID =
   Components.ID("{6078cbf1-f34c-44fa-96f8-11a88d4bfdd3}");
 const GSMCELLINFO_CID =
   Components.ID("{e3cf3aa0-f992-48fe-967b-ec98a28c8535}");
 const WCDMACELLINFO_CID =
   Components.ID("{62e2c83c-b535-4068-9762-8039fac48106}");
 const CDMACELLINFO_CID =
   Components.ID("{40f491f0-dd8b-42fd-af32-aef5b002749a}");
@@ -275,72 +273,16 @@ CdmaCellInfo.prototype = {
   latitude: INT32_MAX,
   cdmaDbm: INT32_MAX,
   cdmaEcio: INT32_MAX,
   evdoDbm: INT32_MAX,
   evdoEcio: INT32_MAX,
   evdoSnr: INT32_MAX
 };
 
-/**
- * Wrap a MobileConnectionCallback to a TelephonyDialCallback.
- */
-function TelephonyDialCallback(aCallback) {
-  this.callback = aCallback;
-}
-TelephonyDialCallback.prototype = {
-  QueryInterface:   XPCOMUtils.generateQI([Ci.nsITelephonyDialCallback]),
-  classID:          TELEPHONYDIALCALLBACK_CID,
-
-  notifyDialMMI: function(mmiServiceCode) {
-    this.serviceCode = mmiServiceCode;
-  },
-
-  notifyDialMMISuccess: function(statusMessage) {
-    this.callback.notifySendCancelMmiSuccess(this.serviceCode, statusMessage);
-  },
-
-  notifyDialMMISuccessWithInteger: function(statusMessage, additionalInfo) {
-    this.callback.notifySendCancelMmiSuccessWithInteger(this.serviceCode,
-                                                        statusMessage,
-                                                        additionalInfo);
-  },
-
-  notifyDialMMISuccessWithStrings: function(statusMessage, count, additionalInfo) {
-    this.callback.notifySendCancelMmiSuccessWithStrings(this.serviceCode,
-                                                        statusMessage,
-                                                        count,
-                                                        additionalInfo);
-  },
-
-  notifyDialMMISuccessWithCallForwardingOptions: function(statusMessage, count, additionalInfo) {
-    this.callback.notifySendCancelMmiSuccessWithCallForwardingOptions(
-                                                        this.serviceCode,
-                                                        statusMessage,
-                                                        count,
-                                                        additionalInfo);
-  },
-
-  notifyDialMMIError: function(error) {
-    this.callback.notifyError(error, "", this.serviceCode);
-  },
-
-  notifyDialMMIErrorWithInfo: function(error, info) {
-    this.callback.notifyError(error, "", this.serviceCode, info);
-  },
-
-  notifyDialError: function() {
-    throw Cr.NS_ERROR_UNEXPECTED;
-  },
-
-  notifyDialSuccess: function() {
-    throw Cr.NS_ERROR_UNEXPECTED;
-  },
-};
-
 function MobileConnectionProvider(aClientId, aRadioInterface) {
   this._clientId = aClientId;
   this._radioInterface = aRadioInterface;
   this._operatorInfo = new MobileNetworkInfo();
   // An array of nsIMobileConnectionListener instances.
   this._listeners = [];
 
   this.supportedNetworkTypes = this._getSupportedNetworkTypes();
@@ -828,34 +770,16 @@ MobileConnectionProvider.prototype = {
         return false;
       }
 
       aCallback.notifySuccessWithBoolean(aResponse.enabled);
       return false;
     }).bind(this));
   },
 
-  sendMMI: function(aMmi, aCallback) {
-    let callback = new TelephonyDialCallback(aCallback);
-    gGonkTelephonyService.dialMMI(this._clientId, aMmi, callback);
-  },
-
-  cancelMMI: function(aCallback) {
-    this._radioInterface.sendWorkerMessage("cancelUSSD", null,
-                                           (function(aResponse) {
-      if (aResponse.errorMsg) {
-        aCallback.notifyError(aResponse.errorMsg);
-        return false;
-      }
-
-      aCallback.notifySuccess();
-      return false;
-    }).bind(this));
-  },
-
   setCallForwarding: function(aAction, aReason, aNumber, aTimeSeconds,
                               aServiceClass, aCallback) {
     let options = {
       action: aAction,
       reason: aReason,
       number: aNumber,
       timeSeconds: aTimeSeconds,
       serviceClass: RIL.ICC_SERVICE_CLASS_VOICE
@@ -1185,28 +1109,16 @@ MobileConnectionService.prototype = {
     if (DEBUG) {
       debug("notifyDataInfoChanged for " + aClientId + ": " +
             JSON.stringify(aDataInfo));
     }
 
     this.getItemByServiceId(aClientId).updateDataInfo(aDataInfo);
   },
 
-  notifyUssdReceived: function(aClientId, aMessage, aSessionEnded) {
-    if (DEBUG) {
-      debug("notifyUssdReceived for " + aClientId + ": " +
-            aMessage + " (sessionEnded : " + aSessionEnded + ")");
-    }
-
-    gMobileConnectionMessenger.notifyUssdReceived(aClientId, aMessage, aSessionEnded);
-
-    this.getItemByServiceId(aClientId)
-        .deliverListenerEvent("notifyUssdReceived", [aMessage, aSessionEnded]);
-  },
-
   notifyDataError: function(aClientId, aMessage) {
     if (DEBUG) {
       debug("notifyDataError for " + aClientId + ": " + aMessage);
     }
 
     this.getItemByServiceId(aClientId)
         .deliverListenerEvent("notifyDataError", [aMessage]);
   },
--- a/dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl
+++ b/dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl
@@ -4,17 +4,17 @@
 
 #include "nsIMobileConnectionService.idl"
 
 %{C++
 #define GONK_MOBILECONNECTION_SERVICE_CONTRACTID \
         "@mozilla.org/mobileconnection/gonkmobileconnectionservice;1"
 %}
 
-[scriptable, uuid(eae40ffe-394a-4355-8e0b-07170d3e70f4)]
+[scriptable, uuid(ef49b866-85a0-11e4-b023-f73e02752840)]
 interface nsIGonkMobileConnectionService : nsIMobileConnectionService
 {
   void notifyNetworkInfoChanged(in unsigned long clientId, in jsval networkInfo);
 
   void notifyVoiceInfoChanged(in unsigned long clientId, in jsval voiceInfo);
 
   void notifyDataInfoChanged(in unsigned long clientId, in jsval dataInfo);
 
@@ -24,20 +24,16 @@ interface nsIGonkMobileConnectionService
 
   void notifyOperatorChanged(in unsigned long clientId, in jsval info);
 
   void notifyOtaStatusChanged(in unsigned long clientId, in DOMString status);
 
   void notifyRadioStateChanged(in unsigned long clientId,
                                in long radioState);
 
-  void notifyUssdReceived(in unsigned long clientId,
-                          in DOMString message,
-                          in boolean sessionEnded);
-
   void notifyEmergencyCallbackModeChanged(in unsigned long clientId,
                                           in boolean active,
                                           in unsigned long timeoutMs);
 
   void notifyIccChanged(in unsigned long clientId, in DOMString iccId);
 
   void notifyNetworkSelectModeChanged(in unsigned long clientId,
                                       in long mode);
--- a/dom/mobileconnection/gonk/nsIMobileConnectionMessenger.idl
+++ b/dom/mobileconnection/gonk/nsIMobileConnectionMessenger.idl
@@ -1,32 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-[scriptable, uuid(fd2fa95c-5b54-11e4-bc6b-6f3bffb681cd)]
+[scriptable, uuid(b9ec941e-8504-11e4-810e-7b62c60e8261)]
 interface nsIMobileConnectionMessenger : nsISupports
 {
   /**
-   * 'ussd-received' system message
-   *
-   * @param aServiceId
-   *        The ID of Service where this info is notified from.
-   * @param aMessage
-   *        USSD Message to be displayed.
-   * @param aSessionEnded
-   *        True if USSD session is ended.
-   */
-  void notifyUssdReceived(in unsigned long aServiceId,
-                          in DOMString aMessage,
-                          in boolean aSessionEnded);
-
-  /**
    * 'cdma-info-rec-received' system message with Display Info
    *
    * @param aServiceId
    *        The ID of Service where this info is notified from.
    * @param aDisplay
    *        The text to be displayed.
    */
   void notifyCdmaInfoRecDisplay(in unsigned long aServiceId,
--- a/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl
+++ b/dom/mobileconnection/interfaces/nsIMobileConnectionService.idl
@@ -7,41 +7,30 @@
 interface nsICellInfoListCallback;
 interface nsIMobileCallForwardingOptions;
 interface nsIMobileConnection;
 interface nsIMobileConnectionInfo;
 interface nsIMobileNetworkInfo;
 interface nsINeighboringCellIdsCallback;
 interface nsIVariant;
 
-[scriptable, uuid(c00abd30-5b2e-11e4-8ed6-0800200c9a66)]
+[scriptable, uuid(6e6468a4-84fb-11e4-9b66-17dbe13c059e)]
 interface nsIMobileConnectionListener : nsISupports
 {
   /**
    * Notify when voice info is changed.
    */
   void notifyVoiceChanged();
 
   /**
    * Notify when data info is changed.
    */
   void notifyDataChanged();
 
   /**
-   * Notify when ussd is received.
-   *
-   * @param message
-   *        The ussd request in string format.
-   * @param sessionEnded
-   *        Indicates whether the session is ended.
-   */
-  void notifyUssdReceived(in DOMString message,
-                          in boolean sessionEnded);
-
-  /**
    * Notify when data call is failed to establish.
    *
    * @param message
    *        Error message from RIL.
    */
   void notifyDataError(in DOMString message);
 
   /**
@@ -119,102 +108,46 @@ interface nsIMobileConnectionListener : 
    */
   void notifyNetworkSelectionModeChanged();
 };
 
 %{C++
 #define NO_ADDITIONAL_INFORMATION 0
 %}
 
-[scriptable, builtinclass, uuid(16e77f19-0298-46de-ae49-9b2fb92a28c0)]
+[scriptable, builtinclass, uuid(14d66926-8434-11e4-8c3f-f724194bb5f1)]
 interface nsIMobileConnectionCallback : nsISupports
 {
   /**
    * notify*Success*() will be called, when request is succeed.
    */
   void notifySuccess();
 
   void notifySuccessWithBoolean(in boolean result);
 
   void notifyGetNetworksSuccess(in uint32_t count,
                                 [array, size_is(count)] in nsIMobileNetworkInfo networks);
 
-  void notifySendCancelMmiSuccess(in DOMString aServiceCode,
-                                  in DOMString aStatusMessage);
-
-  void notifySendCancelMmiSuccessWithInteger(in DOMString aServiceCode,
-                                             in DOMString aStatusMessage,
-                                             in unsigned short aAdditionalInformation);
-
-  void notifySendCancelMmiSuccessWithStrings(in DOMString aServiceCode,
-                                             in DOMString aStatusMessage,
-                                             in unsigned long aLength,
-                                             [array, size_is(aLength)] in wstring aAdditionalInformation);
-
-  void notifySendCancelMmiSuccessWithCallForwardingOptions(in DOMString aServiceCode,
-                                                           in DOMString aStatusMessage,
-                                                           in unsigned long aLength,
-                                                           [array, size_is(aLength)] in nsIMobileCallForwardingOptions aAdditionalInformation);
-
   void notifyGetCallForwardingSuccess(in uint32_t count,
                                       [array, size_is(count)] in nsIMobileCallForwardingOptions results);
 
-
   void notifyGetCallBarringSuccess(in unsigned short program,
                                    in boolean enabled,
                                    in unsigned short serviceClass);
 
   void notifyGetClirStatusSuccess(in unsigned short n, in unsigned short m);
 
   void notifyGetPreferredNetworkTypeSuccess(in long type);
 
   void notifyGetRoamingPreferenceSuccess(in long mode);
 
   /**
    * notifyError() will be called, when request is failed.
    */
-  [optional_argc]
-  void notifyError(in DOMString name,
-                   [optional] in DOMString message,
-                   [optional] in DOMString serviceCode,
-                   [optional] in unsigned short additionalInformation);
-
-%{C++
-  // non-virtual so it won't affect the vtable
-  inline nsresult NotifyError(const nsAString& aName)
-  {
-    return NotifyError(aName, EmptyString(), EmptyString(),
-                       NO_ADDITIONAL_INFORMATION, 0 /* ARGC = 0 */);
-  }
-  // non-virtual so it won't affect the vtable
-  inline nsresult NotifyError(const nsAString& aName,
-                              const nsAString& aMessage)
-  {
-    return NotifyError(aName, aMessage, EmptyString(), NO_ADDITIONAL_INFORMATION,
-                       1 /* ARGC = 1 */);
-  }
-  // non-virtual so it won't affect the vtable
-  inline nsresult NotifyError(const nsAString& aName,
-                              const nsAString& aMessage,
-                              const nsAString& aServiceCode)
-  {
-    return NotifyError(aName, aMessage, aServiceCode, NO_ADDITIONAL_INFORMATION,
-                       2 /* ARGC = 2 */);
-  }
-  // non-virtual so it won't affect the vtable
-  inline nsresult NotifyError(const nsAString& aName,
-                              const nsAString& aMessage,
-                              const nsAString& aServiceCode,
-                              uint16_t aAdditionInformation)
-  {
-    return NotifyError(aName, aMessage, aServiceCode, aAdditionInformation,
-                       3 /* ARGC = 3 */);
-  }
-%}
-
+  void notifyError(in DOMString name);
 };
 
 %{C++
 #define NS_MOBILE_CONNECTION_SERVICE_CID \
   { 0xc6f229d4, 0x16e2, 0x4600, \
     { 0x87, 0x2a, 0x3d, 0x3d, 0xc5, 0xb8, 0x55, 0x41 } }
 #define NS_MOBILE_CONNECTION_SERVICE_CONTRACTID \
   "@mozilla.org/mobileconnection/mobileconnectionservice;1"
@@ -230,17 +163,17 @@ interface nsIMobileConnectionService : n
 
 %{C++
 template<typename T> struct already_AddRefed;
 
 already_AddRefed<nsIMobileConnectionService>
 NS_CreateMobileConnectionService();
 %}
 
-[scriptable, uuid(99e43353-5fc4-497e-88a2-5fa6862ee64c)]
+[scriptable, uuid(2b3d0122-8054-11e4-964e-c727f38fd7e6)]
 interface nsIMobileConnection : nsISupports
 {
   /*
    * ICC service class.
    */
   const long ICC_SERVICE_CLASS_NONE       = 0; // not available
   const long ICC_SERVICE_CLASS_VOICE      = (1 << 0);
   const long ICC_SERVICE_CLASS_DATA       = (1 << 1);
@@ -545,46 +478,16 @@ interface nsIMobileConnection : nsISuppo
    *
    * Otherwise, the notifyError() will be called, and the error will be either
    * 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or
    * 'GenericFailure'.
    */
   void getVoicePrivacyMode(in nsIMobileConnectionCallback requestCallback);
 
   /**
-   * Send a MMI message.
-   *
-   * @param mmi
-   *        DOMString containing an MMI string that can be associated to a
-   *        USSD request or other RIL functionality.
-   * @param requestCallback
-   *        Called when request is finished.
-   *
-   * If successful, the notifySendCancelMmiSuccess*() will be called. And the
-   * result will contain the information about the mmi operation.
-   *
-   * Otherwise, the notifyError() will be called.
-   */
-  void sendMMI(in DOMString mmi,
-               in nsIMobileConnectionCallback requestCallback);
-
-  /**
-   * Cancel the current MMI request if one exists.
-   *
-   * @param requestCallback
-   *        Called when request is finished.
-   *
-   * If successful, the notifySendCancelMmiSuccess*() will be called. And the
-   * result will contain the information about the mmi operation.
-   *
-   * Otherwise, the notifyError() will be called.
-   */
-  void cancelMMI(in nsIMobileConnectionCallback requestCallback);
-
-  /**
    * Queries current call forwarding options.
    *
    * @param reason
    *        Indicates the reason the call is being forwarded. It shall be one of
    *        the nsIMobileConnectionService.CALL_FORWARD_REASON_* values.
    * @param requestCallback
    *        Called when request is finished.
    *
--- a/dom/mobileconnection/ipc/MobileConnectionChild.cpp
+++ b/dom/mobileconnection/ipc/MobileConnectionChild.cpp
@@ -218,30 +218,16 @@ MobileConnectionChild::SetVoicePrivacyMo
 NS_IMETHODIMP
 MobileConnectionChild::GetVoicePrivacyMode(nsIMobileConnectionCallback* aCallback)
 {
   return SendRequest(GetVoicePrivacyModeRequest(), aCallback)
     ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-MobileConnectionChild::SendMMI(const nsAString& aMmi,
-                               nsIMobileConnectionCallback* aCallback)
-{
-  return SendRequest(SendMmiRequest(nsAutoString(aMmi)), aCallback)
-    ? NS_OK : NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-MobileConnectionChild::CancelMMI(nsIMobileConnectionCallback* aCallback)
-{
-  return SendRequest(CancelMmiRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
 MobileConnectionChild::SetCallForwarding(uint16_t aAction, uint16_t aReason,
                                          const nsAString& aNumber,
                                          uint16_t aTimeSeconds, uint16_t aServiceClass,
                                          nsIMobileConnectionCallback* aCallback)
 {
   return SendRequest(SetCallForwardingRequest(aAction, aReason,
                                               nsString(aNumber),
                                               aTimeSeconds, aServiceClass),
@@ -411,27 +397,16 @@ MobileConnectionChild::RecvNotifyDataInf
   for (int32_t i = 0; i < mListeners.Count(); i++) {
     mListeners[i]->NotifyDataChanged();
   }
 
   return true;
 }
 
 bool
-MobileConnectionChild::RecvNotifyUssdReceived(const nsString& aMessage,
-                                              const bool& aSessionEnd)
-{
-  for (int32_t i = 0; i < mListeners.Count(); i++) {
-    mListeners[i]->NotifyUssdReceived(aMessage, aSessionEnd);
-  }
-
-  return true;
-}
-
-bool
 MobileConnectionChild::RecvNotifyDataError(const nsString& aMessage)
 {
   for (int32_t i = 0; i < mListeners.Count(); i++) {
     mListeners[i]->NotifyDataError(aMessage);
   }
 
   return true;
 }
@@ -564,70 +539,16 @@ MobileConnectionRequestChild::DoReply(co
     results.AppendElement(item);
   }
 
   return NS_SUCCEEDED(mRequestCallback->NotifyGetNetworksSuccess(count,
                                                                  const_cast<nsIMobileNetworkInfo**>(aReply.results().Elements())));
 }
 
 bool
-MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessMmi& aReply)
-{
-  nsAutoString serviceCode(aReply.serviceCode());
-  nsAutoString statusMessage(aReply.statusMessage());
-  AdditionalInformation info(aReply.additionalInformation());
-
-  // Handle union types
-  switch (info.type()) {
-    case AdditionalInformation::Tvoid_t:
-      return NS_SUCCEEDED(mRequestCallback->NotifySendCancelMmiSuccess(serviceCode,
-                                                                       statusMessage));
-
-    case AdditionalInformation::Tuint16_t:
-      return NS_SUCCEEDED(mRequestCallback->NotifySendCancelMmiSuccessWithInteger(
-        serviceCode, statusMessage, info.get_uint16_t()));
-
-    case AdditionalInformation::TArrayOfnsString: {
-      uint32_t count = info.get_ArrayOfnsString().Length();
-      const nsTArray<nsString>& additionalInformation = info.get_ArrayOfnsString();
-
-      nsAutoArrayPtr<const char16_t*> additionalInfoPtrs(new const char16_t*[count]);
-      for (size_t i = 0; i < count; ++i) {
-        additionalInfoPtrs[i] = additionalInformation[i].get();
-      }
-
-      return NS_SUCCEEDED(mRequestCallback->NotifySendCancelMmiSuccessWithStrings(
-        serviceCode, statusMessage, count, additionalInfoPtrs));
-    }
-
-    case AdditionalInformation::TArrayOfnsMobileCallForwardingOptions: {
-      uint32_t count = info.get_ArrayOfnsMobileCallForwardingOptions().Length();
-
-      nsTArray<nsCOMPtr<nsIMobileCallForwardingOptions>> results;
-      for (uint32_t i = 0; i < count; i++) {
-        // Use dont_AddRef here because these instances are already AddRef-ed in
-        // MobileConnectionIPCSerializer.h
-        nsCOMPtr<nsIMobileCallForwardingOptions> item = dont_AddRef(
-          info.get_ArrayOfnsMobileCallForwardingOptions()[i]);
-        results.AppendElement(item);
-      }
-
-      return NS_SUCCEEDED(mRequestCallback->NotifySendCancelMmiSuccessWithCallForwardingOptions(
-        serviceCode, statusMessage, count,
-        const_cast<nsIMobileCallForwardingOptions**>(info.get_ArrayOfnsMobileCallForwardingOptions().Elements())));
-    }
-
-    default:
-      MOZ_CRASH("Received invalid type!");
-  }
-
-  return false;
-}
-
-bool
 MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessCallForwarding& aReply)
 {
   uint32_t count = aReply.results().Length();
   nsTArray<nsCOMPtr<nsIMobileCallForwardingOptions>> results;
   for (uint32_t i = 0; i < count; i++) {
     // Use dont_AddRef here because these instances are already AddRef-ed in
     // MobileConnectionIPCSerializer.h
     nsCOMPtr<nsIMobileCallForwardingOptions> item = dont_AddRef(aReply.results()[i]);
@@ -667,67 +588,37 @@ MobileConnectionRequestChild::DoReply(co
 
 bool
 MobileConnectionRequestChild::DoReply(const MobileConnectionReplyError& aReply)
 {
   return NS_SUCCEEDED(mRequestCallback->NotifyError(aReply.message()));
 }
 
 bool
-MobileConnectionRequestChild::DoReply(const MobileConnectionReplyErrorMmi& aReply)
-{
-  nsAutoString name(aReply.name());
-  nsAutoString message(aReply.message());
-  nsAutoString serviceCode(aReply.serviceCode());
-  AdditionalInformation info(aReply.additionalInformation());
-
-  // Handle union types
-  switch (info.type()) {
-    case AdditionalInformation::Tuint16_t:
-      return NS_SUCCEEDED(mRequestCallback->NotifyError(name,
-                                                        message,
-                                                        serviceCode,
-                                                        info.get_uint16_t()));
-    case AdditionalInformation::Tvoid_t:
-    default:
-      // If additionInfomation is not uint16_t, handle it as void_t.
-      return NS_SUCCEEDED(mRequestCallback->NotifyError(name,
-                                                        message,
-                                                        serviceCode));
-  }
-
-  return false;
-}
-
-bool
 MobileConnectionRequestChild::Recv__delete__(const MobileConnectionReply& aReply)
 {
   MOZ_ASSERT(mRequestCallback);
 
   switch (aReply.type()) {
     case MobileConnectionReply::TMobileConnectionReplySuccess:
       return DoReply(aReply.get_MobileConnectionReplySuccess());
     case MobileConnectionReply::TMobileConnectionReplySuccessBoolean:
       return DoReply(aReply.get_MobileConnectionReplySuccessBoolean());
     case MobileConnectionReply::TMobileConnectionReplySuccessNetworks:
       return DoReply(aReply.get_MobileConnectionReplySuccessNetworks());
-    case MobileConnectionReply::TMobileConnectionReplySuccessMmi:
-      return DoReply(aReply.get_MobileConnectionReplySuccessMmi());
     case MobileConnectionReply::TMobileConnectionReplySuccessCallForwarding:
       return DoReply(aReply.get_MobileConnectionReplySuccessCallForwarding());
     case MobileConnectionReply::TMobileConnectionReplySuccessCallBarring:
       return DoReply(aReply.get_MobileConnectionReplySuccessCallBarring());
     case MobileConnectionReply::TMobileConnectionReplySuccessClirStatus:
       return DoReply(aReply.get_MobileConnectionReplySuccessClirStatus());
     case MobileConnectionReply::TMobileConnectionReplySuccessPreferredNetworkType:
       return DoReply(aReply.get_MobileConnectionReplySuccessPreferredNetworkType());
     case MobileConnectionReply::TMobileConnectionReplySuccessRoamingPreference:
       return DoReply(aReply.get_MobileConnectionReplySuccessRoamingPreference());
     case MobileConnectionReply::TMobileConnectionReplyError:
       return DoReply(aReply.get_MobileConnectionReplyError());
-    case MobileConnectionReply::TMobileConnectionReplyErrorMmi:
-      return DoReply(aReply.get_MobileConnectionReplyErrorMmi());
     default:
       MOZ_CRASH("Received invalid response type!");
   }
 
   return false;
 }
--- a/dom/mobileconnection/ipc/MobileConnectionChild.h
+++ b/dom/mobileconnection/ipc/MobileConnectionChild.h
@@ -65,20 +65,16 @@ protected:
 
   virtual bool
   RecvNotifyVoiceInfoChanged(nsIMobileConnectionInfo* const& aInfo) MOZ_OVERRIDE;
 
   virtual bool
   RecvNotifyDataInfoChanged(nsIMobileConnectionInfo* const& aInfo) MOZ_OVERRIDE;
 
   virtual bool
-  RecvNotifyUssdReceived(const nsString& aMessage,
-                         const bool& aSessionEnd) MOZ_OVERRIDE;
-
-  virtual bool
   RecvNotifyDataError(const nsString& aMessage) MOZ_OVERRIDE;
 
   virtual bool
   RecvNotifyCFStateChanged(const uint16_t& aAction, const uint16_t& aReason,
                            const nsString& aNumber, const uint16_t& aTimeSeconds,
                            const uint16_t& aServiceClass) MOZ_OVERRIDE;
 
   virtual bool
@@ -144,19 +140,16 @@ public:
 
   bool
   DoReply(const MobileConnectionReplySuccessBoolean& aReply);
 
   bool
   DoReply(const MobileConnectionReplySuccessNetworks& aReply);
 
   bool
-  DoReply(const MobileConnectionReplySuccessMmi& aReply);
-
-  bool
   DoReply(const MobileConnectionReplySuccessCallForwarding& aReply);
 
   bool
   DoReply(const MobileConnectionReplySuccessCallBarring& aReply);
 
   bool
   DoReply(const MobileConnectionReplySuccessClirStatus& aReply);
 
@@ -164,19 +157,16 @@ public:
   DoReply(const MobileConnectionReplySuccessPreferredNetworkType& aReply);
 
   bool
   DoReply(const MobileConnectionReplySuccessRoamingPreference& aMode);
 
   bool
   DoReply(const MobileConnectionReplyError& aReply);
 
-  bool
-  DoReply(const MobileConnectionReplyErrorMmi& aReply);
-
 protected:
   virtual
   ~MobileConnectionRequestChild()
   {
     MOZ_COUNT_DTOR(MobileConnectionRequestChild);
   }
 
   virtual void
--- a/dom/mobileconnection/ipc/MobileConnectionParent.cpp
+++ b/dom/mobileconnection/ipc/MobileConnectionParent.cpp
@@ -62,20 +62,16 @@ MobileConnectionParent::RecvPMobileConne
     case MobileConnectionRequest::TSetRoamingPreferenceRequest:
       return actor->DoRequest(aRequest.get_SetRoamingPreferenceRequest());
     case MobileConnectionRequest::TGetRoamingPreferenceRequest:
       return actor->DoRequest(aRequest.get_GetRoamingPreferenceRequest());
     case MobileConnectionRequest::TSetVoicePrivacyModeRequest:
       return actor->DoRequest(aRequest.get_SetVoicePrivacyModeRequest());
     case MobileConnectionRequest::TGetVoicePrivacyModeRequest:
       return actor->DoRequest(aRequest.get_GetVoicePrivacyModeRequest());
-    case MobileConnectionRequest::TSendMmiRequest:
-      return actor->DoRequest(aRequest.get_SendMmiRequest());
-    case MobileConnectionRequest::TCancelMmiRequest:
-      return actor->DoRequest(aRequest.get_CancelMmiRequest());
     case MobileConnectionRequest::TSetCallForwardingRequest:
       return actor->DoRequest(aRequest.get_SetCallForwardingRequest());
     case MobileConnectionRequest::TGetCallForwardingRequest:
       return actor->DoRequest(aRequest.get_GetCallForwardingRequest());
     case MobileConnectionRequest::TSetCallBarringRequest:
       return actor->DoRequest(aRequest.get_SetCallBarringRequest());
     case MobileConnectionRequest::TGetCallBarringRequest:
       return actor->DoRequest(aRequest.get_GetCallBarringRequest());
@@ -188,26 +184,16 @@ MobileConnectionParent::NotifyDataChange
   NS_ENSURE_SUCCESS(rv, rv);
 
   // We release the ref after serializing process is finished in
   // MobileConnectionIPCSerializer.
   return SendNotifyDataInfoChanged(info.forget().take()) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-MobileConnectionParent::NotifyUssdReceived(const nsAString& aMessage,
-                                           bool aSessionEnded)
-{
-  NS_ENSURE_TRUE(mLive, NS_ERROR_FAILURE);
-
-  return SendNotifyUssdReceived(nsAutoString(aMessage), aSessionEnded)
-         ? NS_OK : NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
 MobileConnectionParent::NotifyDataError(const nsAString& aMessage)
 {
   NS_ENSURE_TRUE(mLive, NS_ERROR_FAILURE);
 
   return SendNotifyDataError(nsAutoString(aMessage)) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
@@ -395,32 +381,16 @@ bool
 MobileConnectionRequestParent::DoRequest(const GetVoicePrivacyModeRequest& aRequest)
 {
   NS_ENSURE_TRUE(mMobileConnection, false);
 
   return NS_SUCCEEDED(mMobileConnection->GetVoicePrivacyMode(this));
 }
 
 bool
-MobileConnectionRequestParent::DoRequest(const SendMmiRequest& aRequest)
-{
-  NS_ENSURE_TRUE(mMobileConnection, false);
-
-  return NS_SUCCEEDED(mMobileConnection->SendMMI(aRequest.mmi(), this));
-}
-
-bool
-MobileConnectionRequestParent::DoRequest(const CancelMmiRequest& aRequest)
-{
-  NS_ENSURE_TRUE(mMobileConnection, false);
-
-  return NS_SUCCEEDED(mMobileConnection->CancelMMI(this));
-}
-
-bool
 MobileConnectionRequestParent::DoRequest(const SetCallForwardingRequest& aRequest)
 {
   NS_ENSURE_TRUE(mMobileConnection, false);
 
   return NS_SUCCEEDED(mMobileConnection->SetCallForwarding(aRequest.action(),
                                                            aRequest.reason(),
                                                            aRequest.number(),
                                                            aRequest.timeSeconds(),
@@ -552,67 +522,16 @@ MobileConnectionRequestParent::NotifyGet
     // We release the ref after serializing process is finished in
     // MobileConnectionIPCSerializer.
     networks.AppendElement(network.forget().take());
   }
   return SendReply(MobileConnectionReplySuccessNetworks(networks));
 }
 
 NS_IMETHODIMP
-MobileConnectionRequestParent::NotifySendCancelMmiSuccess(const nsAString& aServiceCode,
-                                                          const nsAString& aStatusMessage)
-{
-  return SendReply(MobileConnectionReplySuccessMmi(nsString(aServiceCode),
-                                                   nsString(aStatusMessage),
-                                                   AdditionalInformation(mozilla::void_t())));
-}
-
-NS_IMETHODIMP
-MobileConnectionRequestParent::NotifySendCancelMmiSuccessWithInteger(const nsAString& aServiceCode,
-                                                                     const nsAString& aStatusMessage,
-                                                                     uint16_t aAdditionalInformation)
-{
-  return SendReply(MobileConnectionReplySuccessMmi(nsString(aServiceCode),
-                                                   nsString(aStatusMessage),
-                                                   AdditionalInformation(aAdditionalInformation)));
-}
-
-NS_IMETHODIMP
-MobileConnectionRequestParent::NotifySendCancelMmiSuccessWithStrings(const nsAString& aServiceCode,
-                                                                     const nsAString& aStatusMessage,
-                                                                     uint32_t aCount,
-                                                                     const char16_t** aAdditionalInformation)
-{
-  nsTArray<nsString> additionalInformation;
-  for (uint32_t i = 0; i < aCount; i++) {
-    additionalInformation.AppendElement(nsDependentString(aAdditionalInformation[i]));
-  }
-
-  return SendReply(MobileConnectionReplySuccessMmi(nsString(aServiceCode),
-                                                   nsString(aStatusMessage),
-                                                   AdditionalInformation(additionalInformation)));
-}
-
-NS_IMETHODIMP
-MobileConnectionRequestParent::NotifySendCancelMmiSuccessWithCallForwardingOptions(const nsAString& aServiceCode,
-                                                                                   const nsAString& aStatusMessage,
-                                                                                   uint32_t aCount,
-                                                                                   nsIMobileCallForwardingOptions** aAdditionalInformation)
-{
-  nsTArray<nsIMobileCallForwardingOptions*> additionalInformation;
-  for (uint32_t i = 0; i < aCount; i++) {
-    additionalInformation.AppendElement(aAdditionalInformation[i]);
-  }
-
-  return SendReply(MobileConnectionReplySuccessMmi(nsString(aServiceCode),
-                                                   nsString(aStatusMessage),
-                                                   AdditionalInformation(additionalInformation)));
-}
-
-NS_IMETHODIMP
 MobileConnectionRequestParent::NotifyGetCallForwardingSuccess(uint32_t aCount,
                                                               nsIMobileCallForwardingOptions** aResults)
 {
   nsTArray<nsIMobileCallForwardingOptions*> results;
   for (uint32_t i = 0; i < aCount; i++) {
     results.AppendElement(aResults[i]);
   }
 
@@ -643,31 +562,13 @@ MobileConnectionRequestParent::NotifyGet
 
 NS_IMETHODIMP
 MobileConnectionRequestParent::NotifyGetRoamingPreferenceSuccess(int32_t aMode)
 {
   return SendReply(MobileConnectionReplySuccessRoamingPreference(aMode));
 }
 
 NS_IMETHODIMP
-MobileConnectionRequestParent::NotifyError(const nsAString& aName,
-                                           const nsAString& aMessage,
-                                           const nsAString& aServiceCode,
-                                           uint16_t aInfo,
-                                           uint8_t aArgc)
+MobileConnectionRequestParent::NotifyError(const nsAString& aName)
 {
-  if (aArgc == 0) {
-    nsAutoString error(aName);
-    return SendReply(MobileConnectionReplyError(error));
-  }
-
-  nsAutoString name(aName);
-  nsAutoString message(aMessage);
-  nsAutoString serviceCode(aServiceCode);
-
-  if (aArgc < 3) {
-    return SendReply(MobileConnectionReplyErrorMmi(name, message, serviceCode,
-                                                   AdditionalInformation(mozilla::void_t())));
-  }
-
-  return SendReply(MobileConnectionReplyErrorMmi(name, message, serviceCode,
-                                                 AdditionalInformation(aInfo)));
+  nsAutoString error(aName);
+  return SendReply(MobileConnectionReplyError(error));
 }
--- a/dom/mobileconnection/ipc/MobileConnectionParent.h
+++ b/dom/mobileconnection/ipc/MobileConnectionParent.h
@@ -107,22 +107,16 @@ public:
 
   bool
   DoRequest(const SetVoicePrivacyModeRequest& aRequest);
 
   bool
   DoRequest(const GetVoicePrivacyModeRequest& aRequest);
 
   bool
-  DoRequest(const SendMmiRequest& aRequest);
-
-  bool
-  DoRequest(const CancelMmiRequest& aRequest);
-
-  bool
   DoRequest(const SetCallForwardingRequest& aRequest);
 
   bool
   DoRequest(const GetCallForwardingRequest& aRequest);
 
   bool
   DoRequest(const SetCallBarringRequest& aRequest);
 
--- a/dom/mobileconnection/ipc/PMobileConnection.ipdl
+++ b/dom/mobileconnection/ipc/PMobileConnection.ipdl
@@ -15,17 +15,16 @@ namespace mobileconnection {
 sync protocol PMobileConnection
 {
   manager PContent;
   manages PMobileConnectionRequest;
 
 child:
   NotifyVoiceInfoChanged(nsMobileConnectionInfo aInfo);
   NotifyDataInfoChanged(nsMobileConnectionInfo aInfo);
-  NotifyUssdReceived(nsString aMessage, bool aSessionEnd);
   NotifyDataError(nsString aMessage);
   NotifyCFStateChanged(uint16_t aAction, uint16_t aReason, nsString aNumber,
                        uint16_t aTimeSeconds, uint16_t aServiceClass);
   NotifyEmergencyCbModeChanged(bool aActive, uint32_t aTimeoutMs);
   NotifyOtaStatusChanged(nsString aStatus);
   NotifyIccChanged(nsString aIccId);
   NotifyRadioStateChanged(int32_t aRadioState);
   NotifyClirModeChanged(uint32_t aMode);
@@ -92,25 +91,16 @@ struct SetVoicePrivacyModeRequest
 {
   bool enabled;
 };
 
 struct GetVoicePrivacyModeRequest
 {
 };
 
-struct SendMmiRequest
-{
-  nsString mmi;
-};
-
-struct CancelMmiRequest
-{
-};
-
 struct SetCallForwardingRequest
 {
   uint16_t action;
   uint16_t reason;
   nsString number;
   uint16_t timeSeconds;
   uint16_t serviceClass;
 };
@@ -174,18 +164,16 @@ union MobileConnectionRequest
   SelectNetworkRequest;
   SelectNetworkAutoRequest;
   SetPreferredNetworkTypeRequest;
   GetPreferredNetworkTypeRequest;
   SetRoamingPreferenceRequest;
   GetRoamingPreferenceRequest;
   SetVoicePrivacyModeRequest;
   GetVoicePrivacyModeRequest;
-  SendMmiRequest;
-  CancelMmiRequest;
   SetCallForwardingRequest;
   GetCallForwardingRequest;
   SetCallBarringRequest;
   GetCallBarringRequest;
   ChangeCallBarringPasswordRequest;
   SetCallWaitingRequest;
   GetCallWaitingRequest;
   SetCallingLineIdRestrictionRequest;
--- a/dom/mobileconnection/ipc/PMobileConnectionRequest.ipdl
+++ b/dom/mobileconnection/ipc/PMobileConnectionRequest.ipdl
@@ -35,23 +35,16 @@ struct MobileConnectionReplySuccessBoole
   bool result;
 };
 
 struct MobileConnectionReplySuccessNetworks
 {
   nsMobileNetworkInfo[] results;
 };
 
-struct MobileConnectionReplySuccessMmi
-{
-  nsString serviceCode;
-  nsString statusMessage;
-  AdditionalInformation additionalInformation;
-};
-
 struct MobileConnectionReplySuccessCallForwarding
 {
   nsMobileCallForwardingOptions[] results;
 };
 
 struct MobileConnectionReplySuccessCallBarring
 {
   uint16_t program;
@@ -76,36 +69,26 @@ struct MobileConnectionReplySuccessRoami
 };
 
 // Error
 struct MobileConnectionReplyError
 {
   nsString message;
 };
 
-struct MobileConnectionReplyErrorMmi
-{
-  nsString name;
-  nsString message;
-  nsString serviceCode;
-  AdditionalInformation additionalInformation;
-};
-
 union MobileConnectionReply
 {
   // Success
   MobileConnectionReplySuccess;
   MobileConnectionReplySuccessBoolean;
   MobileConnectionReplySuccessNetworks;
-  MobileConnectionReplySuccessMmi;
   MobileConnectionReplySuccessCallForwarding;
   MobileConnectionReplySuccessCallBarring;
   MobileConnectionReplySuccessClirStatus;
   MobileConnectionReplySuccessPreferredNetworkType;
   MobileConnectionReplySuccessRoamingPreference;
   // Error
   MobileConnectionReplyError;
-  MobileConnectionReplyErrorMmi;
 };
 
 } // namespace mobileconnection
 } // namespace dom
 } // namespace mozilla
--- a/dom/mobileconnection/tests/marionette/manifest.ini
+++ b/dom/mobileconnection/tests/marionette/manifest.ini
@@ -9,20 +9,16 @@ qemu = true
 [test_mobile_operator_names.js]
 [test_mobile_operator_names_plmnlist.js]
 [test_mobile_operator_names_roaming.js]
 [test_mobile_preferred_network_type.js]
 [test_mobile_preferred_network_type_radio_off.js]
 [test_mobile_data_connection.js]
 [test_mobile_data_location.js]
 [test_mobile_data_state.js]
-[test_mobile_mmi.js]
-[test_mobile_mmi_change_pin.js]
-[test_mobile_mmi_call_forwarding.js]
-[test_mobile_mmi_unlock_puk.js]
 [test_mobile_roaming_preference.js]
 [test_call_barring_get_option.js]
 [test_call_barring_set_error.js]
 [test_call_barring_change_password.js]
 [test_mobile_set_radio.js]
 [test_mobile_last_known_network.js]
 [test_mobile_icc_change.js]
 [test_mobile_connections_array_uninitialized.js]
deleted file mode 100644
--- a/dom/mobileconnection/tests/marionette/test_mobile_mmi.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-function testGettingIMEI() {
-  log("Test *#06# ...");
-
-  let MMI_CODE = "*#06#";
-  return sendMMI(MMI_CODE)
-    .then(function resolve(aResult) {
-      ok(true, MMI_CODE + " success");
-      is(aResult.serviceCode, "scImei", "Service code IMEI");
-      // IMEI is hardcoded as "000000000000000".
-      // See it here {B2G_HOME}/external/qemu/telephony/android_modem.c
-      // (The result of +CGSN).
-      is(aResult.statusMessage, "000000000000000", "Emulator IMEI");
-      is(aResult.additionalInformation, undefined, "No additional information");
-    }, function reject() {
-      ok(false, MMI_CODE + " should not fail");
-    });
-}
-
-function testInvalidMMICode() {
-  log("Test invalid MMI code ...");
-
-  let MMI_CODE = "InvalidMMICode";
-  return sendMMI(MMI_CODE)
-    .then(function resolve() {
-      ok(false, MMI_CODE + " should not success");
-    }, function reject(aError) {
-      ok(true, MMI_CODE + " fail");
-      is(aError.name, "emMmiError", "MMI error name");
-      is(aError.message, "", "No message");
-      is(aError.serviceCode, "scUssd", "Service code USSD");
-      is(aError.additionalInformation, null, "No additional information");
-    });
-}
-
-// Start test
-startTestCommon(function() {
-   return Promise.resolve()
-    .then(() => testGettingIMEI())
-    .then(() => testInvalidMMICode());
-});
deleted file mode 100644
--- a/dom/mobileconnection/tests/marionette/test_mobile_mmi_call_forwarding.js
+++ /dev/null
@@ -1,144 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-const TEST_DATA = [
-  {
-    reason: MozMobileConnection.CALL_FORWARD_REASON_UNCONDITIONAL,
-    number: "+886912345678",
-    serviceClass: MozMobileConnection.ICC_SERVICE_CLASS_VOICE,
-    timeSeconds: 5
-  }, {
-    reason: MozMobileConnection.CALL_FORWARD_REASON_MOBILE_BUSY,
-    number: "0912345678",
-    serviceClass: MozMobileConnection.ICC_SERVICE_CLASS_VOICE,
-    timeSeconds: 10
-  }, {
-    reason: MozMobileConnection.CALL_FORWARD_REASON_NO_REPLY,
-    number: "+886987654321",
-    serviceClass: MozMobileConnection.ICC_SERVICE_CLASS_VOICE,
-    timeSeconds: 15
-  }, {
-    reason: MozMobileConnection.CALL_FORWARD_REASON_NOT_REACHABLE,
-    number: "+0987654321",
-    serviceClass: MozMobileConnection.ICC_SERVICE_CLASS_VOICE,
-    timeSeconds: 20
-  }
-];
-
-// Please see TS 22.030 Annex B
-const CF_REASON_TO_MMI = {
-  /* CALL_FORWARD_REASON_UNCONDITIONAL */
-  0: "21",
-  /* CALL_FORWARD_REASON_MOBILE_BUSY */
-  1: "67",
-  /* CALL_FORWARD_REASON_NO_REPLY */
-  2: "61",
-  /* CALL_FORWARD_REASON_NOT_REACHABLE */
-  3: "62",
-  /* CALL_FORWARD_REASON_ALL_CALL_FORWARDING */
-  4: "002",
-  /* CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING */
-  5: "004"
-};
-
-// Please see TS 22.030 Annex C
-const SERVICE_CLASS_TO_MMI = {
-  /* ICC_SERVICE_CLASS_VOICE */
-  1: "11"
-};
-
-function testSetCallForwarding(aData) {
-  // Registration: **SC*SIA*SIB*SIC#
-  let MMI_CODE = "**" + CF_REASON_TO_MMI[aData.reason] + "*" + aData.number +
-                 "*" + SERVICE_CLASS_TO_MMI[aData.serviceClass] +
-                 "*" + aData.timeSeconds + "#";
-  log("Test " + MMI_CODE);
-
-  let promises = [];
-  // Check cfstatechange event.
-  promises.push(waitForManagerEvent("cfstatechange").then(function(aEvent) {
-    is(aEvent.action, MozMobileConnection.CALL_FORWARD_ACTION_REGISTRATION,
-       "check action");
-    is(aEvent.reason, aData.reason, "check reason");
-    is(aEvent.number, aData.number, "check number");
-    is(aEvent.timeSeconds, aData.timeSeconds, "check timeSeconds");
-    is(aEvent.serviceClass, aData.serviceClass, "check serviceClass");
-  }));
-  // Check DOMRequest's result.
-  promises.push(sendMMI(MMI_CODE)
-    .then(function resolve(aResult) {
-      is(aResult.serviceCode, "scCallForwarding", "Check service code");
-      is(aResult.statusMessage, "smServiceRegistered", "Check status message");
-      is(aResult.additionalInformation, undefined, "Check additional information");
-    }, function reject(aError) {
-      ok(false, "got '" + aError.name + "' error");
-    }));
-
-  return Promise.all(promises);
-}
-
-function testGetCallForwarding(aExpectedData) {
-  // Interrogation: *#SC#
-  let MMI_CODE = "*#" + CF_REASON_TO_MMI[aExpectedData.reason] + "#";
-  log("Test " + MMI_CODE);
-
-  return sendMMI(MMI_CODE)
-    .then(function resolve(aResult) {
-      is(aResult.serviceCode, "scCallForwarding", "Check service code");
-      is(aResult.statusMessage, "smServiceInterrogated", "Check status message");
-      is(Array.isArray(aResult.additionalInformation), true,
-         "additionalInformation should be an array");
-
-      for (let i = 0; i < aResult.additionalInformation.length; i++) {
-        let result = aResult.additionalInformation[i];
-
-        // Only need to check the result containing the serviceClass that we are
-        // interested in.
-        if (!(result.serviceClass & aExpectedData.serviceClass)) {
-          continue;
-        }
-
-        is(result.active, true, "check active");
-        is(result.reason, aExpectedData.reason, "check reason");
-        is(result.number, aExpectedData.number, "check number");
-        is(result.timeSeconds, aExpectedData.timeSeconds, "check timeSeconds");
-      }
-    }, function reject(aError) {
-      ok(false, MMI_CODE + " got error: " + aError.name);
-    });
-}
-
-function clearAllCallForwardingSettings() {
-  log("Clear all call forwarding settings");
-
-  let promise = Promise.resolve();
-  for (let reason = MozMobileConnection.CALL_FORWARD_REASON_UNCONDITIONAL;
-       reason <= MozMobileConnection.CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING;
-       reason++) {
-    let options = {
-      reason: reason,
-      action: MozMobileConnection.CALL_FORWARD_ACTION_ERASURE
-    };
-    // Emulator doesn't support CALL_FORWARD_REASON_ALL_* yet, we catch the
-    // reject here in order to avoid impact the test result.
-    promise =
-      promise.then(() => setCallForwardingOption(options).then(null, () => {}));
-  }
-  return promise;
-}
-
-// Start tests
-startTestCommon(function() {
-  let promise = Promise.resolve();
-  for (let i = 0; i < TEST_DATA.length; i++) {
-    let data = TEST_DATA[i];
-    promise = promise.then(() => testSetCallForwarding(data))
-                     .then(() => testGetCallForwarding(data));
-  }
-  // reset call forwarding settings.
-  return promise.then(null, () => { ok(false, "promise reject during test"); })
-    .then(() => clearAllCallForwardingSettings());
-});
deleted file mode 100644
--- a/dom/mobileconnection/tests/marionette/test_mobile_mmi_change_pin.js
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = "head.js";
-
-// PIN is hardcoded as "0000" by default.
-// See it here {B2G_HOME}/external/qemu/telephony/sim_card.c,
-// in asimcard_create().
-const TEST_DATA = [
-  // Test passing no pin.
-  {
-    pin: "",
-    newPin: "0000",
-    newPinAgain: "1111",
-    expectedError: {
-      name: "emMmiError",
-      additionalInformation: null
-    }
-  },
-  // Test passing no newPin.
-  {
-    pin: "0000",
-    newPin: "",
-    newPinAgain: "",
-    expectedError: {
-      name: "emMmiError",
-      additionalInformation: null
-    }
-  },
-  // Test passing mismatched newPin.
-  {
-    pin: "0000",
-    newPin: "0000",
-    newPinAgain: "1111",
-    expectedError: {
-      name: "emMmiErrorMismatchPin",
-      additionalInformation: null
-    }
-  },
-  // Test passing invalid pin (< 4 digit).
-  {
-    pin: "000",
-    newPin: "0000",
-    newPinAgain: "0000",
-    expectedError: {
-      name: "emMmiErrorInvalidPin",
-      additionalInformation: null
-    }
-  },
-  // Test passing invalid newPin (> 8 digit).
-  {
-    pin: "0000",
-    newPin: "000000000",
-    newPinAgain: "000000000",
-    expectedError: {
-      name: "emMmiErrorInvalidPin",
-      additionalInformation: null
-    }
-  },
-  // Test passing incorrect pin.
-  {
-    pin: "1234",
-    newPin: "0000",
-    newPinAgain: "0000",
-    expectedError: {
-      name: "emMmiErrorBadPin",
-      // The default pin retries is 3, failed once becomes to 2
-      additionalInformation: 2
-    }
-  },
-  // Test changing pin successfully (Reset the retries).
-  {
-    pin: "0000",
-    newPin: "0000",
-    newPinAgain: "0000"
-  }
-];
-
-function testChangePin(aPin, aNewPin, aNewPinAgain, aExpectedError) {
-  let MMI_CODE = "**04*" + aPin + "*" + aNewPin + "*" + aNewPinAgain + "#";
-  log("Test " + MMI_CODE);
-
-  return sendMMI(MMI_CODE)
-    .then(function resolve(aResult) {
-      ok(!aExpectedError, MMI_CODE + " success");
-      is(aResult.serviceCode, "scPin", "Check service code");
-      is(aResult.statusMessage, "smPinChanged", "Check status message");
-      is(aResult.additionalInformation, undefined, "Check additional information");
-    }, function reject(aError) {
-      ok(aExpectedError, MMI_CODE + " fail");
-      is(aError.name, aExpectedError.name, "Check name");
-      is(aError.message, "", "Check message");
-      is(aError.serviceCode, "scPin", "Check service code");
-      is(aError.additionalInformation, aExpectedError.additionalInformation,
-         "Chech additional information");
-    });
-}
-
-// Start test
-startTestCommon(function() {
-  let promise = Promise.resolve();
-  for (let i = 0; i < TEST_DATA.length; i++) {
-    let data = TEST_DATA[i];
-    promise = promise.then(() => testChangePin(data.pin,
-                                               data.newPin,
-                                               data.newPinAgain,
-                                               data.expectedError));
-  }
-  return promise;
-});
--- a/dom/mobileconnection/tests/mochitest/test_mobileconnection_permission.html
+++ b/dom/mobileconnection/tests/mochitest/test_mobileconnection_permission.html
@@ -44,18 +44,16 @@ if (!SpecialPowers.hasPermission("mobile
   is("selectNetwork" in mobileConnection, true, "selectNetwork");
   is("selectNetworkAutomatically" in mobileConnection, true, "selectNetworkAutomatically");
   is("setPreferredNetworkType" in mobileConnection, true, "setPreferredNetworkType");
   is("getPreferredNetworkType" in mobileConnection, true, "getPreferredNetworkType");
   is("setRoamingPreference" in mobileConnection, true, "setRoamingPreference");
   is("getRoamingPreference" in mobileConnection, true, "getRoamingPreference");
   is("setVoicePrivacyMode" in mobileConnection, true, "setVoicePrivacyMode");
   is("getVoicePrivacyMode" in mobileConnection, true, "getVoicePrivacyMode");
-  is("sendMMI" in mobileConnection, true, "sendMMI");
-  is("cancelMMI" in mobileConnection, true, "cancelMMI");
   is("setCallForwardingOption" in mobileConnection, true, "setCallForwardingOption");
   is("getCallForwardingOption" in mobileConnection, true, "getCallForwardingOption");
   is("setCallBarringOption" in mobileConnection, true, "setCallBarringOption");
   is("getCallBarringOption" in mobileConnection, true, "getCallBarringOption");
   is("changeCallBarringPassword" in mobileConnection, true, "changeCallBarringPassword");
   is("setCallWaitingOption" in mobileConnection, true, "setCallWaitingOption");
   is("getCallWaitingOption" in mobileConnection, true, "getCallWaitingOption");
   is("setCallingLineIdRestriction" in mobileConnection, true, "setCallingLineIdRestriction");
--- a/dom/mobileconnection/tests/mochitest/test_mobilenetwork_permission.html
+++ b/dom/mobileconnection/tests/mochitest/test_mobilenetwork_permission.html
@@ -44,18 +44,16 @@ if (!SpecialPowers.hasPermission("mobile
   is("selectNetwork" in mobileConnection, false, "selectNetwork");
   is("selectNetworkAutomatically" in mobileConnection, false, "selectNetworkAutomatically");
   is("setPreferredNetworkType" in mobileConnection, false, "setPreferredNetworkType");
   is("getPreferredNetworkType" in mobileConnection, false, "getPreferredNetworkType");
   is("setRoamingPreference" in mobileConnection, false, "setRoamingPreference");
   is("getRoamingPreference" in mobileConnection, false, "getRoamingPreference");
   is("setVoicePrivacyMode" in mobileConnection, false, "setVoicePrivacyMode");
   is("getVoicePrivacyMode" in mobileConnection, false, "getVoicePrivacyMode");
-  is("sendMMI" in mobileConnection, false, "sendMMI");
-  is("cancelMMI" in mobileConnection, false, "cancelMMI");
   is("setCallForwardingOption" in mobileConnection, false, "setCallForwardingOption");
   is("getCallForwardingOption" in mobileConnection, false, "getCallForwardingOption");
   is("setCallBarringOption" in mobileConnection, false, "setCallBarringOption");
   is("getCallBarringOption" in mobileConnection, false, "getCallBarringOption");
   is("changeCallBarringPassword" in mobileConnection, false, "changeCallBarringPassword");
   is("setCallWaitingOption" in mobileConnection, false, "setCallWaitingOption");
   is("getCallWaitingOption" in mobileConnection, false, "getCallWaitingOption");
   is("setCallingLineIdRestriction" in mobileConnection, false, "setCallingLineIdRestriction");
new file mode 100644
--- /dev/null
+++ b/dom/settings/tests/file_loadserver.js
@@ -0,0 +1,17 @@
+let Ci = Components.interfaces;
+let Cc = Components.classes;
+let Cu = Components.utils;
+
+// Stolen from SpecialPowers, since at this point we don't know we're in a test.
+let isMainProcess = function() {
+  try {
+    return Cc["@mozilla.org/xre/app-info;1"].
+        getService(Ci.nsIXULRuntime).
+        processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
+  } catch (e) { }
+  return true;
+};
+
+if (isMainProcess()) {
+  Components.utils.import("resource://gre/modules/SettingsRequestManager.jsm");
+}
--- a/dom/settings/tests/mochitest.ini
+++ b/dom/settings/tests/mochitest.ini
@@ -1,10 +1,12 @@
 [DEFAULT]
-skip-if = (toolkit == 'gonk' && debug) || e10s #debug-only failure, bug 932878
+skip-if = (toolkit == 'gonk' && debug) #debug-only failure, bug 932878
+support-files =
+  file_loadserver.js
 
 [test_settings_basics.html]
 [test_settings_permissions.html]
 [test_settings_blobs.html]
 [test_settings_data_uris.html]
 [test_settings_events.html]
 [test_settings_navigator_object.html]
 [test_settings_onsettingchange.html]
--- a/dom/settings/tests/test_settings_basics.html
+++ b/dom/settings/tests/test_settings_basics.html
@@ -16,20 +16,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 "use strict";
 
-if (SpecialPowers.isMainProcess()) {
-  SpecialPowers.Cu.import("resource://gre/modules/SettingsRequestManager.jsm");
-}
-
+var url = SimpleTest.getTestFileURL("file_loadserver.js");
+var script = SpecialPowers.loadChromeScript(url);
 SpecialPowers.addPermission("settings-api-read", true, document);
 SpecialPowers.addPermission("settings-api-write", true, document);
 SpecialPowers.addPermission("settings-read", true, document);
 SpecialPowers.addPermission("settings-write", true, document);
 SpecialPowers.addPermission("settings-clear", true, document);
 
 function onUnwantedSuccess() {
   ok(false, "onUnwantedSuccess: shouldn't get here");
@@ -94,50 +92,48 @@ function onsettingschangeWithNext(event)
 
 function check(o1, o2) {
   is(JSON.stringify(o1), JSON.stringify(o2), "same");
 }
 
 var req, req2, req3, req4, req5, req6;
 var index = 0;
 
-var mozSettings = navigator.mozSettings;
-
 var steps = [
   function () {
     ok(true, "Deleting database");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.clear();
     req.onsuccess = function () {
       ok(true, "Deleted the database");
       next();
     };
   },
   function () {
     ok(true, "Setting wifi");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(wifi);
     req.onsuccess = function () {
       ok(true, "set done");
     }
     req.onerror = onFailure;
 
-    var lock2 = mozSettings.createLock();
+    var lock2 = navigator.mozSettings.createLock();
     req2 = lock2.get("net3g.apn");
     req2.onsuccess = function () {
       is(Object.keys(req2.result).length, 1, "length 1");
       check(wifi, req2.result);
       ok(true, "Get net3g.apn Done");
       next();
     };
     req2.onerror = onFailure;
   },
   function () {
     ok(true, "Change wifi1");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(wifi2);
     req.onsuccess = function () {
       ok(true, "Set Done");
     };
     req.onerror = onFailure;
     ok(true, "Get changed net3g.apn");
     req2 = lock.get("net3g.apn");
     req2.onsuccess = function () {
@@ -145,159 +141,159 @@ var steps = [
       check(wifi2, req2.result);
       ok(true, "Get net3g.apn Done");
       next();
     };
     req2.onerror = onFailure;
   },
   function () {
     ok(true, "Set Combination");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req3 = lock.set(combination);
     req3.onsuccess = function () {
       ok(true, "set done");
       req4 = lock.get("net3g.apn2");
       req4.onsuccess = function() {
         ok(true, "Done");
         check(combination["net3g.apn2"], req4.result["net3g.apn2"]);
         next();
       }
     }
     req3.onerror = onFailure;
   },
   function() {
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req4 = lock.get("net3g.apn2");
     req4.onsuccess = function() {
       ok(true, "Done");
       check(combination["net3g.apn2"], req4.result["net3g.apn2"]);
       next();
     }
     req4.onerror = onFailure;
   },
   function() {
     ok(true, "Get unknown key");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("abc.def");
     req.onsuccess = function() {
       is(req.result["abc.def"], undefined, "no result");
       next();
     };
     req.onerror = onFailure;
   },
   function() {
     ok(true, "adding onsettingchange");
     navigator.mozSettings.onsettingchange = onsettingschangeWithNext;
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req2 = lock.get("screen.brightness");
     req2.onsuccess = function() {
       ok(true, "end adding onsettingchange");
       next();
     };
     req2.onerror = onFailure;
   },
   function() {
     ok(true, "Test onsettingchange");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set done, observer has to call next");
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "delete onsettingschange");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     navigator.mozSettings.onsettingchange = null;
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set done");
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Waiting for all set callbacks");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("screen.brightness");
     req.onsuccess = function() {
       ok(true, "Done");
       next();
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "adding Observers 1");
     navigator.mozSettings.addObserver("screen.brightness", observer1);
     navigator.mozSettings.addObserver("screen.brightness", observer1);
     navigator.mozSettings.addObserver("screen.brightness", observer2);
     navigator.mozSettings.addObserver("screen.brightness", observerWithNext);
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req2 = lock.get("screen.brightness");
     req2.onsuccess = function() {
       ok(true, "set observeSetting done!");
       next();
     };
     req2.onerror = onFailure;
   },
   function() {
     ok(true, "test observers");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set done");
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "removing Event Listener");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set done");
       navigator.mozSettings.removeObserver("screen.brightness", observer2);
       navigator.mozSettings.removeObserver("screen.brightness", observer1);
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "test Event Listener");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set done");
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "removing Event Listener");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     navigator.mozSettings.removeObserver("screen.brightness", observerWithNext);
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set done");
       navigator.mozSettings.removeObserver("screen.brightness", observer2);
       navigator.mozSettings.removeObserver("screen.brightness", observer1);
       next();
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "removing Event Listener");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("screen.brightness");
     req.onsuccess = function () {
       ok(true, "get done");
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Nested test");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("screen.brightness");
     req.onsuccess = function () {
       req3 = lock.set({"screen.brightness": req.result["screen.brightness"] + 1})
       req3.onsuccess = function () {
         req4 = lock.get("screen.brightness");
         req4.onsuccess = function() {
           is(req4.result["screen.brightness"], 1.7, "same Value");
         }
@@ -308,43 +304,43 @@ var steps = [
     req.onerror = onFailure;
 
     req2 = lock.get("screen.brightness");
     req2.onsuccess = function () {
       is(req2.result["screen.brightness"], 0.7, "same Value");
     }
     req2.onerror = onFailure;
 
-    var lock2 = mozSettings.createLock();
+    var lock2 = navigator.mozSettings.createLock();
     req5 = lock2.get("screen.brightness");
     req5.onsuccess = function () {
       is(req5.result["screen.brightness"], 1.7, "same Value");
       next();
     }
     req5.onerror = onFailure;
   },
   function () {
     ok(true, "Deleting database");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.clear();
     req.onsuccess = function () {
       ok(true, "Deleted the database");
       next();
     };
   },
   function () {
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req2 = lock.set(wifi);
     req2.onsuccess = function () {
       ok(true, "set done");
     }
     req2.onerror = onFailure;
 
     ok(true, "Get all settings");
-    var lock2 = mozSettings.createLock();
+    var lock2 = navigator.mozSettings.createLock();
     req3 = lock2.get("*");
     req3.onsuccess = function () {
       is(Object.keys(req3.result).length, 1, "length 1");
       check(req3.result, wifi);
       ok(true, JSON.stringify(req3.result));
       ok(true, "Get all settings Done");
     };
     req3.onerror = onFailure;
@@ -355,17 +351,17 @@ var steps = [
       check(wifi, req4.result);
       ok(true, "Get net3g.apn Done");
       next();
     };
     req4.onerror = onFailure;
   },
   function () {
     ok(true, "Change wifi1");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(wifi2);
     req.onsuccess = function () {
       ok(true, "Set Done");
     };
     req.onerror = onFailure;
 
     ok(true, "Get changed net3g.apn");
     req2 = lock.get("net3g.apn");
@@ -374,409 +370,409 @@ var steps = [
       check(wifi2, req2.result);
       ok(true, "Get net3g.apn Done");
       next();
     };
     req2.onerror = onFailure;
   },
   function () {
     ok(true, "Test locking");
-    var lock = mozSettings.createLock();
-    var lock2 = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
+    var lock2 = navigator.mozSettings.createLock();
     req = lock.set(wifiEnabled);
     req.onsuccess = function () {
       ok(true, "Test Locking Done");
     };
     req.onerror = onFailure;
 
     req2 = lock2.set(wifiDisabled);
     req2.onsuccess = function () {
       ok(true, "Set Done");
       next();
     };
     req2.onerror = onFailure;
   },
   function () {
     ok(true, "Test locking result");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("wifi.enabled");
     req.onsuccess = function() {
       check(req.result, wifiDisabled);
       ok(true, "Test1 locking result done");
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Test locking heavy");
     for (var i=0; i<30; i++) {
       // only new locks!
-      var lock = mozSettings.createLock();
+      var lock = navigator.mozSettings.createLock();
       var obj = {};
       obj["wifi.enabled" + i] = true;
       req = lock.set( obj );
       req.onsuccess = function () {
         ok(true, "Set1 Done");
       };
       req.onerror = onFailure;
     };
     {
-      var lock2 = mozSettings.createLock();
+      var lock2 = navigator.mozSettings.createLock();
       req2 = lock2.get("*");
       req2.onsuccess = function () {
         is(Object.keys(req2.result).length, 32, "length 12");
         ok(true, JSON.stringify(req2.result));
         ok(true, "Get all settings Done");
       };
       req2.onerror = onFailure;
     }
-    var lock2 = mozSettings.createLock();
+    var lock2 = navigator.mozSettings.createLock();
     var obj = {};
     obj["wifi.enabled" + 30] = true;
     req3 = lock2.set( obj );
     req3.onsuccess = function () {
       ok(true, "Set12 Done");
     };
     req3.onerror = onFailure;
 
-    var lock3 = mozSettings.createLock();
+    var lock3 = navigator.mozSettings.createLock();
     // with one lock
     for (var i = 0; i < 30; i++) {
       req4 = lock3.get("wifi.enabled" + i);
       var testObj = {};
       testObj["wifi.enabled" + i] = true;
       req4.onsuccess = function () {
         check(this.request.result, this.testObj);
         ok(true, "Get1 Done");
       }.bind({testObj: testObj, request: req4});
       req4.onerror = onFailure;
     }
 
     ok(true, "start next2!");
-    var lock4 = mozSettings.createLock();
+    var lock4 = navigator.mozSettings.createLock();
     for (var i=0; i<30; i++) {
       var obj = {};
       obj["wifi.enabled" + i] = false;
       req4 = lock4.set( obj );
       req4.onsuccess = function () {
         ok(true, "Set2 Done");
       };
       req4.onerror = onFailure;
     }
-    var lock5 = mozSettings.createLock();
+    var lock5 = navigator.mozSettings.createLock();
     for (var i=0; i<30; i++) {
       req5 = lock5.get("wifi.enabled" + i);
       var testObj = {};
       testObj["wifi.enabled" + i] = false;
       req5.onsuccess = function () {
         check(this.request.result, this.testObj);
         ok(true, "Get2 Done");
       }.bind({testObj: testObj, request: req5});
       req5.onerror = onFailure;
     }
 
-    var lock6 = mozSettings.createLock();
+    var lock6 = navigator.mozSettings.createLock();
     req6 = lock6.clear();
     req6.onsuccess = function () {
       ok(true, "Deleted the database");
       next();
     };
     req6.onerror = onFailure;
   },
   function () {
     ok(true, "reverse Test locking");
-    var lock2 = mozSettings.createLock();
-    var lock = mozSettings.createLock();
+    var lock2 = navigator.mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
 
     req = lock.set(wifiEnabled);
     req.onsuccess = function () {
       ok(true, "Test Locking Done");
       next();
     };
     req.onerror = onFailure;
 
     req2 = lock2.set(wifiDisabled);
     req2.onsuccess = function () {
       ok(true, "Set Done");
     };
     req2.onerror = onFailure;
   },
   function () {
     ok(true, "Test locking result");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
 
     req = lock.get("wifi.enabled");
     req.onsuccess = function() {
       check(req.result, wifiEnabled);
       ok(true, "Test2 locking result done");
     }
     req.onerror = onFailure;
 
-    var lock2 = mozSettings.createLock();
+    var lock2 = navigator.mozSettings.createLock();
     req2 = lock2.clear();
     req2.onsuccess = function () {
       ok(true, "Deleted the database");
     };
     req2.onerror = onFailure;
 
-    var lock3 = mozSettings.createLock();
+    var lock3 = navigator.mozSettings.createLock();
     req3 = lock3.set(wifi);
     req3.onsuccess = function () {
       ok(true, "set done");
       next();
     }
     req3.onerror = onFailure;
 
   },
   function () {
     ok(true, "Get all settings");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("*");
     req.onsuccess = function () {
       is(Object.keys(req.result).length, 1, "length 1");
       check(wifi, req.result);
       ok(true, "Get all settings Done");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Get net3g.apn");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("net3g.apn");
     req.onsuccess = function () {
       is(Object.keys(req.result).length, 1, "length 1");
       check(wifi, req.result);
       ok(true, "Get net3g.apn Done");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Change wifi2");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(wifi2);
     req.onsuccess = function () {
       ok(true, "Set Done");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Get net3g.apn");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("net3g.apn");
     req.onsuccess = function () {
       is(Object.keys(req.result).length, 1, "length 1");
       check(wifi2, req.result);
       ok(true, "Get net3g.apn Done");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Add wifi.enabled");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(wifiEnabled);
     req.onsuccess = function () {
       ok(true, "Set Done");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Get Wifi Enabled");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("wifi.enabled");
     req.onsuccess = function () {
       is(Object.keys(req.result).length, 1, "length 1");
       check(wifiEnabled, req.result);
       ok(true, "Get wifi.enabledDone");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Get all");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("*");
     req.onsuccess = function () {
       is(Object.keys(req.result).length, 2, "length 2");
       check(wifiEnabled["wifi.enabled"], req.result["wifi.enabled"]);
       check(wifi2["net3g.apn"], req.result["net3g.apn"]);
       ok(true, "Get all Done");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Add wifiNetworks");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(wifiNetworks0);
     req.onsuccess = function () {
       ok(true, "Set Done");
     };
     req.onerror = onFailure;
 
     req2 = lock.set(wifiNetworks1);
     req2.onsuccess = function () {
       ok(true, "Set Done");
       next();
     };
     req2.onerror = onFailure;
   },
   function () {
     ok(true, "Get Wifi Networks");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("wifi.networks[0]");
     req.onsuccess = function () {
       is(Object.keys(req.result).length, 1, "length 1");
       check(wifiNetworks0, req.result);
       ok(true, "Get wifi.networks[0]");
       next();
     };
     req.onerror = onFailure;
   },
   function() {
     ok(true, "Clear DB, multiple locks");
-    var lock4 = mozSettings.createLock();
-    var lock3 = mozSettings.createLock();
-    var lock2 = mozSettings.createLock();
-    var lock = mozSettings.createLock();
-    var lock6 = mozSettings.createLock();
-    var lock7 = mozSettings.createLock();
+    var lock4 = navigator.mozSettings.createLock();
+    var lock3 = navigator.mozSettings.createLock();
+    var lock2 = navigator.mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
+    var lock6 = navigator.mozSettings.createLock();
+    var lock7 = navigator.mozSettings.createLock();
     req = lock.clear();
     req.onsuccess = function () {
       ok(true, "Deleted the database");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Add wifiNetworks");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(wifiNetworks0);
     req.onsuccess = function () {
       ok(true, "Set Done");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Test set after lock closed");
-    var lockx = mozSettings.createLock();
+    var lockx = navigator.mozSettings.createLock();
     var cb = function() {
       var reqx = null;
       try {
         reqx = lockx.set(wifiNetworks0);
         ok(false, "should have thrown");
       } catch (ex) {
         ok(reqx == null, "request is still null");
         ok(true, "Caught Exception");
         next();
       }
     }
     SimpleTest.executeSoon(cb);
   },
   function() {
     ok(true, "Clear DB");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.clear();
     req.onsuccess = function () {
       ok(true, "Deleted the database");
       next();
     };
     req.onerror = onFailure;
   },
   function() {
     ok(true, "Set with multiple arguments");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(combination);
     req.onsuccess = function () {
       ok(true, "Set Done");
       next();
     };
     req.onerror = onFailure;
   },
   function() {
     ok(true, "request argument from multiple set");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("screen.brightness");
     req.onsuccess = function () {
       check(req.result["screen.brightness"], 0.7, "get done");
       next();
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "Test closed attribute on a valid lock");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     is(lock.closed, false, "closed attribute is false on creation");
     req = lock.get("screen.brightness");
     req.onsuccess = function () {
       is(lock.closed, false, "closed attribute is false on success callback");
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Test closed attribute on invalid lock");
-    var lockx = mozSettings.createLock();
+    var lockx = navigator.mozSettings.createLock();
     var cb = function() {
       var reqx = null;
       try {
         reqx = lockx.set(wifiNetworks0);
         ok(false, "should have thrown");
       } catch (ex) {
         is(lockx.closed, true, "closed attribute is true");
         ok(true, "Caught Exception");
         next();
       }
     }
     SimpleTest.executeSoon(cb);
   },
   function() {
     ok(true, "Clear DB");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.clear();
     req.onsuccess = function () {
       ok(true, "Deleted the database");
       next();
     };
     req.onerror = onFailure;
   },
   function() {
     ok(true, "Set object value");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set({"setting-obj": {foo: {bar: 23}}});
     req.onsuccess = function() {
       req2 = lock.get("setting-obj");
       req2.onsuccess = function(event) {
         var result = event.target.result["setting-obj"];
         ok(result, "Got valid result");
         ok(typeof result == "object", "Result is object");
         ok("foo" in result && "bar" in result.foo, "Result has properties");
         ok(result.foo.bar == 23, "Result properties are set");
         next();
       };
     };
   },
   function() {
     ok(true, "Clear DB");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.clear();
     req.onsuccess = function () {
       ok(true, "Deleted the database");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Call success callback when transaction commits");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     lock.onsettingstransactionsuccess = function () {
       next();
     };
     req = lock.set({"setting-obj": {foo: {bar: 23}}});
     req.onsuccess = function() {
       req2 = lock.get("setting-obj");
       req2.onsuccess = function(event) {
         var result = event.target.result["setting-obj"];
@@ -784,17 +780,17 @@ var steps = [
         ok(typeof result == "object", "Result is object");
         ok("foo" in result && "bar" in result.foo, "Result has properties");
         ok(result.foo.bar == 23, "Result properties are set");
       };
     };
   },
   function() {
     ok(true, "Clear DB");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.clear();
     req.onsuccess = function () {
       ok(true, "Deleted the database");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
--- a/dom/settings/tests/test_settings_blobs.html
+++ b/dom/settings/tests/test_settings_blobs.html
@@ -16,20 +16,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript;version=1.7">
 
 "use strict";
 
-if (SpecialPowers.isMainProcess()) {
-  SpecialPowers.Cu.import("resource://gre/modules/SettingsRequestManager.jsm");
-}
-
+var url = SimpleTest.getTestFileURL("file_loadserver.js");
+var script = SpecialPowers.loadChromeScript(url);
 SpecialPowers.addPermission("settings-read", true, document);
 SpecialPowers.addPermission("settings-write", true, document);
 SpecialPowers.addPermission("settings-api-read", true, document);
 SpecialPowers.addPermission("settings-api-write", true, document);
 SpecialPowers.addPermission("settings-clear", true, document);
 
 function onUnwantedSuccess() {
   ok(false, "onUnwantedSuccess: shouldn't get here");
@@ -40,97 +38,96 @@ function onFailure() {
     if (s) {
       ok(false, "in on Failure! - " + s);
     } else {
       ok(false, "in on Failure!");
     }
   }
 }
 
-let mozSettings = window.navigator.mozSettings;
 let req;
 
 let storedBlob = new Blob(['12345'], {"type": "text/plain"});
 
 function checkBlob(blob) {
   try {
     let url = URL.createObjectURL(blob);
     ok(true, "Valid blob");
   } catch (e) {
     ok(false, "Valid blob");
   }
 }
 
 let steps = [
   function() {
-    let lock = mozSettings.createLock();
+    let lock = navigator.mozSettings.createLock();
     req = lock.clear();
     req.onsuccess = next;
     req.onerror = onFailure("Deleting database");
   },
   function() {
     function obs(e) {
       checkBlob(e.settingValue);
-      mozSettings.removeObserver("test1", obs);
+      navigator.mozSettings.removeObserver("test1", obs);
       next();
     }
-    mozSettings.addObserver("test1", obs);
+    navigator.mozSettings.addObserver("test1", obs);
     next();
   },
   function() {
     // next is called by the observer above
-    let req = mozSettings.createLock().set({"test1": storedBlob});
+    let req = navigator.mozSettings.createLock().set({"test1": storedBlob});
     req.onerror = onFailure("Saving blob");
   },
   function() {
-    let req = mozSettings.createLock().get("test1");
+    let req = navigator.mozSettings.createLock().get("test1");
     req.onsuccess = function(event) {
       checkBlob(event.target.result["test1"]);
       next();
     };
     req.onerror = onFailure("Getting blob");
   },
   function() {
-    let req = mozSettings.createLock().set({"test2": [1, 2, storedBlob, 4]});
+    let req = navigator.mozSettings.createLock().set({"test2": [1, 2, storedBlob, 4]});
     req.onsuccess = next;
     req.onerror = onFailure("Saving array");
   },
   function() {
-    let req = mozSettings.createLock().get("test2");
+    let req = navigator.mozSettings.createLock().get("test2");
     req.onsuccess = function(event) {
       let val = event.target.result["test2"];
       ok(Array.isArray(val), "Result is an array");
       ok(val[0] == 1 && val[1] == 2 && val[3] == 4, "Primitives are preserved");
       checkBlob(val[2]);
       next();
     };
     req.onerror = onFailure("Getting array");
   },
   function() {
-    let req = mozSettings.createLock().set({"test3": {foo: "bar", baz: {number: 1, arr: [storedBlob]}}});
+    let req = navigator.mozSettings.createLock().set({"test3": {foo: "bar", baz: {number: 1, arr: [storedBlob]}}});
     req.onsuccess = next();
     req.onerror = onFailure("Saving object");
   },
   function() {
-    let req = mozSettings.createLock().get("test3");
+    let req = navigator.mozSettings.createLock().get("test3");
     req.onsuccess = function(event) {
       let val = event.target.result["test3"];
       ok(typeof(val) == "object", "Result is an object");
       ok("foo" in val && typeof(val.foo) == "string", "String property preserved");
       ok("baz" in val && typeof(val.baz) == "object", "Object property preserved");
       let baz = val.baz;
       ok("number" in baz && baz.number == 1, "Primite inside object preserved");
       ok("arr" in baz && Array.isArray(baz.arr), "Array inside object is preserved");
       checkBlob(baz.arr[0]);
       next();
     };
     req.onerror = onFailure("Getting object");
   },
   function() {
-    let req = mozSettings.createLock().clear();
+    let req = navigator.mozSettings.createLock().clear();
     req.onsuccess = function() {
       next();
     };
     req.onerror = onFailure("Deleting database");
   },
   function () {
     ok(true, "all done!\n");
     SimpleTest.finish();
--- a/dom/settings/tests/test_settings_data_uris.html
+++ b/dom/settings/tests/test_settings_data_uris.html
@@ -16,20 +16,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript;version=1.7">
 
 "use strict";
 
-if (SpecialPowers.isMainProcess()) {
-  SpecialPowers.Cu.import("resource://gre/modules/SettingsRequestManager.jsm");
-}
-
+var url = SimpleTest.getTestFileURL("file_loadserver.js");
+var script = SpecialPowers.loadChromeScript(url);
 SpecialPowers.addPermission("settings-read", true, document);
 SpecialPowers.addPermission("settings-write", true, document);
 SpecialPowers.addPermission("settings-api-read", true, document);
 SpecialPowers.addPermission("settings-api-write", true, document);
 SpecialPowers.addPermission("settings-clear", true, document);
 
 function onUnwantedSuccess() {
   ok(false, "onUnwantedSuccess: shouldn't get here");
@@ -40,98 +38,97 @@ function onFailure() {
     if (s) {
       ok(false, "in on Failure! - " + s);
     } else {
       ok(false, "in on Failure!");
     }
   }
 }
 
-let mozSettings = window.navigator.mozSettings;
 let req;
 
 // A simple data URI that will be converted to a blob.
 let dataURI = "data:text/html;charset=utf-8,%3C!DOCTYPE html>%3Cbody style='background:black;";
 
 function checkBlob(blob) {
   try {
     let url = URL.createObjectURL(blob);
     ok(true, "Valid blob");
   } catch (e) {
     ok(false, "Valid blob");
   }
 }
 
 let steps = [
   function() {
-    let lock = mozSettings.createLock();
+    let lock = navigator.mozSettings.createLock();
     req = lock.clear();
     req.onsuccess = next;
     req.onerror = onFailure("Deleting database");
   },
   function() {
     function obs(e) {
       checkBlob(e.settingValue);
-      mozSettings.removeObserver("test1", obs);
+      navigator.mozSettings.removeObserver("test1", obs);
       next();
     }
-    mozSettings.addObserver("test1", obs);
+    navigator.mozSettings.addObserver("test1", obs);
     next();
   },
   function() {
     // next is called by the observer above
-    let req = mozSettings.createLock().set({"test1": dataURI});
+    let req = navigator.mozSettings.createLock().set({"test1": dataURI});
     req.onerror = onFailure("Saving blob");
   },
   function() {
-    let req = mozSettings.createLock().get("test1");
+    let req = navigator.mozSettings.createLock().get("test1");
     req.onsuccess = function(event) {
       checkBlob(event.target.result["test1"]);
       next();
     };
     req.onerror = onFailure("Getting blob");
   },
   function() {
-    let req = mozSettings.createLock().set({"test2": [1, 2, dataURI, 4]});
+    let req = navigator.mozSettings.createLock().set({"test2": [1, 2, dataURI, 4]});
     req.onsuccess = next;
     req.onerror = onFailure("Saving array");
   },
   function() {
-    let req = mozSettings.createLock().get("test2");
+    let req = navigator.mozSettings.createLock().get("test2");
     req.onsuccess = function(event) {
       let val = event.target.result["test2"];
       ok(Array.isArray(val), "Result is an array");
       ok(val[0] == 1 && val[1] == 2 && val[3] == 4, "Primitives are preserved");
       checkBlob(val[2]);
       next();
     };
     req.onerror = onFailure("Getting array");
   },
   function() {
-    let req = mozSettings.createLock().set({"test3": {foo: "bar", baz: {number: 1, arr: [dataURI]}}});
+    let req = navigator.mozSettings.createLock().set({"test3": {foo: "bar", baz: {number: 1, arr: [dataURI]}}});
     req.onsuccess = next();
     req.onerror = onFailure("Saving object");
   },
   function() {
-    let req = mozSettings.createLock().get("test3");
+    let req = navigator.mozSettings.createLock().get("test3");
     req.onsuccess = function(event) {
       let val = event.target.result["test3"];
       ok(typeof(val) == "object", "Result is an object");
       ok("foo" in val && typeof(val.foo) == "string", "String property preserved");
       ok("baz" in val && typeof(val.baz) == "object", "Object property preserved");
       let baz = val.baz;
       ok("number" in baz && baz.number == 1, "Primite inside object preserved");
       ok("arr" in baz && Array.isArray(baz.arr), "Array inside object is preserved");
       checkBlob(baz.arr[0]);
       next();
     };
     req.onerror = onFailure("Getting object");
   },
   function() {
-    let req = mozSettings.createLock().clear();
+    let req = navigator.mozSettings.createLock().clear();
     req.onsuccess = function() {
       next();
     };
     req.onerror = onFailure("Deleting database");
   },
   function () {
     ok(true, "all done!\n");
     SimpleTest.finish();
--- a/dom/settings/tests/test_settings_onsettingchange.html
+++ b/dom/settings/tests/test_settings_onsettingchange.html
@@ -16,20 +16,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 "use strict";
 
-if (SpecialPowers.isMainProcess()) {
-  SpecialPowers.Cu.import("resource://gre/modules/SettingsRequestManager.jsm");
-}
-
+var url = SimpleTest.getTestFileURL("file_loadserver.js");
+var script = SpecialPowers.loadChromeScript(url);
 SpecialPowers.addPermission("settings-write", true, document);
 SpecialPowers.addPermission("settings-read", true, document);
 SpecialPowers.addPermission("settings-api-read", true, document);
 SpecialPowers.addPermission("settings-api-write", true, document);
 SpecialPowers.addPermission("settings-clear", true, document);
 
 var screenBright = {"screen.brightness": 0.7};
 
@@ -78,213 +76,211 @@ function onComplexSettingschangeWithNext
   ok(Array.isArray(c), "c is array!");
   is(c[0]['d'], 'e', "Right settingValue!");
   next();
 };
 
 var req, req2;
 var index = 0;
 
-var mozSettings = window.navigator.mozSettings;
-
 var steps = [
   function () {
     ok(true, "Deleting database");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.clear();
     req.onsuccess = function () {
       ok(true, "Deleted the database");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req2 = lock.set(screenBright);
     req2.onsuccess = function () {
       ok(true, "set done");
       navigator.mozSettings.onsettingchange = onsettingschangeWithNext;
       next();
     }
     req2.onerror = onFailure;
   },
   function() {
     ok(true, "testing");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req2 = lock.set(screenBright);
     req2.onsuccess = function() {
       ok(true, "end adding onsettingchange");
     };
     req2.onerror = onFailure;
   },
   function() {
     ok(true, "test observers");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("screen.brightness");
     req.onsuccess = function () {
       ok(true, "get done");
       next();
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "adding Observers 1");
     navigator.mozSettings.addObserver("screen.brightness", observer1);
     navigator.mozSettings.addObserver("screen.brightness", observer1);
     navigator.mozSettings.addObserver("screen.brightness", observer2);
     navigator.mozSettings.addObserver("screen.brightness", observerOnlyCalledOnce);
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req2 = lock.get("screen.brightness");
     req2.onsuccess = function() {
       ok(true, "set observeSetting done!");
       next();
     };
     req2.onerror = onFailure;
   },
   function() {
     ok(true, "test observers");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set1 done");
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "test observers");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("screen.brightness");
     navigator.mozSettings.removeObserver("screen.brightness", observerOnlyCalledOnce);
     req.onsuccess = function () {
       ok(true, "set1 done");
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "removing Event Listener");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set2 done");
       navigator.mozSettings.removeObserver("screen.brightness", observer2);
       navigator.mozSettings.removeObserver("screen.brightness", observer1);
       navigator.mozSettings.removeObserver("screen.brightness", observer1);
     }
     req.onerror = onFailure;
   },
 
   function() {
     ok(true, "delete onsettingschange");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     navigator.mozSettings.onsettingchange = null;
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set0 done");
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Waiting for all set callbacks");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("screen.brightness");
     req.onsuccess = function() {
       ok(true, "Done");
       next();
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "adding Observers 1");
     navigator.mozSettings.addObserver("screen.brightness", observer1);
     navigator.mozSettings.addObserver("screen.brightness", observer1);
     navigator.mozSettings.addObserver("screen.brightness", observer2);
     navigator.mozSettings.addObserver("screen.brightness", observerWithNext);
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req2 = lock.get("screen.brightness");
     req2.onsuccess = function() {
       ok(true, "set observeSetting done!");
       next();
     };
     req2.onerror = onFailure;
   },
   function() {
     ok(true, "test observers");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set1 done");
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "removing Event Listener");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set2 done");
       navigator.mozSettings.removeObserver("screen.brightness", observer2);
       navigator.mozSettings.removeObserver("screen.brightness", observer1);
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "test Event Listener");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set3 done");
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "removing Event Listener");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     navigator.mozSettings.removeObserver("screen.brightness", observerWithNext);
     req = lock.set(screenBright);
     req.onsuccess = function () {
       ok(true, "set4 done");
       navigator.mozSettings.removeObserver("screen.brightness", observer2);
       navigator.mozSettings.removeObserver("screen.brightness", observer1);
       next();
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "removing Event Listener");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("screen.brightness");
     req.onsuccess = function () {
       ok(true, "get5 done");
       next();
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "Clear DB");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.clear();
     req.onsuccess = function () {
       ok(true, "Deleted the database");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Deleting database");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.clear();
     req.onsuccess = function () {
       ok(true, "Deleted the database");
       next();
     };
     req.onerror = onFailure;
   },
   function () {
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     navigator.mozSettings.onsettingchange = onComplexSettingschangeWithNext;
     req2 = navigator.mozSettings.createLock().set({'test.key': cset});
     req2.onsuccess = function () {
       ok(true, "set done");
     }
     req2.onerror = onFailure;
   },
   function () {
--- a/dom/settings/tests/test_settings_permissions.html
+++ b/dom/settings/tests/test_settings_permissions.html
@@ -16,20 +16,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 "use strict";
 
-if (SpecialPowers.isMainProcess()) {
-  SpecialPowers.Cu.import("resource://gre/modules/SettingsRequestManager.jsm");
-}
-
+var url = SimpleTest.getTestFileURL("file_loadserver.js");
+var script = SpecialPowers.loadChromeScript(url);
 SpecialPowers.removePermission("settings-read", document);
 SpecialPowers.removePermission("settings-write", document);
 SpecialPowers.addPermission("settings-api-read", true, document);
 SpecialPowers.addPermission("settings-api-write", true, document);
 SpecialPowers.addPermission("settings:wallpaper.image-read", true, document);
 SpecialPowers.addPermission("settings:wallpaper.image-write", true, document);
 SpecialPowers.addPermission("settings-clear", true, document);
 
@@ -75,73 +73,71 @@ function onsettingschangeWithNext(event)
 
 function check(o1, o2) {
   is(JSON.stringify(o1), JSON.stringify(o2), "same");
 }
 
 var req, req2, req3, req4, req5, req6;
 var index = 0;
 
-var mozSettings = navigator.mozSettings;
-
 var steps = [
   // Can't delete database here since that requires permissions we don't want
   // to give the page.
   function () {
     ok(true, "Setting wallpaper");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(wallpaper);
     req.onsuccess = function () {
       ok(true, "set done");
     }
     req.onerror = onFailure;
 
-    var lock2 = mozSettings.createLock();
+    var lock2 = navigator.mozSettings.createLock();
     req2 = lock2.get("wallpaper.image");
     req2.onsuccess = function () {
       is(Object.keys(req2.result).length, 1, "length 1");
       check(wallpaper, req2.result);
       ok(true, "Get wallpaper Done");
       next();
     };
     req2.onerror = onFailure;
   },
   function () {
     ok(true, "Get Wifi");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.get("wifi.enabled");
     req.onerror = function () {
       ok(true, "get failed (expected)");
       next();
     }
     req.onsuccess = onFailure;
   },
   function () {
     ok(true, "Set Wifi");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(wifi);
     req.onerror = function () {
       ok(true, "set failed (expected)");
       next();
     }
     req.onsuccess = onFailure;
   },
   function () {
     ok(true, "Set combination (1 valid 1 not valid)");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(combination);
     req.onerror = function () {
       ok(true, "set failed (expected)");
       next();
     }
     req.onsuccess = onFailure;
   },
   function () {
     ok(true, "All requests on a failed lock should fail");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     lock.onsettingstransactionfailure = function (evt) {
       ok(evt.error == "Lock failed a permissions check, all requests now failing.", "transaction failure on permissions error message correct.");
       ok(true, "transaction failed (expected) ");
       next();
     };
     lock.onsettingstransactionsuccess = onFailure;
 
     req = lock.set(wifi);
@@ -152,17 +148,17 @@ var steps = [
     req2 = lock.get("wallpaper.image");
     req2.onerror = function () {
       ok(true, "get failed (expected)");
     }
     req2.onsuccess = onFailure;
   },
   function () {
     ok(true, "Set combination (1 valid 1 not valid)");
-    var lock = mozSettings.createLock();
+    var lock = navigator.mozSettings.createLock();
     req = lock.set(combination);
     req.onerror = function () {
       ok(true, "set failed (expected)");
       next();
     }
     req.onsuccess = onFailure;
   },
   function () {
--- a/dom/system/gonk/RILSystemMessengerHelper.js
+++ b/dom/system/gonk/RILSystemMessengerHelper.js
@@ -68,16 +68,20 @@ RILSystemMessengerHelper.prototype = {
   },
 
   notifyCallEnded: function(aServiceId, aNumber, aCdmaWaitingNumber, aEmergency,
                             aDuration, aOutgoing, aHangUpLocal) {
     this.messenger.notifyCallEnded(aServiceId, aNumber, aCdmaWaitingNumber, aEmergency,
                                    aDuration, aOutgoing, aHangUpLocal);
   },
 
+  notifyUssdReceived: function(aServiceId, aMessage, aSessionEnded) {
+    this.messenger.notifyUssdReceived(aServiceId, aMessage, aSessionEnded);
+  },
+
   /**
    * nsISmsMessenger API
    */
   notifySms: function(aNotificationType, aId, aThreadId, aIccId, aDelivery,
                       aDeliveryStatus, aSender, aReceiver, aBody, aMessageClass,
                       aTimestamp, aSentTimestamp, aDeliveryTimestamp, aRead) {
     this.messenger.notifySms(aNotificationType, aId, aThreadId, aIccId, aDelivery,
                              aDeliveryStatus, aSender, aReceiver, aBody, aMessageClass,
@@ -95,20 +99,16 @@ RILSystemMessengerHelper.prototype = {
                                            aMessageId, aLanguage, aBody, aMessageClass,
                                            aTimestamp, aCdmaServiceCategory, aHasEtwsInfo,
                                            aEtwsWarningType, aEtwsEmergencyUserAlert, aEtwsPopup);
   },
 
   /**
    * nsIMobileConnectionMessenger API
    */
-  notifyUssdReceived: function(aServiceId, aMessage, aSessionEnded) {
-    this.messenger.notifyUssdReceived(aServiceId, aMessage, aSessionEnded);
-  },
-
   notifyCdmaInfoRecDisplay: function(aServiceId, aDisplay) {
     this.messenger.notifyCdmaInfoRecDisplay(aServiceId, aDisplay);
   },
 
   notifyCdmaInfoRecCalledPartyNumber: function(aServiceId, aType, aPlan,
                                                aNumber, aPi, aSi) {
     this.messenger.notifyCdmaInfoRecCalledPartyNumber(aServiceId, aType, aPlan,
                                                       aNumber, aPi, aSi);
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -1988,38 +1988,38 @@ RadioInterface.prototype = {
       }
     }
     return true;
   },
 
   matchMvno: function(target, message) {
     if (DEBUG) this.debug("matchMvno: " + JSON.stringify(message));
 
-    if (!message || !message.mvnoType || !message.mvnoData) {
+    if (!message || !message.mvnoData) {
       message.errorMsg = RIL.GECKO_ERROR_INVALID_PARAMETER;
     }
 
     if (!message.errorMsg) {
       switch (message.mvnoType) {
-        case "imsi":
+        case RIL.GECKO_CARDMVNO_TYPE_IMSI:
           if (!this.rilContext.imsi) {
             message.errorMsg = RIL.GECKO_ERROR_GENERIC_FAILURE;
             break;
           }
           message.result = this.isImsiMatches(message.mvnoData);
           break;
-        case "spn":
+        case RIL.GECKO_CARDMVNO_TYPE_SPN:
           let spn = this.rilContext.iccInfo && this.rilContext.iccInfo.spn;
           if (!spn) {
             message.errorMsg = RIL.GECKO_ERROR_GENERIC_FAILURE;
             break;
           }
           message.result = spn == message.mvnoData;
           break;
-        case "gid":
+        case RIL.GECKO_CARDMVNO_TYPE_GID:
           this.workerMessenger.send("getGID1", null, (function(response) {
             let gid = response.gid1;
             let mvnoDataLength = message.mvnoData.length;
 
             if (!gid) {
               message.errorMsg = RIL.GECKO_ERROR_GENERIC_FAILURE;
             } else if (mvnoDataLength > gid.length) {
               message.result = false;
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -2640,16 +2640,21 @@ GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOC
 GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_CCK] = ICC_SEL_CODE_PH_CORP_PIN;
 GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_SPCK] = ICC_SEL_CODE_PH_SP_PIN;
 
 // See nsIIccProvider::CARD_CONTACT_TYPE_*
 this.GECKO_CARDCONTACT_TYPE_ADN = 0;
 this.GECKO_CARDCONTACT_TYPE_FDN = 1;
 this.GECKO_CARDCONTACT_TYPE_SDN = 2;
 
+// See nsIIccProvider::CARD_MVNO_TYPE_*
+this.GECKO_CARDMVNO_TYPE_IMSI = 0;
+this.GECKO_CARDMVNO_TYPE_SPN = 1;
+this.GECKO_CARDMVNO_TYPE_GID = 2;
+
 // See ril.h RIL_PersoSubstate
 this.PERSONSUBSTATE = {};
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_UNKNOWN] = GECKO_CARDSTATE_UNKNOWN;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_IN_PROGRESS] = GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_READY] = GECKO_CARDSTATE_PERSONALIZATION_READY;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK] = GECKO_CARDSTATE_NETWORK_LOCKED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET] = GECKO_CARDSTATE_NETWORK_SUBSET_LOCKED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_CORPORATE] = GECKO_CARDSTATE_CORPORATE_LOCKED;
@@ -2994,16 +2999,20 @@ this.MMI_SC_IMEI = "06";
 
 // MMI called line presentation service codes
 this.MMI_SC_CLIP = "30";
 this.MMI_SC_CLIR = "31";
 
 // MMI call waiting service code
 this.MMI_SC_CALL_WAITING = "43";
 
+// MMI service code for registration new password as defined in TS 22.030 6.5.4
+this.MMI_SC_CHANGE_PASSWORD = "03";
+this.MMI_ZZ_BARRING_SERVICE = "330";
+
 // MMI call barring service codes
 this.MMI_SC_BAOC = "33";
 this.MMI_SC_BAOIC = "331";
 this.MMI_SC_BAOICxH = "332";
 this.MMI_SC_BAIC = "35";
 this.MMI_SC_BAICr = "351";
 this.MMI_SC_BA_ALL = "330";
 this.MMI_SC_BA_MO = "333";
@@ -3026,32 +3035,36 @@ this.MMI_KS_SC_CALL_FORWARDING = "scCall
 this.MMI_KS_SC_CLIP = "scClip";
 this.MMI_KS_SC_CLIR = "scClir";
 this.MMI_KS_SC_PWD = "scPwd";
 this.MMI_KS_SC_CALL_WAITING = "scCallWaiting";
 this.MMI_KS_SC_PIN = "scPin";
 this.MMI_KS_SC_PIN2 = "scPin2";
 this.MMI_KS_SC_PUK = "scPuk";
 this.MMI_KS_SC_PUK2 = "scPuk2";
+this.MMI_KS_SC_CHANGE_PASSWORD = "scChangePassword"
 this.MMI_KS_SC_IMEI = "scImei";
 this.MMI_KS_SC_USSD = "scUssd";
 this.MMI_KS_SC_CALL = "scCall";
 
 // MMI error messages key strings.
 this.MMI_ERROR_KS_ERROR = "emMmiError";
 this.MMI_ERROR_KS_NOT_SUPPORTED = "emMmiErrorNotSupported";
 this.MMI_ERROR_KS_INVALID_ACTION = "emMmiErrorInvalidAction";
 this.MMI_ERROR_KS_MISMATCH_PIN = "emMmiErrorMismatchPin";
+this.MMI_ERROR_KS_MISMATCH_PASSWORD = "emMmiErrorMismatchPassword";
 this.MMI_ERROR_KS_BAD_PIN = "emMmiErrorBadPin";
 this.MMI_ERROR_KS_BAD_PUK = "emMmiErrorBadPuk";
 this.MMI_ERROR_KS_INVALID_PIN = "emMmiErrorInvalidPin";
+this.MMI_ERROR_KS_INVALID_PASSWORD = "emMmiErrorInvalidPassword";
 this.MMI_ERROR_KS_NEEDS_PUK = "emMmiErrorNeedsPuk";
 this.MMI_ERROR_KS_SIM_BLOCKED = "emMmiErrorSimBlocked";
 
 // MMI status message.
+this.MMI_SM_KS_PASSWORD_CHANGED = "smPasswordChanged";
 this.MMI_SM_KS_PIN_CHANGED = "smPinChanged";
 this.MMI_SM_KS_PIN2_CHANGED = "smPin2Changed";
 this.MMI_SM_KS_PIN_UNBLOCKED = "smPinUnblocked";
 this.MMI_SM_KS_PIN2_UNBLOCKED = "smPin2Unblocked";
 this.MMI_SM_KS_SERVICE_ENABLED = "smServiceEnabled";
 this.MMI_SM_KS_SERVICE_ENABLED_FOR = "smServiceEnabledFor";
 this.MMI_SM_KS_SERVICE_DISABLED = "smServiceDisabled";
 this.MMI_SM_KS_SERVICE_REGISTERED = "smServiceRegistered";
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -2404,16 +2404,43 @@ RilObject.prototype = {
       if (mmi.sib != mmi.sic) {
         _sendMMIError(MMI_ERROR_KS_MISMATCH_PIN);
         return false;
       }
 
       return true;
     }
 
+    function _isValidChangePasswordRequest() {
+      if (mmi.procedure !== MMI_PROCEDURE_REGISTRATION &&
+          mmi.procedure !== MMI_PROCEDURE_ACTIVATION) {
+        _sendMMIError(MMI_ERROR_KS_INVALID_ACTION);
+        return false;
+      }
+
+      if (mmi.sia !== "" && mmi.sia !== MMI_ZZ_BARRING_SERVICE) {
+        _sendMMIError(MMI_ERROR_KS_NOT_SUPPORTED);
+        return false;
+      }
+
+      let validPassword = si => /^[0-9]{4}$/.test(si);
+      if (!validPassword(mmi.sib) || !validPassword(mmi.sic) ||
+          !validPassword(mmi.pwd)) {
+        _sendMMIError(MMI_ERROR_KS_INVALID_PASSWORD);
+        return false;
+      }
+
+      if (mmi.sic != mmi.pwd) {
+        _sendMMIError(MMI_ERROR_KS_MISMATCH_PASSWORD);
+        return false;
+      }
+
+      return true;
+    }
+
     let _isRadioAvailable = (function() {
       if (this.radioState !== GECKO_RADIOSTATE_ENABLED) {
         _sendMMIError(GECKO_ERROR_RADIO_NOT_AVAILABLE);
         return false;
       }
       return true;
     }).bind(this);
 
@@ -2551,16 +2578,27 @@ RilObject.prototype = {
           default:
             _sendMMIError(MMI_ERROR_KS_NOT_SUPPORTED);
             return;
         }
         options.isSetCLIR = true;
         this.setCLIR(options);
         return;
 
+      // Change call barring password
+      case MMI_SC_CHANGE_PASSWORD:
+        if (!_isRadioAvailable() || !_isValidChangePasswordRequest()) {
+          return;
+        }
+
+        options.pin = mmi.sib;
+        options.newPin = mmi.sic;
+        this.changeCallBarringPassword(options);
+        return;
+
       // Call barring
       case MMI_SC_BAOC:
       case MMI_SC_BAOIC:
       case MMI_SC_BAOICxH:
       case MMI_SC_BAIC:
       case MMI_SC_BAICr:
       case MMI_SC_BA_ALL:
       case MMI_SC_BA_MO:
@@ -2612,17 +2650,17 @@ RilObject.prototype = {
 
     // If the MMI code is not a known code, it is treated as an ussd.
     if (!_isRadioAvailable()) {
       return;
     }
 
     options.ussd = mmi.fullMMI;
 
-    if (options.startNewSession && this._ussdSession) {
+    if (this._ussdSession) {
       if (DEBUG) this.context.debug("Cancel existing ussd session.");
       this.cachedUSSDRequest = options;
       this.cancelUSSD({});
       return;
     }
 
     this.sendUSSD(options);
   },
@@ -5981,16 +6019,23 @@ RilObject.prototype[REQUEST_SET_FACILITY
   }
   this.sendChromeMessage(options);
 };
 RilObject.prototype[REQUEST_CHANGE_BARRING_PASSWORD] =
   function REQUEST_CHANGE_BARRING_PASSWORD(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
+
+  if (options.rilMessageType != "sendMMI") {
+    this.sendChromeMessage(options);
+    return;
+  }
+
+  options.statusMessage = MMI_SM_KS_PASSWORD_CHANGED;
   this.sendChromeMessage(options);
 };
 RilObject.prototype[REQUEST_SIM_OPEN_CHANNEL] = function REQUEST_SIM_OPEN_CHANNEL(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
--- a/dom/telephony/gonk/TelephonyService.js
+++ b/dom/telephony/gonk/TelephonyService.js
@@ -561,17 +561,17 @@ TelephonyService.prototype = {
                          isDialEmergency: aIsDialEmergency }, aCallback);
       } else {
         // Reject MMI code from dialEmergency api.
         if (aIsDialEmergency) {
           aCallback.notifyError(DIAL_ERROR_BAD_NUMBER);
           return;
         }
 
-        this._dialMMI(aClientId, mmi, aCallback, true);
+        this._dialMMI(aClientId, mmi, aCallback);
       }
     }
   },
 
   /**
    * @param aOptions.number
    * @param aOptions.clirMode (optional)
    * @param aOptions.isDialEmergency
@@ -659,25 +659,24 @@ TelephonyService.prototype = {
    *        Client id.
    * @param aMmi
    *        Parsed MMI structure.
    * @param aCallback
    *        A nsITelephonyDialCallback object.
    * @param aStartNewSession
    *        True to start a new session for ussd request.
    */
-  _dialMMI: function(aClientId, aMmi, aCallback, aStartNewSession) {
+  _dialMMI: function(aClientId, aMmi, aCallback) {
     let mmiServiceCode = aMmi ?
       this._serviceCodeToKeyString(aMmi.serviceCode) : RIL.MMI_KS_SC_USSD;
 
     aCallback.notifyDialMMI(mmiServiceCode);
 
     this._sendToRilWorker(aClientId, "sendMMI",
-                          { mmi: aMmi,
-                            startNewSession: aStartNewSession }, response => {
+                          { mmi: aMmi }, response => {
       if (DEBUG) debug("MMI response: " + JSON.stringify(response));
 
       if (!response.success) {
         if (response.additionalInformation != null) {
           aCallback.notifyDialMMIErrorWithInfo(response.errorMsg,
                                                response.additionalInformation);
         } else {
           aCallback.notifyDialMMIError(response.errorMsg);
@@ -902,16 +901,18 @@ TelephonyService.prototype = {
       case RIL.MMI_SC_BAIC:
       case RIL.MMI_SC_BAICr:
       case RIL.MMI_SC_BA_ALL:
       case RIL.MMI_SC_BA_MO:
       case RIL.MMI_SC_BA_MT:
         return RIL.MMI_KS_SC_CALL_BARRING;
       case RIL.MMI_SC_CALL_WAITING:
         return RIL.MMI_KS_SC_CALL_WAITING;
+      case RIL.MMI_SC_CHANGE_PASSWORD:
+        return RIL.MMI_KS_SC_CHANGE_PASSWORD;
       default:
         return RIL.MMI_KS_SC_USSD;
     }
   },
 
   hangUp: function(aClientId, aCallIndex) {
     let parentId = this._currentCalls[aClientId][aCallIndex].parentId;
     if (parentId) {
@@ -1297,23 +1298,17 @@ TelephonyService.prototype = {
   },
 
   notifyUssdReceived: function(aClientId, aMessage, aSessionEnded) {
     if (DEBUG) {
       debug("notifyUssdReceived for " + aClientId + ": " +
             aMessage + " (sessionEnded : " + aSessionEnded + ")");
     }
 
-    gGonkMobileConnectionService.notifyUssdReceived(aClientId, aMessage,
-                                                    aSessionEnded);
-  },
-
-  dialMMI: function(aClientId, aMmiString, aCallback) {
-    let mmi = this._parseMMI(aMmiString, this._hasCalls(aClientId));
-    this._dialMMI(aClientId, mmi, aCallback, false);
+    gTelephonyMessenger.notifyUssdReceived(aClientId, aMessage, aSessionEnded);
   },
 
   /**
    * nsIObserver interface.
    */
 
   observe: function(aSubject, aTopic, aData) {
     switch (aTopic) {
@@ -1350,17 +1345,16 @@ USSDReceivedWrapper.prototype = {
     if (DEBUG) debug("wrapMessage: " + JSON.stringify(aMessage));
 
     let session = aMessage.sessionEnded ? null :
       new aWindow.USSDSession(aMessage.serviceId);
 
     let event = new aWindow.USSDReceivedEvent("ussdreceived", {
       serviceId: aMessage.serviceId,
       message: aMessage.message,
-      sessionEnded: aMessage.sessionEnded,
       session: session
     });
 
     return event;
   },
 
   classDescription: "USSDReceivedWrapper",
   classID: Components.ID("{d03684ed-ede4-4210-8206-f4f32772d9f5}"),
--- a/dom/telephony/nsIGonkTelephonyService.idl
+++ b/dom/telephony/nsIGonkTelephonyService.idl
@@ -5,17 +5,17 @@
 
 #include "nsITelephonyService.idl"
 
 %{C++
 #define GONK_TELEPHONY_SERVICE_CONTRACTID \
         "@mozilla.org/telephony/gonktelephonyservice;1"
 %}
 
-[scriptable, uuid(068d7bf2-1773-48ef-95f8-bd835115fed7)]
+[scriptable, uuid(cbbe66d8-865b-11e4-94f1-ab441e55905b)]
 interface nsIGonkTelephonyService : nsITelephonyService
 {
   void notifyAudioStateChanged(in unsigned long clientId, in short state);
 
   void notifyCallDisconnected(in unsigned long clientId, in jsval call);
 
   void notifyCallRing();
 
@@ -26,12 +26,9 @@ interface nsIGonkTelephonyService : nsIT
 
   void notifySupplementaryService(in unsigned long clientId, in long callIndex,
                                   in AString notification);
 
   void notifyConferenceCallStateChanged(in short state);
 
   void notifyUssdReceived(in unsigned long clientId, in DOMString message,
                           in boolean sessionEnded);
-
-  void dialMMI(in unsigned long clientId, in AString mmiString,
-               in nsITelephonyDialCallback callback);
 };
--- a/dom/telephony/nsITelephonyMessenger.idl
+++ b/dom/telephony/nsITelephonyMessenger.idl
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-[scriptable, uuid(998a48b2-5b54-11e4-833e-6b17c1427d49)]
+[scriptable, uuid(84045b7e-84fb-11e4-a94c-5ba58d0d5932)]
 interface nsITelephonyMessenger : nsISupports
 {
   /**
    * To broadcast 'telephony-new-call' system message
    */
   void notifyNewCall();
 
   /**
@@ -32,9 +32,23 @@ interface nsITelephonyMessenger : nsISup
    */
   void notifyCallEnded(in unsigned long aServiceId,
                        in DOMString aNumber,
                        in DOMString aCdmaWaitingNumber,
                        in boolean aEmergency,
                        in unsigned long aDuration,
                        in boolean aOutgoing,
                        in boolean aHangUpLocal);
+
+  /**
+   * 'ussd-received' system message
+   *
+   * @param aServiceId
+   *        The ID of Service where this info is notified from.
+   * @param aMessage
+   *        USSD Message to be displayed.
+   * @param aSessionEnded
+   *        True if USSD session is ended.
+   */
+  void notifyUssdReceived(in unsigned long aServiceId,
+                          in DOMString aMessage,
+                          in boolean aSessionEnded);
 };
\ No newline at end of file
--- a/dom/telephony/test/marionette/manifest.ini
+++ b/dom/telephony/test/marionette/manifest.ini
@@ -28,16 +28,17 @@ qemu = true
 [test_incoming_already_connected.js]
 [test_incoming_already_held.js]
 [test_incoming_answer_hangup_oncallschanged.js]
 [test_incoming_basic_operations.js]
 [test_incoming_connecting_hangup.js]
 [test_incoming_onstatechange.js]
 [test_mmi.js]
 [test_mmi_call_forwarding.js]
+[test_mmi_change_barring_password.js]
 [test_mmi_change_pin.js]
 [test_mmi_unlock_puk.js]
 [test_multiple_hold.js]
 [test_outgoing_already_held.js]
 [test_outgoing_answer_hangup_oncallschanged.js]
 [test_outgoing_answer_radio_off.js]
 [test_outgoing_auto_hold.js]
 [test_outgoing_badNumber.js]
new file mode 100644
--- /dev/null
+++ b/dom/telephony/test/marionette/test_mmi_change_barring_password.js
@@ -0,0 +1,99 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = "head.js";
+
+const TEST_DATA = [
+  // Test passing no password.
+  {
+    password: "",
+    newPassword: "0000",
+    newPasswordAgain: "1111",
+    expectedError: {
+      name: "emMmiErrorInvalidPassword"
+    }
+  },
+  // Test passing no newPassword.
+  {
+    password: "0000",
+    newPassword: "",
+    newPasswordAgain: "",
+    expectedError: {
+      name: "emMmiErrorInvalidPassword"
+    }
+  },
+  // Test passing mismatched newPassword.
+  {
+    password: "0000",
+    newPassword: "0000",
+    newPasswordAgain: "1111",
+    expectedError: {
+      name: "emMmiErrorMismatchPassword"
+    }
+  },
+  // Test passing invalid password (not 4 digits).
+  {
+    password: "000",
+    newPassword: "0000",
+    newPasswordAgain: "0000",
+    expectedError: {
+      name: "emMmiErrorInvalidPassword"
+    }
+  },
+  // TODO: Bug 906603 - B2G RIL: Support Change Call Barring Password on Emulator.
+  // Currently emulator doesn't support REQUEST_CHANGE_BARRING_PASSWORD, so we
+  // expect to get a 'RequestNotSupported' error here.
+  {
+    password: "0000",
+    newPassword: "1234",
+    newPasswordAgain: "1234",
+    expectedError: {
+      name: "RequestNotSupported"
+    }
+  }
+];
+
+let MMI_PREFIX = [
+  "*03*330*",
+  "**03*330*",
+  "*03**",
+  "**03**",
+];
+
+function testChangeCallBarringPassword(aMMIPrefix, aPassword, aNewPassword,
+                                       aNewPasswordAgain, aExpectedError) {
+  let MMI_CODE = aMMIPrefix + aPassword + "*" + aNewPassword + "*" + aNewPasswordAgain + "#";
+  log("Test " + MMI_CODE);
+
+  return gSendMMI(MMI_CODE).then(aResult => {
+    is(aResult.success, !aExpectedError, "check success");
+    is(aResult.serviceCode, "scChangePassword", "Check service code");
+
+    if (aResult.success) {
+      is(aResult.statusMessage, "smPasswordChanged", "Check status message");
+    } else {
+      is(aResult.statusMessage, aExpectedError.name, "Check name");
+    }
+  });
+}
+
+// Start test
+startTest(function() {
+  let promise = Promise.resolve();
+
+  for (let prefix of MMI_PREFIX) {
+    for (let i = 0; i < TEST_DATA.length; i++) {
+      let data = TEST_DATA[i];
+      promise = promise.then(() => testChangeCallBarringPassword(prefix,
+                                                                 data.password,
+                                                                 data.newPassword,
+                                                                 data.newPasswordAgain,
+                                                                 data.expectedError));
+    }
+  }
+
+  return promise
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
+});
--- a/dom/webidl/HTMLMenuElement.webidl
+++ b/dom/webidl/HTMLMenuElement.webidl
@@ -35,21 +35,21 @@ partial interface HTMLMenuElement {
    * The event is not cancelable and does not bubble.
    * See http://www.whatwg.org/specs/web-apps/current-work/multipage/interactive-elements.html#context-menus
    */
   [ChromeOnly]
   void sendShowEvent();
 
   /**
    * Creates a native menu builder. The builder type is dependent on menu type.
-   * Currently, it returns nsXULContextMenuBuilder for context menus.
-   * Toolbar menus are not yet supported (the method returns null).
+   * Currently, it returns the @mozilla.org/content/html-menu-builder;1
+   * component. Toolbar menus are not yet supported (the method returns null).
    */
   [ChromeOnly]
-  MenuBuilder createBuilder();
+  MenuBuilder? createBuilder();
 
   /*
    * Builds a menu by iterating over menu children.
    * See http://www.whatwg.org/specs/web-apps/current-work/multipage/interactive-elements.html#building-menus-and-toolbars
    * The caller can use a native builder by calling createBuilder() or provide
    * a custom builder that implements the nsIMenuBuilder interface.
    * A custom builder can be used for example to build native context menus
    * that are not defined using <menupopup>.
--- a/dom/webidl/MozIcc.webidl
+++ b/dom/webidl/MozIcc.webidl
@@ -77,16 +77,23 @@ enum IccLockType
 
 enum IccContactType
 {
   "adn", // Abbreviated Dialling Number.
   "fdn", // Fixed Dialling Number.
   "sdn"  // Service Dialling Number.
 };
 
+enum IccMvnoType
+{
+  "imsi",
+  "spn",
+  "gid"
+};
+
 dictionary IccUnlockCardLockOptions
 {
   required IccLockType lockType;
 
   DOMString? pin = null; // Necessary for lock types: "pin", "pin2", "nck",
                          // "nck1", "nck2", "hnck", "cck", "spck", "rcck",
                          // "rspck".
 
@@ -310,22 +317,18 @@ interface MozIcc : EventTarget
   // Integrated Circuit Card Helpers.
 
   /**
    * Verify whether the passed data (matchData) matches with some ICC's field
    * according to the mvno type (mvnoType).
    *
    * @param mvnoType
    *        Mvno type to use to compare the match data.
-   *        Currently, we only support 'imsi'.
    * @param matchData
    *        Data to be compared with ICC's field.
    *
    * @return a DOMRequest.
    *         The request's result will be a boolean indicating the matching
    *         result.
-   *
-   * TODO: change param mvnoType to WebIDL enum after Bug 864489 -
-   *       B2G RIL: use ipdl as IPC in MozIccManager
    */
   [Throws]
-  DOMRequest matchMvno(DOMString mvnoType, DOMString matchData);
+  DOMRequest matchMvno(IccMvnoType mvnoType, DOMString matchData);
 };
--- a/dom/webidl/MozMobileConnection.webidl
+++ b/dom/webidl/MozMobileConnection.webidl
@@ -259,59 +259,16 @@ interface MozMobileConnection : EventTar
    * Otherwise, the request's onerror will be called, and the request's error
    * will be either 'RadioNotAvailable', 'RequestNotSupported',
    * 'IllegalSIMorME', or 'GenericFailure'.
    */
   [Throws, CheckPermissions="mobileconnection"]
   DOMRequest getVoicePrivacyMode();
 
   /**
-   * Send a MMI message.
-   *
-   * @param mmi
-   *        DOMString containing an MMI string that can be associated to a
-   *        USSD request or other RIL functionality.
-   *
-   * @return a DOMRequest.
-   *
-   * If successful, the request's onsuccess will be called. And the request's
-   * result will be an object containing information about the operation.
-   * @see MozMMIResult for the detail of result.
-   *
-   * Otherwise, the request's onerror will be called, and the request's error
-   * will be a DOMMMIError.
-   * @see DOMMMIError for the detail of error.
-   *
-   * Note: In case that the MMI code requires sending an USSD request, the
-   * DOMrequest 'success' event means that the RIL has successfully processed
-   * and sent the USSD request to the network. The network reply will be
-   * reported via 'onussdreceived' event. If the MMI code is not associated to
-   * a USSD but to other RIL request its result, if one is needed, will be
-   * notified via the returned DOMRequest 'success' or 'error' event.
-   */
-  [Throws, CheckPermissions="mobileconnection"]
-  DOMRequest sendMMI(DOMString mmi);
-
-  /**
-   * Cancel the current MMI request if one exists.
-   *
-   * @return a DOMRequest.
-   *
-   * If successful, the request's onsuccess will be called. And the request's
-   * result will be an object containing information about the operation.
-   * @see MozMMIResult for the detail of result.
-   *
-   * Otherwise, the request's onerror will be called, and the request's error
-   * will be a DOMMMIError.
-   * @see DOMMMIError for the detail of error.
-   */
-  [Throws, CheckPermissions="mobileconnection"]
-  DOMRequest cancelMMI();
-
-  /**
    * Configures call forward options.
    *
    * @param options
    *        An object containing the call forward rule to set.
    * @see MozCallForwardingOptions for the detail of options.
    *
    * @return a DOMRequest
    *
@@ -518,22 +475,16 @@ interface MozMobileConnection : EventTar
 
   /**
    * The 'datachange' event is notified whenever the data connection object
    * changes values.
    */
   attribute EventHandler ondatachange;
 
   /**
-   * The 'ussdreceived' event is notified whenever a new USSD message is
-   * received.
-   */
-  attribute EventHandler onussdreceived;
-
-  /**
    * The 'dataerror' event is notified whenever the data connection object
    * receives an error from the RIL.
    */
   attribute EventHandler ondataerror;
 
   /**
    * The 'oncfstatechange' event is notified whenever the call forwarding
    * state changes.
--- a/dom/webidl/USSDReceivedEvent.webidl
+++ b/dom/webidl/USSDReceivedEvent.webidl
@@ -1,25 +1,23 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
 [Pref="dom.telephony.enabled",
- CheckPermissions="telephony mobileconnection",
+ CheckPermissions="telephony",
  AvailableIn="CertifiedApps",
  Constructor(DOMString type, optional USSDReceivedEventInit eventInitDict)]
 interface USSDReceivedEvent : Event
 {
   readonly attribute unsigned long serviceId;
   readonly attribute DOMString? message;
   readonly attribute USSDSession? session;  // null if session is ended.
-  readonly attribute boolean sessionEnded;  // deprecated. Bug 1070831
 };
 
 dictionary USSDReceivedEventInit : EventInit
 {
   unsigned long serviceId = 0;
   DOMString? message = null;
   USSDSession? session = null;
-  boolean sessionEnded = false;
 };
--- a/dom/xul/moz.build
+++ b/dom/xul/moz.build
@@ -7,28 +7,26 @@
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
 if CONFIG['MOZ_XUL']:
     DIRS += ['templates']
 
     XPIDL_SOURCES += [
-        'nsIXULContextMenuBuilder.idl',
         'nsIXULOverlayProvider.idl',
     ]
 
     EXPORTS += [
         'nsIXULDocument.h',
     ]
 
     UNIFIED_SOURCES += [
         'nsXULCommandDispatcher.cpp',
         'nsXULContentSink.cpp',
-        'nsXULContextMenuBuilder.cpp',
         'nsXULElement.cpp',
         'nsXULPopupListener.cpp',
         'nsXULPrototypeCache.cpp',
         'nsXULPrototypeDocument.cpp',
         'XULDocument.cpp',
     ]
 
 XPIDL_SOURCES += [
deleted file mode 100644
--- a/dom/xul/nsIXULContextMenuBuilder.idl
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIDOMDocumentFragment;
-
-/**
- * An interface for initialization of XUL context menu builder
- * and for triggering of menuitem actions with assigned identifiers.
- */
-
-[scriptable, uuid(eb6b42c0-2f1c-4760-b5ca-bdc9b3ec77d4)]
-interface nsIXULContextMenuBuilder : nsISupports
-{
-
-  /**
-   * Initialize builder before building.
-   *
-   * @param aDocumentFragment the fragment that will be used to append top
-   *        level elements
-   *
-   * @param aGeneratedItemIdAttrName the name of the attribute that will be
-   *        used to mark elements as generated and for menuitem identification
-   */
-  void init(in nsIDOMDocumentFragment aDocumentFragment,
-            in AString aGeneratedItemIdAttrName);
-
-  /**
-   * Invoke the action of the menuitem with assigned id aGeneratedItemId.
-   *
-   * @param aGeneratedItemId the menuitem id
-   */
-  void click(in DOMString aGeneratedItemId);
-
-};
deleted file mode 100644
--- a/dom/xul/nsXULContextMenuBuilder.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/* -*- 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 "nsContentCreatorFunctions.h"
-#include "nsIContent.h"
-#include "nsIDOMDocumentFragment.h"
-#include "nsIDOMHTMLElement.h"
-#include "nsIDOMHTMLMenuItemElement.h"
-#include "nsXULContextMenuBuilder.h"
-#include "nsIDocument.h"
-#include "mozilla/dom/Element.h"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-nsXULContextMenuBuilder::nsXULContextMenuBuilder()
-  : mCurrentGeneratedItemId(0)
-{
-}
-
-nsXULContextMenuBuilder::~nsXULContextMenuBuilder()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION(nsXULContextMenuBuilder, mFragment, mDocument,
-                         mCurrentNode, mElements)
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULContextMenuBuilder)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULContextMenuBuilder)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULContextMenuBuilder)
-  NS_INTERFACE_MAP_ENTRY(nsIMenuBuilder)
-  NS_INTERFACE_MAP_ENTRY(nsIXULContextMenuBuilder)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMenuBuilder)
-NS_INTERFACE_MAP_END
-
-
-NS_IMETHODIMP
-nsXULContextMenuBuilder::OpenContainer(const nsAString& aLabel)
-{
-  if (!mFragment) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  if (!mCurrentNode) {
-    mCurrentNode = mFragment;
-  } else {
-    nsCOMPtr<Element> menu;
-    nsresult rv = CreateElement(nsGkAtoms::menu, nullptr, getter_AddRefs(menu));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    menu->SetAttr(kNameSpaceID_None, nsGkAtoms::label, aLabel, false);
-
-    nsCOMPtr<Element> menuPopup;
-    rv = CreateElement(nsGkAtoms::menupopup, nullptr,
-                       getter_AddRefs(menuPopup));
-    NS_ENSURE_SUCCESS(rv, rv);
-        
-    rv = menu->AppendChildTo(menuPopup, false);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = mCurrentNode->AppendChildTo(menu, false);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    mCurrentNode = menuPopup;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULContextMenuBuilder::AddItemFor(nsIDOMHTMLMenuItemElement* aElement,
-                                    bool aCanLoadIcon)
-{
-  if (!mFragment) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  nsCOMPtr<Element> menuitem;
-  nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(aElement);
-  nsresult rv = CreateElement(nsGkAtoms::menuitem, element,
-                              getter_AddRefs(menuitem));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsAutoString type;
-  aElement->GetType(type);
-  if (type.EqualsLiteral("checkbox") || type.EqualsLiteral("radio")) {
-    // The menu is only temporary, so we don't need to handle
-    // the radio type precisely.
-    menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
-                      NS_LITERAL_STRING("checkbox"), false);
-    bool checked;
-    aElement->GetChecked(&checked);
-    if (checked) {
-      menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::checked,
-                        NS_LITERAL_STRING("true"), false);
-    }
-  }
-
-  nsAutoString label;
-  aElement->GetLabel(label);
-  menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::label, label, false);
-
-  nsAutoString icon;
-  aElement->GetIcon(icon);
-  if (!icon.IsEmpty()) {
-    menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
-                      NS_LITERAL_STRING("menuitem-iconic"), false);
-    if (aCanLoadIcon) {
-      menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::image, icon, false);
-    }
-  }
-
-  bool disabled;
-  aElement->GetDisabled(&disabled);
-  if (disabled) {
-    menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled,
-                      NS_LITERAL_STRING("true"), false);
-  }
-
-  return mCurrentNode->AppendChildTo(menuitem, false);
-}
-
-NS_IMETHODIMP
-nsXULContextMenuBuilder::AddSeparator()
-{
-  if (!mFragment) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  nsCOMPtr<Element> menuseparator;
-  nsresult rv = CreateElement(nsGkAtoms::menuseparator, nullptr,
-                              getter_AddRefs(menuseparator));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return mCurrentNode->AppendChildTo(menuseparator, false);
-}
-
-NS_IMETHODIMP
-nsXULContextMenuBuilder::UndoAddSeparator()
-{
-  if (!mFragment) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  uint32_t count = mCurrentNode->GetChildCount();
-  if (!count ||
-      mCurrentNode->GetChildAt(count - 1)->Tag() != nsGkAtoms::menuseparator) {
-    return NS_OK;
-  }
-
-  mCurrentNode->RemoveChildAt(count - 1, false);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULContextMenuBuilder::CloseContainer()
-{
-  if (!mFragment) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  if (mCurrentNode == mFragment) {
-    mCurrentNode = nullptr;
-  } else {
-    nsIContent* parent = mCurrentNode->GetParent();
-    mCurrentNode = parent->GetParent();
-  }
-
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsXULContextMenuBuilder::Init(nsIDOMDocumentFragment* aDocumentFragment,
-                              const nsAString& aGeneratedItemIdAttrName)
-{
-  NS_ENSURE_ARG_POINTER(aDocumentFragment);
-
-  mFragment = do_QueryInterface(aDocumentFragment);
-  mDocument = mFragment->GetOwnerDocument();
-  mGeneratedItemIdAttr = do_GetAtom(aGeneratedItemIdAttrName);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULContextMenuBuilder::Click(const nsAString& aGeneratedItemId)
-{
-  nsresult rv;
-  int32_t idx = nsString(aGeneratedItemId).ToInteger(&rv);
-  if (NS_SUCCEEDED(rv)) {
-    nsCOMPtr<nsIDOMHTMLElement> element = mElements.SafeObjectAt(idx);
-    if (element) {
-      element->DOMClick();
-    }
-  }
-
-  return NS_OK;
-}
-
-nsresult
-nsXULContextMenuBuilder::CreateElement(nsIAtom* aTag,
-                                       nsIDOMHTMLElement* aHTMLElement,
-                                       Element** aResult)
-{
-  *aResult = nullptr;
-
-  nsRefPtr<mozilla::dom::NodeInfo> nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(
-    aTag, nullptr, kNameSpaceID_XUL, nsIDOMNode::ELEMENT_NODE);
-
-  nsresult rv = NS_NewElement(aResult, nodeInfo.forget(), NOT_FROM_PARSER);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  nsAutoString generateditemid;
-
-  if (aHTMLElement) {
-    mElements.AppendObject(aHTMLElement);
-    generateditemid.AppendInt(mCurrentGeneratedItemId++);
-  }
-
-  (*aResult)->SetAttr(kNameSpaceID_None, mGeneratedItemIdAttr, generateditemid,
-                      false);
-
-  return NS_OK;
-}
deleted file mode 100644
--- a/dom/xul/nsXULContextMenuBuilder.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- 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 "nsCOMPtr.h"
-#include "nsCOMArray.h"
-#include "nsIMenuBuilder.h"
-#include "nsIXULContextMenuBuilder.h"
-#include "nsCycleCollectionParticipant.h"
-
-class nsIAtom;
-class nsIContent;
-class nsIDocument;
-class nsIDOMHTMLElement;
-
-namespace mozilla {
-namespace dom {
-class Element;
-} // namespace dom
-} // namespace mozilla
-
-class nsXULContextMenuBuilder : public nsIMenuBuilder,
-                                public nsIXULContextMenuBuilder
-{
-public:
-  nsXULContextMenuBuilder();
-
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULContextMenuBuilder,
-                                           nsIMenuBuilder)
-  NS_DECL_NSIMENUBUILDER
-
-  NS_DECL_NSIXULCONTEXTMENUBUILDER
-
-protected:
-  virtual ~nsXULContextMenuBuilder();
-
-  nsresult CreateElement(nsIAtom* aTag,
-                         nsIDOMHTMLElement* aHTMLElement,
-                         mozilla::dom::Element** aResult);
-
-  nsCOMPtr<nsIContent>          mFragment;
-  nsCOMPtr<nsIDocument>         mDocument;
-  nsCOMPtr<nsIAtom>             mGeneratedItemIdAttr;
-
-  nsCOMPtr<nsIContent>          mCurrentNode;
-  int32_t                       mCurrentGeneratedItemId;
-
-  nsCOMArray<nsIDOMHTMLElement> mElements;
-};
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -211,17 +211,17 @@ SharedFrameMetricsHelper::UpdateFromComp
   // display-port. If we abort updating when we shouldn't, we can end up
   // with blank regions on the screen and we open up the risk of entering
   // an endless updating cycle.
   if (fabsf(contentMetrics.GetScrollOffset().x - compositorMetrics.GetScrollOffset().x) <= 2 &&
       fabsf(contentMetrics.GetScrollOffset().y - compositorMetrics.GetScrollOffset().y) <= 2 &&
       fabsf(contentMetrics.mDisplayPort.x - compositorMetrics.mDisplayPort.x) <= 2 &&
       fabsf(contentMetrics.mDisplayPort.y - compositorMetrics.mDisplayPort.y) <= 2 &&
       fabsf(contentMetrics.mDisplayPort.width - compositorMetrics.mDisplayPort.width) <= 2 &&
-      fabsf(contentMetrics.mDisplayPort.height - compositorMetrics.mDisplayPort.height)) {
+      fabsf(contentMetrics.mDisplayPort.height - compositorMetrics.mDisplayPort.height) <= 2) {
     return false;
   }
 
   // When not a low precision pass and the page is in danger of checker boarding
   // abort update.
   if (!aLowPrecision && !mProgressiveUpdateWasInDanger) {
     bool scrollUpdatePending = contentMetrics.GetScrollOffsetUpdated() &&
         contentMetrics.GetScrollGeneration() != compositorMetrics.GetScrollGeneration();
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -91,160 +91,16 @@ TextureTargetForAndroidPixelFormat(andro
       // we'll take down the compositor process and thus the phone. This seems
       // like undesirable behaviour. We'd rather have a subtle artifact.
       MOZ_ASSERT(false, "Unknown Android pixel format.");
       return LOCAL_GL_TEXTURE_EXTERNAL;
     }
   }
 }
 
-GrallocTextureSourceOGL::GrallocTextureSourceOGL(CompositorOGL* aCompositor,
-                                                 GrallocTextureHostOGL* aTextureHost,
-                                                 android::GraphicBuffer* aGraphicBuffer,
-                                                 gfx::SurfaceFormat aFormat)
-  : mCompositor(aCompositor)
-  , mTextureHost(aTextureHost)
-  , mGraphicBuffer(aGraphicBuffer)
-  , mEGLImage(0)
-  , mFormat(aFormat)
-  , mNeedsReset(true)
-{
-  MOZ_ASSERT(mGraphicBuffer.get());
-}
-
-GrallocTextureSourceOGL::~GrallocTextureSourceOGL()
-{
-  DeallocateDeviceData();
-  mCompositor = nullptr;
-}
-
-void
-GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
-{
-  /*
-   * The job of this function is to ensure that the texture is tied to the
-   * android::GraphicBuffer, so that texturing will source the GraphicBuffer.
-   *
-   * To this effect we create an EGLImage wrapping this GraphicBuffer,
-   * using EGLImageCreateFromNativeBuffer, and then we tie this EGLImage to our
-   * texture using fEGLImageTargetTexture2D.
-   */
-  MOZ_ASSERT(gl());
-  if (!IsValid() || !gl()->MakeCurrent()) {
-    return;
-  }
-
-  GLuint tex = GetGLTexture();
-  GLuint textureTarget = GetTextureTarget();
-
-  gl()->fActiveTexture(aTextureUnit);
-  gl()->fBindTexture(textureTarget, tex);
-
-  ApplyFilterToBoundTexture(gl(), aFilter, textureTarget);
-
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
-  if (mTextureHost) {
-    // Wait until it's ready.
-    mTextureHost->WaitAcquireFenceSyncComplete();
-  }
-#endif
-}
-
-bool GrallocTextureSourceOGL::Lock()
-{
-  MOZ_ASSERT(IsValid());
-  if (!IsValid()) {
-    return false;
-  }
-  if (!gl()->MakeCurrent()) {
-    NS_WARNING("Failed to make the gl context current");
-    return false;
-  }
-
-  mTexture = mCompositor->GetTemporaryTexture(GetTextureTarget(), LOCAL_GL_TEXTURE0);
-
-  GLuint textureTarget = GetTextureTarget();
-
-  gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
-  gl()->fBindTexture(textureTarget, mTexture);
-  if (!mEGLImage) {
-    mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
-  }
-  gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
-  return true;
-}
-
-bool
-GrallocTextureSourceOGL::IsValid() const
-{
-  return !!gl() && !!mGraphicBuffer.get() && !!mCompositor;
-}
-
-gl::GLContext*
-GrallocTextureSourceOGL::gl() const
-{
-  return mCompositor ? mCompositor->gl() : nullptr;
-}
-
-void
-GrallocTextureSourceOGL::SetCompositor(Compositor* aCompositor)
-{
-  if (mCompositor && !aCompositor) {
-    DeallocateDeviceData();
-  }
-  mCompositor = static_cast<CompositorOGL*>(aCompositor);
-}
-
-
-GLenum
-GrallocTextureSourceOGL::GetTextureTarget() const
-{
-  MOZ_ASSERT(gl());
-  MOZ_ASSERT(mGraphicBuffer.get());
-
-  if (!gl() || !mGraphicBuffer.get()) {
-    return LOCAL_GL_TEXTURE_EXTERNAL;
-  }
-
-  // SGX has a quirk that only TEXTURE_EXTERNAL works and any other value will
-  // result in black pixels when trying to draw from bound textures.
-  // Unfortunately, using TEXTURE_EXTERNAL on Adreno has a terrible effect on
-  // performance.
-  // See Bug 950050.
-  if (gl()->Renderer() == gl::GLRenderer::SGX530 ||
-      gl()->Renderer() == gl::GLRenderer::SGX540) {
-    return LOCAL_GL_TEXTURE_EXTERNAL;
-  }
-
-  return TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
-}
-
-gfx::IntSize
-GrallocTextureSourceOGL::GetSize() const
-{
-  if (!IsValid()) {
-    NS_WARNING("Trying to access the size of an invalid GrallocTextureSourceOGL");
-    return gfx::IntSize(0, 0);
-  }
-  return gfx::IntSize(mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight());
-}
-
-void
-GrallocTextureSourceOGL::DeallocateDeviceData()
-{
-  if (mEGLImage) {
-    MOZ_ASSERT(mCompositor);
-    if (!gl() || !gl()->MakeCurrent()) {
-      return;
-    }
-    EGLImageDestroy(gl(), mEGLImage);
-    mEGLImage = EGL_NO_IMAGE;
-  }
-}
-
 GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags,
                                              const NewSurfaceDescriptorGralloc& aDescriptor)
   : TextureHost(aFlags)
   , mGrallocHandle(aDescriptor)
   , mSize(0, 0)
   , mDescriptorSize(aDescriptor.size())
   , mFormat(gfx::SurfaceFormat::UNKNOWN)
   , mEGLImage(EGL_NO_IMAGE)
@@ -267,19 +123,16 @@ GrallocTextureHostOGL::~GrallocTextureHo
 {
   DestroyEGLImage();
 }
 
 void
 GrallocTextureHostOGL::SetCompositor(Compositor* aCompositor)
 {
   mCompositor = static_cast<CompositorOGL*>(aCompositor);
-  if (mTilingTextureSource) {
-    mTilingTextureSource->SetCompositor(mCompositor);
-  }
   if (mGLTextureSource) {
     mGLTextureSource->SetCompositor(mCompositor);
   }
 
   if (mCompositor && aCompositor != mCompositor) {
     DestroyEGLImage();
   }
 }
@@ -307,20 +160,16 @@ gfx::SurfaceFormat
 GrallocTextureHostOGL::GetFormat() const
 {
   return mFormat;
 }
 
 void
 GrallocTextureHostOGL::DeallocateSharedData()
 {
-  if (mTilingTextureSource) {
-    mTilingTextureSource->ForgetBuffer();
-    mTilingTextureSource = nullptr;
-  }
   if (mGLTextureSource) {
     mGLTextureSource = nullptr;
   }
 
   DestroyEGLImage();
 
   if (mGrallocHandle.buffer().type() != MaybeMagicGrallocBufferHandle::Tnull_t) {
     MaybeMagicGrallocBufferHandle handle = mGrallocHandle.buffer();
@@ -334,31 +183,24 @@ GrallocTextureHostOGL::DeallocateSharedD
 
     SharedBufferManagerParent::DropGrallocBuffer(owner, mGrallocHandle);
   }
 }
 
 void
 GrallocTextureHostOGL::ForgetSharedData()
 {
-  if (mTilingTextureSource) {
-    mTilingTextureSource->ForgetBuffer();
-    mTilingTextureSource = nullptr;
-  }
   if (mGLTextureSource) {
     mGLTextureSource = nullptr;
   }
 }
 
 void
 GrallocTextureHostOGL::DeallocateDeviceData()
 {
-  if (mTilingTextureSource) {
-    mTilingTextureSource->DeallocateDeviceData();
-  }
   if (mGLTextureSource) {
     mGLTextureSource = nullptr;
   }
   DestroyEGLImage();
 }
 
 LayerRenderState
 GrallocTextureHostOGL::GetRenderState()
@@ -382,87 +224,34 @@ GrallocTextureHostOGL::GetRenderState()
                             this);
   }
 
   return LayerRenderState();
 }
 
 TemporaryRef<gfx::DataSourceSurface>
 GrallocTextureHostOGL::GetAsSurface() {
-  if (mTilingTextureSource) {
-    return mTilingTextureSource->GetAsSurface();
-  } else {
-    android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
-    uint8_t* grallocData;
-    int32_t rv = graphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&grallocData));
-    RefPtr<gfx::DataSourceSurface> grallocTempSurf =
-      gfx::Factory::CreateWrappingDataSourceSurface(grallocData,
-                                                    graphicBuffer->getStride() * android::bytesPerPixel(graphicBuffer->getPixelFormat()),
-                                                    GetSize(), GetFormat());
-    RefPtr<gfx::DataSourceSurface> surf = CreateDataSourceSurfaceByCloning(grallocTempSurf);
-
-    graphicBuffer->unlock();
-
-    return surf.forget();
-  }
-}
-
-TemporaryRef<gfx::DataSourceSurface>
-GrallocTextureSourceOGL::GetAsSurface() {
-  if (!IsValid()) {
-    return nullptr;
-  }
-
+  android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
   uint8_t* grallocData;
-  int32_t rv = mGraphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&grallocData));
-  if (rv) {
-    return nullptr;
-  }
-
+  int32_t rv = graphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&grallocData));
   RefPtr<gfx::DataSourceSurface> grallocTempSurf =
     gfx::Factory::CreateWrappingDataSourceSurface(grallocData,
-                                                  mGraphicBuffer->getStride() * android::bytesPerPixel(mGraphicBuffer->getPixelFormat()),
+                                                  graphicBuffer->getStride() * android::bytesPerPixel(graphicBuffer->getPixelFormat()),
                                                   GetSize(), GetFormat());
-
   RefPtr<gfx::DataSourceSurface> surf = CreateDataSourceSurfaceByCloning(grallocTempSurf);
 
-  mGraphicBuffer->unlock();
+  graphicBuffer->unlock();
 
   return surf.forget();
 }
 
-GLuint
-GrallocTextureSourceOGL::GetGLTexture()
-{
-  return mTexture;
-}
-
-void
-GrallocTextureSourceOGL::BindEGLImage()
-{
-  gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage);
-}
-
 TextureSource*
 GrallocTextureHostOGL::GetTextureSources()
 {
-  // This is now only used with tiled layers, and will eventually be removed.
-  // Other layer types use BindTextureSource instead.
-  MOZ_ASSERT(!mGLTextureSource);
-  if (!mTilingTextureSource) {
-    android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
-    MOZ_ASSERT(graphicBuffer);
-    if (!graphicBuffer) {
-      return nullptr;
-    }
-    mTilingTextureSource = new GrallocTextureSourceOGL(mCompositor, this,
-                                                 graphicBuffer, mFormat);
-  }
-  mTilingTextureSource->Lock();
-  return mTilingTextureSource;
+  return nullptr;
 }
 
 void
 GrallocTextureHostOGL::UnbindTextureSource()
 {
   // Clear the reference to the TextureSource (if any), because we know that
   // another TextureHost is being bound to the TextureSource. This means that
   // we will have to re-do gl->fEGLImageTargetTexture2D next time we go through
@@ -524,18 +313,16 @@ GrallocTextureHostOGL::PrepareTextureSou
   // attach to it. This has the effect of unlocking the previous TextureHost that
   // we attached to the TextureSource (the previous frame)
 
   // If the TextureSource used by the compositable is also used by other
   // compositables (see NumCompositableRefs), we have to create a new TextureSource,
   // because otherwise we would be modifying the content of every layer that uses
   // the TextureSource in question, even thoug they don't use this TextureHost.
 
-  MOZ_ASSERT(!mTilingTextureSource);
-
   android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
 
   MOZ_ASSERT(graphicBuffer);
   if (!graphicBuffer) {
     mGLTextureSource = nullptr;
     return;
   }
 
--- a/gfx/layers/opengl/GrallocTextureHost.h
+++ b/gfx/layers/opengl/GrallocTextureHost.h
@@ -10,84 +10,16 @@
 #include "mozilla/layers/CompositorOGL.h"
 #include "mozilla/layers/TextureHostOGL.h"
 #include "mozilla/layers/ShadowLayerUtilsGralloc.h"
 #include <ui/GraphicBuffer.h>
 
 namespace mozilla {
 namespace layers {
 
-class GrallocTextureHostOGL;
-
-// Progressively getting replaced by GLTextureSource
-class GrallocTextureSourceOGL : public TextureSource
-                              , public TextureSourceOGL
-{
-public:
-  friend class GrallocTextureHostOGL;
-
-  GrallocTextureSourceOGL(CompositorOGL* aCompositor,
-                          GrallocTextureHostOGL* aTextureHost,
-                          android::GraphicBuffer* aGraphicBuffer,
-                          gfx::SurfaceFormat aFormat);
-
-  virtual ~GrallocTextureSourceOGL();
-
-  virtual bool IsValid() const MOZ_OVERRIDE;
-
-  virtual void BindTexture(GLenum aTextureUnit, gfx::Filter aFilter) MOZ_OVERRIDE;
-
-  virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
-
-  virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; }
-
-  virtual GLenum GetTextureTarget() const MOZ_OVERRIDE;
-
-  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
-
-  virtual GLenum GetWrapMode() const MOZ_OVERRIDE
-  {
-    return LOCAL_GL_CLAMP_TO_EDGE;
-  }
-
-  void DeallocateDeviceData();
-
-  gl::GLContext* gl() const;
-
-  virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
-
-  void ForgetBuffer()
-  {
-    mGraphicBuffer = nullptr;
-    mTextureHost = nullptr;
-  }
-
-  TemporaryRef<gfx::DataSourceSurface> GetAsSurface();
-
-  GLuint GetGLTexture();
-
-  void BindEGLImage();
-
-  EGLImage GetEGLImage()
-  {
-    return mEGLImage;
-  }
-
-  bool Lock();
-
-protected:
-  RefPtr<CompositorOGL> mCompositor;
-  GrallocTextureHostOGL* mTextureHost;
-  android::sp<android::GraphicBuffer> mGraphicBuffer;
-  EGLImage mEGLImage;
-  GLuint mTexture;
-  gfx::SurfaceFormat mFormat;
-  bool mNeedsReset;
-};
-
 class GrallocTextureHostOGL : public TextureHost
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
                             , public TextureHostOGL
 #endif
 {
   friend class GrallocBufferActor;
 public:
   GrallocTextureHostOGL(TextureFlags aFlags,
@@ -139,18 +71,16 @@ public:
   gl::GLContext* GetGLContext() const { return mCompositor ? mCompositor->gl() : nullptr; }
 
 private:
   void DestroyEGLImage();
 
   NewSurfaceDescriptorGralloc mGrallocHandle;
   RefPtr<GLTextureSource> mGLTextureSource;
   RefPtr<CompositorOGL> mCompositor;
-  // only used for tiling, will be removed.
-  RefPtr<GrallocTextureSourceOGL> mTilingTextureSource;
   // Size reported by the GraphicBuffer
   gfx::IntSize mSize;
   // Size reported by TextureClient, can be different in some cases (video?),
   // used by LayerRenderState.
   gfx::IntSize mDescriptorSize;
   gfx::SurfaceFormat mFormat;
   EGLImage mEGLImage;
   bool mIsOpaque;
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -22,21 +22,17 @@
 #include <math.h>
 #include <regex.h>
 #include <sched.h>
 #include <stdio.h>
 #include <sys/klog.h>
 #include <sys/syscall.h>
 #include <sys/resource.h>
 #include <time.h>
-#if ANDROID_VERSION >= 21
-#include <limits.h>
-#else
-#include <asm/page.h>
-#endif
+#include <unistd.h>
 
 #include "mozilla/DebugOnly.h"
 
 #include "android/log.h"
 #include "cutils/properties.h"
 #include "hardware/hardware.h"
 #include "hardware/lights.h"
 #include "hardware_legacy/uevent.h"
@@ -1316,16 +1312,18 @@ EnsureKernelLowMemKillerParamsSet()
   // Build the adj and minfree strings.
   nsAutoCString adjParams;
   nsAutoCString minfreeParams;
 
   int32_t lowerBoundOfNextOomScoreAdj = OOM_SCORE_ADJ_MIN - 1;
   int32_t lowerBoundOfNextKillUnderKB = 0;
   int32_t countOfLowmemorykillerParametersSets = 0;
 
+  long page_size = sysconf(_SC_PAGESIZE);
+
   for (int i = NUM_PROCESS_PRIORITY - 1; i >= 0; i--) {
     // The system doesn't function correctly if we're missing these prefs, so
     // crash loudly.
 
     ProcessPriority priority = static_cast<ProcessPriority>(i);
 
     int32_t oomScoreAdj;
     if (!NS_SUCCEEDED(Preferences::GetInt(
@@ -1353,17 +1351,17 @@ EnsureKernelLowMemKillerParamsSet()
 
     // The LMK in kernel only accept 6 sets of LMK parameters. See bug 914728.
     MOZ_ASSERT(countOfLowmemorykillerParametersSets < 6);
 
     // adj is in oom_adj units.
     adjParams.AppendPrintf("%d,", OomAdjOfOomScoreAdj(oomScoreAdj));
 
     // minfree is in pages.
-    minfreeParams.AppendPrintf("%d,", killUnderKB * 1024 / PAGE_SIZE);
+    minfreeParams.AppendPrintf("%ld,", killUnderKB * 1024 / page_size);
 
     lowerBoundOfNextOomScoreAdj = oomScoreAdj;
     lowerBoundOfNextKillUnderKB = killUnderKB;
     countOfLowmemorykillerParametersSets++;
   }
 
   // Strip off trailing commas.
   adjParams.Cut(adjParams.Length() - 1, 1);
@@ -1376,17 +1374,17 @@ EnsureKernelLowMemKillerParamsSet()
   // Set the low-memory-notification threshold.
   int32_t lowMemNotifyThresholdKB;
   if (NS_SUCCEEDED(Preferences::GetInt(
         "hal.processPriorityManager.gonk.notifyLowMemUnderKB",
         &lowMemNotifyThresholdKB))) {
 
     // notify_trigger is in pages.
     WriteToFile("/sys/module/lowmemorykiller/parameters/notify_trigger",
-      nsPrintfCString("%d", lowMemNotifyThresholdKB * 1024 / PAGE_SIZE).get());
+      nsPrintfCString("%ld", lowMemNotifyThresholdKB * 1024 / page_size).get());
   }
 
   // Ensure OOM events appear in logcat
   nsRefPtr<OomVictimLogger> oomLogger = new OomVictimLogger();
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   if (os) {
     os->AddObserver(oomLogger, "ipc:content-shutdown", false);
   }
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2237,17 +2237,17 @@ LIRGenerator::visitLoadSlot(MLoadSlot *i
         defineBox(new(alloc()) LLoadSlotV(useRegisterAtStart(ins->slots())), ins);
         break;
 
       case MIRType_Undefined:
       case MIRType_Null:
         MOZ_CRASH("typed load must have a payload");
 
       default:
-        define(new(alloc()) LLoadSlotT(useRegisterAtStart(ins->slots())), ins);
+        define(new(alloc()) LLoadSlotT(useRegisterForTypedLoad(ins->slots(), ins->type())), ins);
         break;
     }
 }
 
 void
 LIRGenerator::visitFunctionEnvironment(MFunctionEnvironment *ins)
 {
     define(new(alloc()) LFunctionEnvironment(useRegisterAtStart(ins->function())), ins);
@@ -3083,23 +3083,26 @@ LIRGenerator::visitStoreTypedArrayElemen
     else
         value = useRegisterOrNonDoubleConstant(ins->value());
     add(new(alloc()) LStoreTypedArrayElementHole(elements, length, index, value), ins);
 }
 
 void
 LIRGenerator::visitLoadFixedSlot(MLoadFixedSlot *ins)
 {
-    MOZ_ASSERT(ins->object()->type() == MIRType_Object);
-
-    if (ins->type() == MIRType_Value) {
-        LLoadFixedSlotV *lir = new(alloc()) LLoadFixedSlotV(useRegisterAtStart(ins->object()));
+    MDefinition *obj = ins->object();
+    MOZ_ASSERT(obj->type() == MIRType_Object);
+
+    MIRType type = ins->type();
+
+    if (type == MIRType_Value) {
+        LLoadFixedSlotV *lir = new(alloc()) LLoadFixedSlotV(useRegisterAtStart(obj));
         defineBox(lir, ins);
     } else {
-        LLoadFixedSlotT *lir = new(alloc()) LLoadFixedSlotT(useRegisterAtStart(ins->object()));
+        LLoadFixedSlotT *lir = new(alloc()) LLoadFixedSlotT(useRegisterForTypedLoad(obj, type));
         define(lir, ins);
     }
 }
 
 void
 LIRGenerator::visitStoreFixedSlot(MStoreFixedSlot *ins)
 {
     MOZ_ASSERT(ins->object()->type() == MIRType_Object);
--- a/js/src/jit/shared/Lowering-shared-inl.h
+++ b/js/src/jit/shared/Lowering-shared-inl.h
@@ -477,12 +477,29 @@ void
 LIRGeneratorShared::fillBoxUses(LInstruction *lir, size_t n, MDefinition *mir)
 {
     ensureDefined(mir);
     lir->getOperand(n)->toUse()->setVirtualRegister(mir->virtualRegister() + VREG_TYPE_OFFSET);
     lir->getOperand(n + 1)->toUse()->setVirtualRegister(VirtualRegisterOfPayload(mir));
 }
 #endif
 
+LUse
+LIRGeneratorShared::useRegisterForTypedLoad(MDefinition *mir, MIRType type)
+{
+    MOZ_ASSERT(type != MIRType_Value && type != MIRType_None);
+    MOZ_ASSERT(mir->type() == MIRType_Object || mir->type() == MIRType_Slots);
+
+#ifdef JS_PUNBOX64
+    // On x64, masm.loadUnboxedValue emits slightly less efficient code when
+    // the input and output use the same register and we're not loading an
+    // int32/bool/double, so we just call useRegister in this case.
+    if (type != MIRType_Int32 && type != MIRType_Boolean && type != MIRType_Double)
+        return useRegister(mir);
+#endif
+
+    return useRegisterAtStart(mir);
+}
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_shared_Lowering_shared_inl_h */
--- a/js/src/jit/shared/Lowering-shared.h
+++ b/js/src/jit/shared/Lowering-shared.h
@@ -106,16 +106,18 @@ class LIRGeneratorShared : public MDefin
     inline LAllocation useStorable(MDefinition *mir);
     inline LAllocation useStorableAtStart(MDefinition *mir);
     inline LAllocation useKeepaliveOrConstant(MDefinition *mir);
     inline LAllocation useRegisterOrConstant(MDefinition *mir);
     inline LAllocation useRegisterOrConstantAtStart(MDefinition *mir);
     inline LAllocation useRegisterOrNonNegativeConstantAtStart(MDefinition *mir);
     inline LAllocation useRegisterOrNonDoubleConstant(MDefinition *mir);
 
+    inline LUse useRegisterForTypedLoad(MDefinition *mir, MIRType type);
+
 #ifdef JS_NUNBOX32
     inline LUse useType(MDefinition *mir, LUse::Policy policy);
     inline LUse usePayload(MDefinition *mir, LUse::Policy policy);
     inline LUse usePayloadAtStart(MDefinition *mir, LUse::Policy policy);
     inline LUse usePayloadInRegisterAtStart(MDefinition *mir);
 
     // Adds a box input to an instruction, setting operand |n| to the type and
     // |n+1| to the payload. Does not modify the operands, instead expecting a
deleted file mode 100644
--- a/js/xpconnect/tests/idl/Makefile.in
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-include $(topsrcdir)/config/rules.mk
-
-componentdir = js/xpconnect/tests/components
-libs:: $(DEPTH)/config/makefiles/xpidl/xpt/$(XPT_NAME)
-	$(INSTALL) $^ $(testxpcobjdir)/$(componentdir)/native
-	$(INSTALL) $^ $(testxpcobjdir)/$(componentdir)/js
--- a/js/xpconnect/tests/idl/moz.build
+++ b/js/xpconnect/tests/idl/moz.build
@@ -9,8 +9,16 @@ XPIDL_SOURCES += [
     'xpctest_bug809674.idl',
     'xpctest_interfaces.idl',
     'xpctest_params.idl',
     'xpctest_returncode.idl',
 ]
 
 XPIDL_MODULE = 'xpctest'
 
+# XXX: This relies on xpctest.xpt being created in dist/bin/components/ during
+# the export tier AND TEST_HARNESS_FILES being processed after that.
+TEST_HARNESS_FILES.xpcshell.js.xpconnect.tests.components.native += [
+    '!/dist/bin/components/xpctest.xpt',
+]
+TEST_HARNESS_FILES.xpcshell.js.xpconnect.tests.components.js += [
+    '!/dist/bin/components/xpctest.xpt',
+]
--- a/mfbt/MathAlgorithms.h
+++ b/mfbt/MathAlgorithms.h
@@ -141,17 +141,17 @@ template<>
 inline long double
 Abs<long double>(const long double aLongDouble)
 {
   return std::fabs(aLongDouble);
 }
 
 } // namespace mozilla
 
-#if defined(_WIN32) && \
+#if defined(_MSC_VER) && \
     (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
 #  define MOZ_BITSCAN_WINDOWS
 
 #  include <intrin.h>
 #  pragma intrinsic(_BitScanForward, _BitScanReverse)
 
 #  if defined(_M_AMD64) || defined(_M_X64)
 #    define MOZ_BITSCAN_WINDOWS64
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -403,16 +403,18 @@
 @BINPATH@/components/TelemetryStartup.js
 @BINPATH@/components/TelemetryStartup.manifest
 @BINPATH@/components/XULStore.js
 @BINPATH@/components/XULStore.manifest
 @BINPATH@/components/Webapps.js
 @BINPATH@/components/Webapps.manifest
 @BINPATH@/components/AppsService.js
 @BINPATH@/components/AppsService.manifest
+@BINPATH@/components/htmlMenuBuilder.js
+@BINPATH@/components/htmlMenuBuilder.manifest
 
 @BINPATH@/components/Activities.manifest
 @BINPATH@/components/ActivitiesGlue.js
 @BINPATH@/components/ActivityProxy.js
 @BINPATH@/components/ActivityRequestHandler.js
 @BINPATH@/components/ActivityWrapper.js
 @BINPATH@/components/ActivityMessageConfigurator.js
 
--- a/netwerk/dns/effective_tld_names.dat
+++ b/netwerk/dns/effective_tld_names.dat
@@ -9228,17 +9228,17 @@ flynnhub.com
 github.io
 githubusercontent.com
 
 // GlobeHosting, Inc.
 // Submitted by Zoltan Egresi <egresi@globehosting.com> 2013-07-12
 ro.com
 
 // Google, Inc.
-// Submitted by Eduardo Vela <evn@google.com> 2012-10-24
+// Submitted by Eduardo Vela <evn@google.com> 2014-12-19
 appspot.com
 blogspot.ae
 blogspot.be
 blogspot.bj
 blogspot.ca
 blogspot.cf
 blogspot.ch
 blogspot.co.at
@@ -9276,16 +9276,17 @@ blogspot.ru
 blogspot.se
 blogspot.sg
 blogspot.sk
 blogspot.td
 blogspot.tw
 codespot.com
 googleapis.com
 googlecode.com
+pagespeedmobilizer.com
 withgoogle.com
 
 // Heroku : https://www.heroku.com/
 // Submitted by Tom Maher <tmaher@heroku.com> 2013-05-02
 herokuapp.com
 herokussl.com
 
 // iki.fi
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -2372,34 +2372,36 @@ nsHttpConnectionMgr::OnMsgReschedTransac
 
 void
 nsHttpConnectionMgr::OnMsgCancelTransaction(int32_t reason, void *param)
 {
     MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
     LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p]\n", param));
 
     nsresult closeCode = static_cast<nsresult>(reason);
-    nsHttpTransaction *trans = (nsHttpTransaction *) param;
+    nsRefPtr<nsHttpTransaction> trans =
+        dont_AddRef(static_cast<nsHttpTransaction *>(param));
+
     //
     // if the transaction owns a connection and the transaction is not done,
     // then ask the connection to close the transaction.  otherwise, close the
     // transaction directly (removing it from the pending queue first).
     //
-    nsAHttpConnection *conn = trans->Connection();
+    nsRefPtr<nsAHttpConnection> conn(trans->Connection());
     if (conn && !trans->IsDone()) {
         conn->CloseTransaction(trans, closeCode);
     } else {
         nsConnectionEntry *ent =
             LookupConnectionEntry(trans->ConnectionInfo(), nullptr, trans);
 
         if (ent) {
             int32_t index = ent->mPendingQ.IndexOf(trans);
             if (index >= 0) {
                 LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p]"
-                     " found in pending queue\n", trans));
+                     " found in pending queue\n", trans.get()));
                 ent->mPendingQ.RemoveElementAt(index);
                 nsHttpTransaction *temp = trans;
                 NS_RELEASE(temp); // b/c NS_RELEASE nulls its argument!
             }
 
             // Abandon all half-open sockets belonging to the given transaction.
             for (uint32_t index = 0;
                  index < ent->mHalfOpens.Length();
@@ -2424,22 +2426,21 @@ nsHttpConnectionMgr::OnMsgCancelTransact
         for (uint32_t index = 0;
              ent && (index < ent->mActiveConns.Length());
              ++index) {
             nsHttpConnection *activeConn = ent->mActiveConns[index];
             nsAHttpTransaction *liveTransaction = activeConn->Transaction();
             if (liveTransaction && liveTransaction->IsNullTransaction()) {
                 LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p] "
                      "also canceling Null Transaction %p on conn %p\n",
-                     trans, liveTransaction, activeConn));
+                     trans.get(), liveTransaction, activeConn));
                 activeConn->CloseTransaction(liveTransaction, closeCode);
             }
         }
     }
-    NS_RELEASE(trans);
 }
 
 void
 nsHttpConnectionMgr::OnMsgProcessPendingQ(int32_t, void *param)
 {
     MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
     nsHttpConnectionInfo *ci = (nsHttpConnectionInfo *) param;
 
--- a/python/mozbuild/mozbuild/backend/common.py
+++ b/python/mozbuild/mozbuild/backend/common.py
@@ -34,17 +34,17 @@ class XPIDLManager(object):
     def __init__(self, config):
         self.config = config
         self.topsrcdir = config.topsrcdir
         self.topobjdir = config.topobjdir
 
         self.idls = {}
         self.modules = {}
 
-    def register_idl(self, source, module, allow_existing=False):
+    def register_idl(self, source, module, install_target, allow_existing=False):
         """Registers an IDL file with this instance.
 
         The IDL file will be built, installed, etc.
         """
         basename = mozpath.basename(source)
         root = mozpath.splitext(basename)[0]
 
         entry = {
@@ -53,17 +53,18 @@ class XPIDLManager(object):
             'basename': basename,
             'root': root,
         }
 
         if not allow_existing and entry['basename'] in self.idls:
             raise Exception('IDL already registered: %' % entry['basename'])
 
         self.idls[entry['basename']] = entry
-        self.modules.setdefault(entry['module'], set()).add(entry['root'])
+        t = self.modules.setdefault(entry['module'], (install_target, set()))
+        t[1].add(entry['root'])
 
 
 class WebIDLCollection(object):
     """Collects WebIDL info referenced during the build."""
 
     def __init__(self):
         self.sources = set()
         self.generated_sources = set()
@@ -176,17 +177,18 @@ class CommonBackend(BuildBackend):
         self._configs.add(obj.config)
 
         if isinstance(obj, TestManifest):
             for test in obj.tests:
                 self._test_manager.add(test, flavor=obj.flavor,
                     topsrcdir=obj.topsrcdir)
 
         elif isinstance(obj, XPIDLFile):
-            self._idl_manager.register_idl(obj.source_path, obj.module)
+            self._idl_manager.register_idl(obj.source_path, obj.module,
+                obj.install_target)
 
         elif isinstance(obj, ConfigFileSubstitution):
             # Do not handle ConfigFileSubstitution for Makefiles. Leave that
             # to other
             if mozpath.basename(obj.output_path) == 'Makefile':
                 return
             with self._get_preprocessor(obj) as pp:
                 pp.do_include(obj.input_path)
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -1,30 +1,31 @@
 # 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/.
 
 from __future__ import unicode_literals
 
+import errno
 import itertools
 import json
 import logging
 import os
 import re
 import types
 
 from collections import (
     defaultdict,
     namedtuple,
 )
+from StringIO import StringIO
 
 import mozwebidlcodegen
 from reftest import ReftestManifest
 
-import mozbuild.makeutil as mozmakeutil
 from mozpack.copier import FilePurger
 from mozpack.manifests import (
     InstallManifest,
 )
 import mozpack.path as mozpath
 
 from .common import CommonBackend
 from ..frontend.data import (
@@ -746,17 +747,17 @@ class RecursiveMakeBackend(CommonBackend
                             continue
                         if objdir == self.environment.topobjdir:
                             continue
                         self._no_skip['tools'].add(mozpath.relpath(objdir,
                             self.environment.topobjdir))
 
         # Write out a master list of all IPDL source files.
         ipdl_dir = mozpath.join(self.environment.topobjdir, 'ipc', 'ipdl')
-        mk = mozmakeutil.Makefile()
+        mk = Makefile()
 
         sorted_ipdl_sources = list(sorted(self._ipdl_sources))
         mk.add_statement('ALL_IPDLSRCS := %s' % ' '.join(sorted_ipdl_sources))
 
         def files_from(ipdl):
             base = mozpath.basename(ipdl)
             root, ext = mozpath.splitext(base)
 
@@ -978,72 +979,82 @@ INSTALL_TARGETS += %(prefix)s
         manifest = self._install_manifests['tests']
 
         for source, dest, _ in self._walk_hierarchy(obj, obj.modules):
             manifest.add_symlink(source, mozpath.join('modules', dest))
 
     def _handle_idl_manager(self, manager):
         build_files = self._install_manifests['xpidl']
 
-        for p in ('Makefile', 'backend.mk', '.deps/.mkdir.done',
-            'xpt/.mkdir.done'):
+        for p in ('Makefile', 'backend.mk', '.deps/.mkdir.done'):
             build_files.add_optional_exists(p)
 
         for idl in manager.idls.values():
             self._install_manifests['dist_idl'].add_symlink(idl['source'],
                 idl['basename'])
             self._install_manifests['dist_include'].add_optional_exists('%s.h'
                 % idl['root'])
 
         for module in manager.modules:
-            build_files.add_optional_exists(mozpath.join('xpt',
-                '%s.xpt' % module))
             build_files.add_optional_exists(mozpath.join('.deps',
                 '%s.pp' % module))
 
         modules = manager.modules
         xpt_modules = sorted(modules.keys())
-        rules = []
+        xpt_files = set()
+
+        mk = Makefile()
 
         for module in xpt_modules:
-            deps = sorted(modules[module])
-            idl_deps = ['$(dist_idl_dir)/%s.idl' % dep for dep in deps]
-            rules.extend([
-                # It may seem strange to have the .idl files listed as
-                # prerequisites both here and in the auto-generated .pp files.
-                # It is necessary to list them here to handle the case where a
-                # new .idl is added to an xpt. If we add a new .idl and nothing
-                # else has changed, the new .idl won't be referenced anywhere
-                # except in the command invocation. Therefore, the .xpt won't
-                # be rebuilt because the dependencies say it is up to date. By
-                # listing the .idls here, we ensure the make file has a
-                # reference to the new .idl. Since the new .idl presumably has
-                # an mtime newer than the .xpt, it will trigger xpt generation.
-                '$(idl_xpt_dir)/%s.xpt: %s' % (module, ' '.join(idl_deps)),
-                '\t@echo "$(notdir $@)"',
-                '\t$(idlprocess) $(basename $(notdir $@)) %s' % ' '.join(deps),
-                '',
-            ])
+            install_target, sources = modules[module]
+            deps = sorted(sources)
+
+            # It may seem strange to have the .idl files listed as
+            # prerequisites both here and in the auto-generated .pp files.
+            # It is necessary to list them here to handle the case where a
+            # new .idl is added to an xpt. If we add a new .idl and nothing
+            # else has changed, the new .idl won't be referenced anywhere
+            # except in the command invocation. Therefore, the .xpt won't
+            # be rebuilt because the dependencies say it is up to date. By
+            # listing the .idls here, we ensure the make file has a
+            # reference to the new .idl. Since the new .idl presumably has
+            # an mtime newer than the .xpt, it will trigger xpt generation.
+            xpt_path = '$(DEPTH)/%s/components/%s.xpt' % (install_target, module)
+            xpt_files.add(xpt_path)
+            rule = mk.create_rule([xpt_path])
+            rule.add_dependencies(['$(call mkdir_deps,%s)' % mozpath.dirname(xpt_path)])
+            rule.add_dependencies(manager.idls['%s.idl' % dep]['source'] for dep in deps)
+
+            if install_target.startswith('dist/'):
+                path = mozpath.relpath(xpt_path, '$(DEPTH)/dist')
+                prefix, subpath = path.split('/', 1)
+                key = 'dist_%s' % prefix
+
+                self._install_manifests[key].add_optional_exists(subpath)
+
+        rules = StringIO()
+        mk.dump(rules, removal_guard=False)
 
         # Create dependency for output header so we force regeneration if the
         # header was deleted. This ideally should not be necessary. However,
         # some processes (such as PGO at the time this was implemented) wipe
         # out dist/include without regard to our install manifests.
 
         obj = self.Substitution()
         obj.output_path = mozpath.join(self.environment.topobjdir, 'config',
             'makefiles', 'xpidl', 'Makefile')
         obj.input_path = mozpath.join(self.environment.topsrcdir, 'config',
             'makefiles', 'xpidl', 'Makefile.in')
         obj.topsrcdir = self.environment.topsrcdir
         obj.topobjdir = self.environment.topobjdir
         obj.config = self.environment
         self._create_makefile(obj, extra=dict(
-            xpidl_rules='\n'.join(rules),
+            xpidl_rules=rules.getvalue(),
             xpidl_modules=' '.join(xpt_modules),
+            xpt_files=' '.join(sorted(xpt_files)),
         ))
 
     def _process_program(self, program, backend_file):
         backend_file.write('PROGRAM = %s\n' % program)
 
     def _process_host_program(self, program, backend_file):
         backend_file.write('HOST_PROGRAM = %s\n' % program)
 
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -1156,17 +1156,17 @@ VARIABLES = {
         which subdirectory they should be exported to. For example,
         to export ``foo.py`` to ``_tests/foo``, append to
         ``TEST_HARNESS_FILES`` like so::
            TEST_HARNESS_FILES.foo += ['foo.py']
 
         Files from topsrcdir and the objdir can also be installed by prefixing
         the path(s) with a '/' character and a '!' character, respectively::
            TEST_HARNESS_FILES.path += ['/build/bar.py', '!quux.py']
-        """, None),
+        """, 'libs'),
 }
 
 # Sanity check: we don't want any variable above to have a list as storage type.
 for name, (storage_type, input_types, docs, tier) in VARIABLES.items():
     if storage_type == list:
         raise RuntimeError('%s has a "list" storage type. Use "List" instead.'
             % name)
 
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -152,26 +152,29 @@ class VariablePassthru(ContextDerived):
         ContextDerived.__init__(self, context)
         self.variables = {}
 
 class XPIDLFile(ContextDerived):
     """Describes an XPIDL file to be compiled."""
 
     __slots__ = (
         'basename',
+        'install_target',
         'source_path',
     )
 
     def __init__(self, context, source, module):
         ContextDerived.__init__(self, context)
 
         self.source_path = source
         self.basename = mozpath.basename(source)
         self.module = module
 
+        self.install_target = context['FINAL_TARGET']
+
 class Defines(ContextDerived):
     """Context derived container object for DEFINES, which is an OrderedDict.
     """
     __slots__ = ('defines')
 
     def __init__(self, context, defines):
         ContextDerived.__init__(self, context)
         self.defines = defines
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -340,16 +340,24 @@ class TreeMetadataEmitter(LoggingMixin):
         else:
             return ExternalSharedLibrary(context, name)
 
     def emit_from_context(self, context):
         """Convert a Context to tree metadata objects.
 
         This is a generator of mozbuild.frontend.data.ContextDerived instances.
         """
+
+        # We only want to emit an InstallationTarget if one of the consulted
+        # variables is defined. Later on, we look up FINAL_TARGET, which has
+        # the side-effect of populating it. So, we need to do this lookup
+        # early.
+        if any(k in context for k in ('FINAL_TARGET', 'XPI_NAME', 'DIST_SUBDIR')):
+            yield InstallationTarget(context)
+
         # We always emit a directory traversal descriptor. This is needed by
         # the recursive make backend.
         for o in self._emit_directory_traversal_from_context(context): yield o
 
         for path in context['CONFIGURE_SUBST_FILES']:
             yield self._create_substitution(ConfigFileSubstitution, context,
                 path)
 
@@ -518,19 +526,19 @@ class TreeMetadataEmitter(LoggingMixin):
             for path, strings in test_harness_files.walk():
                 if not path and strings:
                     raise SandboxValidationError(
                         'Cannot install files to the root of TEST_HARNESS_FILES', context)
 
                 for s in strings:
                     if context.is_objdir_path(s):
                         if s.startswith('!/'):
-                            raise SandboxValidationError(
-                                'Topobjdir-relative file not allowed in TEST_HARNESS_FILES: %s' % s, context)
-                        objdir_files[path].append(s[1:])
+                            objdir_files[path].append('$(DEPTH)/%s' % s[2:])
+                        else:
+                            objdir_files[path].append(s[1:])
                     else:
                         resolved = context.resolve_path(s)
                         if '*' in s:
                             srcdir_pattern_files[path].append(s);
                         elif not os.path.exists(resolved):
                             raise SandboxValidationError(
                                 'File listed in TEST_HARNESS_FILES does not exist: %s' % s, context)
                         else:
@@ -611,20 +619,16 @@ class TreeMetadataEmitter(LoggingMixin):
                 relative_include = local_include
 
             actual_include = os.path.join(path, relative_include)
             if not os.path.exists(actual_include):
                 raise SandboxValidationError('Path specified in LOCAL_INCLUDES '
                     'does not exist: %s (resolved to %s)' % (local_include, actual_include), context)
             yield LocalInclude(context, local_include)
 
-        if context.get('FINAL_TARGET') or context.get('XPI_NAME') or \
-                context.get('DIST_SUBDIR'):
-            yield InstallationTarget(context)
-
         final_target_files = context.get('FINAL_TARGET_FILES')
         if final_target_files:
             yield FinalTargetFiles(context, final_target_files, context['FINAL_TARGET'])
 
         host_libname = context.get('HOST_LIBRARY_NAME')
         libname = context.get('LIBRARY_NAME')
 
         if host_libname:
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -438,17 +438,19 @@ class TestRecursiveMakeBackend(BackendTe
 
         m = InstallManifest(path=mozpath.join(install_dir, 'dist_idl'))
         self.assertEqual(len(m), 2)
         self.assertIn('bar.idl', m)
         self.assertIn('foo.idl', m)
 
         m = InstallManifest(path=mozpath.join(install_dir, 'xpidl'))
         self.assertIn('.deps/my_module.pp', m)
-        self.assertIn('xpt/my_module.xpt', m)
+
+        m = InstallManifest(path=os.path.join(install_dir, 'dist_bin'))
+        self.assertIn('components/my_module.xpt', m)
 
         m = InstallManifest(path=mozpath.join(install_dir, 'dist_include'))
         self.assertIn('foo.h', m)
 
         p = mozpath.join(env.topobjdir, 'config/makefiles/xpidl')
         self.assertTrue(os.path.isdir(p))
 
         self.assertTrue(os.path.isfile(mozpath.join(p, 'Makefile')))
--- a/toolkit/modules/PageMenu.jsm
+++ b/toolkit/modules/PageMenu.jsm
@@ -1,141 +1,313 @@
 /* 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/. */
 
-this.EXPORTED_SYMBOLS = ["PageMenu"];
+this.EXPORTED_SYMBOLS = ["PageMenuParent", "PageMenuChild"];
 
 this.PageMenu = function PageMenu() {
 }
 
 PageMenu.prototype = {
   PAGEMENU_ATTR: "pagemenu",
   GENERATEDITEMID_ATTR: "generateditemid",
 
-  popup: null,
-  builder: null,
+  _popup: null,
+
+  // Only one of builder or browser will end up getting set.
+  _builder: null,
+  _browser: null,
 
-  maybeBuildAndAttachMenu: function(aTarget, aPopup) {
-    var pageMenu = null;
-    var target = aTarget;
+  // Given a target node, get the context menu for it or its ancestor.
+  getContextMenu: function(aTarget) {
+    let pageMenu = null;
+    let target = aTarget;
     while (target) {
-      var contextMenu = target.contextMenu;
+      let contextMenu = target.contextMenu;
       if (contextMenu) {
-        pageMenu = contextMenu;
-        break;
+        return contextMenu;
       }
       target = target.parentNode;
     }
 
-    if (!pageMenu) {
-      return false;
-    }
+    return null;
+  },
 
-    var insertionPoint = this.getInsertionPoint(aPopup);
-    if (!insertionPoint) {
-      return false;
+  // Given a target node, generate a JSON object for any context menu
+  // associated with it, or null if there is no context menu.
+  maybeBuild: function(aTarget) {
+    let pageMenu = this.getContextMenu(aTarget);
+    if (!pageMenu) {
+      return null;
     }
 
     pageMenu.QueryInterface(Components.interfaces.nsIHTMLMenu);
     pageMenu.sendShowEvent();
     // the show event is not cancelable, so no need to check a result here
 
-    var fragment = aPopup.ownerDocument.createDocumentFragment();
+    this._builder = pageMenu.createBuilder();
+    if (!this._builder) {
+      return null;
+    }
+
+    pageMenu.build(this._builder);
 
-    var builder = pageMenu.createBuilder();
-    if (!builder) {
+    // This serializes then parses again, however this could be avoided in
+    // the single-process case with further improvement.
+    let menuString = this._builder.toJSONString();
+    if (!menuString) {
+      return null;
+    }
+
+    return JSON.parse(menuString);
+  },
+
+  // Given a JSON menu object and popup, add the context menu to the popup.
+  buildAndAttachMenuWithObject: function(aMenu, aBrowser, aPopup) {
+    if (!aMenu) {
       return false;
     }
-    builder.QueryInterface(Components.interfaces.nsIXULContextMenuBuilder);
-    builder.init(fragment, this.GENERATEDITEMID_ATTR);
 
-    pageMenu.build(builder);
+    let insertionPoint = this.getInsertionPoint(aPopup);
+    if (!insertionPoint) {
+      return false;
+    }
 
-    var pos = insertionPoint.getAttribute(this.PAGEMENU_ATTR);
+    let fragment = aPopup.ownerDocument.createDocumentFragment();
+    this.buildXULMenu(aMenu, fragment);
+
+    let pos = insertionPoint.getAttribute(this.PAGEMENU_ATTR);
     if (pos == "start") {
       insertionPoint.insertBefore(fragment,
                                   insertionPoint.firstChild);
     } else if (pos.startsWith("#")) {
       insertionPoint.insertBefore(fragment, insertionPoint.querySelector(pos));
     } else {
       insertionPoint.appendChild(fragment);
     }
 
-    this.builder = builder;
-    this.popup = aPopup;
+    this._browser = aBrowser;
+    this._popup = aPopup;
 
-    this.popup.addEventListener("command", this);
-    this.popup.addEventListener("popuphidden", this);
+    this._popup.addEventListener("command", this);
+    this._popup.addEventListener("popuphidden", this);
 
     return true;
   },
 
-  handleEvent: function(event) {
-    var type = event.type;
-    var target = event.target;
-    if (type == "command" && target.hasAttribute(this.GENERATEDITEMID_ATTR)) {
-      this.builder.click(target.getAttribute(this.GENERATEDITEMID_ATTR));
-    } else if (type == "popuphidden" && this.popup == target) {
-      this.removeGeneratedContent(this.popup);
+  // Construct the XUL menu structure for a given JSON object.
+  buildXULMenu: function(aNode, aElementForAppending) {
+    let document = aElementForAppending.ownerDocument;
+
+    let children = aNode.children;
+    for (let child of children) {
+      let menuitem;
+      switch (child.type) {
+        case "menuitem":
+          if (!child.id) {
+            continue; // Ignore children without ids
+          }
+
+          menuitem = document.createElement("menuitem");
+          if (child.checkbox) {
+            menuitem.setAttribute("type", "checkbox");
+            if (child.checked) {
+              menuitem.setAttribute("checked", "true");
+            }
+          }
 
-      this.popup.removeEventListener("popuphidden", this);
-      this.popup.removeEventListener("command", this);
+          if (child.label) {
+            menuitem.setAttribute("label", child.label);
+          }
+          if (child.icon) {
+            menuitem.setAttribute("image", child.icon);
+            menuitem.className = "menuitem-iconic";
+          }
+          if (child.disabled) {
+            menuitem.setAttribute("disabled", true);
+          }
+
+          break;
 
-      this.popup = null;
-      this.builder = null;
+        case "separator":
+          menuitem = document.createElement("menuseparator");
+          break;
+
+        case "menu":
+          menuitem = document.createElement("menu");
+          if (child.label) {
+            menuitem.setAttribute("label", child.label);
+          }
+
+          let menupopup = document.createElement("menupopup");
+          menuitem.appendChild(menupopup);
+
+          this.buildXULMenu(child, menupopup);
+          break;
+      }
+
+      menuitem.setAttribute(this.GENERATEDITEMID_ATTR, child.id ? child.id : 0);
+      aElementForAppending.appendChild(menuitem);
     }
   },
 
+  // Called when the generated menuitem is executed.
+  handleEvent: function(event) {
+    let type = event.type;
+    let target = event.target;
+    if (type == "command" && target.hasAttribute(this.GENERATEDITEMID_ATTR)) {
+      // If a builder is assigned, call click on it directly. Otherwise, this is
+      // likely a menu with data from another process, so send a message to the
+      // browser to execute the menuitem.
+      if (this._builder) {
+        this._builder.click(target.getAttribute(this.GENERATEDITEMID_ATTR));
+      }
+      else if (this._browser) {
+        this._browser.messageManager.sendAsyncMessage("ContextMenu:DoCustomCommand",
+          target.getAttribute(this.GENERATEDITEMID_ATTR));
+      }
+    } else if (type == "popuphidden" && this._popup == target) {
+      this.removeGeneratedContent(this._popup);
+
+      this._popup.removeEventListener("popuphidden", this);
+      this._popup.removeEventListener("command", this);
+
+      this._popup = null;
+      this._builder = null;
+      this._browser = null;
+    }
+  },
+
+  // Get the first child of the given element with the given tag name.
   getImmediateChild: function(element, tag) {
-    var child = element.firstChild;
+    let child = element.firstChild;
     while (child) {
       if (child.localName == tag) {
         return child;
       }
       child = child.nextSibling;
     }
     return null;
   },
 
+  // Return the location where the generated items should be inserted into the
+  // given popup. They should be inserted as the next sibling of the returned
+  // element.
   getInsertionPoint: function(aPopup) {
     if (aPopup.hasAttribute(this.PAGEMENU_ATTR))
       return aPopup;
 
-    var element = aPopup.firstChild;
+    let element = aPopup.firstChild;
     while (element) {
       if (element.localName == "menu") {
-        var popup = this.getImmediateChild(element, "menupopup");
+        let popup = this.getImmediateChild(element, "menupopup");
         if (popup) {
-          var result = this.getInsertionPoint(popup);
+          let result = this.getInsertionPoint(popup);
           if (result) {
             return result;
           }
         }
       }
       element = element.nextSibling;
     }
 
     return null;
   },
 
+  // Remove the generated content from the given popup.
   removeGeneratedContent: function(aPopup) {
-    var ungenerated = [];
+    let ungenerated = [];
     ungenerated.push(aPopup);
 
-    var count;
+    let count;
     while (0 != (count = ungenerated.length)) {
-      var last = count - 1;
-      var element = ungenerated[last];
+      let last = count - 1;
+      let element = ungenerated[last];
       ungenerated.splice(last, 1);
 
-      var i = element.childNodes.length;
+      let i = element.childNodes.length;
       while (i-- > 0) {
-        var child = element.childNodes[i];
+        let child = element.childNodes[i];
         if (!child.hasAttribute(this.GENERATEDITEMID_ATTR)) {
           ungenerated.push(child);
           continue;
         }
         element.removeChild(child);
       }
     }
   }
 }
+
+// This object is expected to be used from a parent process.
+this.PageMenuParent = function PageMenuParent() {
+}
+
+PageMenuParent.prototype = {
+  __proto__ : PageMenu.prototype,
+
+  /*
+   * Given a target node and popup, add the context menu to the popup. This is
+   * intended to be called when a single process is used. This is equivalent to
+   * calling PageMenuChild.build and PageMenuParent.addToPopup in sequence.
+   *
+   * Returns true if custom menu items were present.
+   */
+  buildAndAddToPopup: function(aTarget, aPopup) {
+    let menuObject = this.maybeBuild(aTarget);
+    if (!menuObject) {
+      return false;
+    }
+
+    return this.buildAndAttachMenuWithObject(menuObject, null, aPopup);
+  },
+
+  /*
+   * Given a JSON menu object and popup, add the context menu to the popup. This
+   * is intended to be called when the child page is in a different process.
+   * aBrowser should be the browser containing the page the context menu is
+   * displayed for, which may be null.
+   *
+   * Returns true if custom menu items were present.
+   */
+  addToPopup: function(aMenu, aBrowser, aPopup) {
+    return this.buildAndAttachMenuWithObject(aMenu, aBrowser, aPopup);
+  }
+}
+
+// This object is expected to be used from a child process.
+this.PageMenuChild = function PageMenuChild() {
+}
+
+PageMenuChild.prototype = {
+  __proto__ : PageMenu.prototype,
+
+  /*
+   * Given a target node, return a JSON object for the custom menu commands. The
+   * object will consist of a hierarchical structure of menus, menuitems or
+   * separators. Supported properties of each are:
+   *   Menu: children, label, type="menu"
+   *   Menuitems: checkbox, checked, disabled, icon, label, type="menuitem"
+   *   Separators: type="separator"
+   *
+   * In addition, the id of each item will be used to identify the item
+   * when it is executed. The type will either be 'menu', 'menuitem' or
+   * 'separator'. The toplevel node will be a menu with a children property. The
+   * children property of a menu is an array of zero or more other items.
+   *
+   * If there is no menu associated with aTarget, null will be returned.
+   */
+  build: function(aTarget) {
+    return this.maybeBuild(aTarget);
+  },
+
+  /*
+   * Given the id of a menu, execute the command associated with that menu. It
+   * is assumed that only one command will be executed so the builder is
+   * cleared afterwards.
+   */
+  executeMenu: function(aId) {
+    if (this._builder) {
+      this._builder.click(aId);
+      this._builder = null;
+    }
+  }
+}
--- a/widget/gonk/nativewindow/FakeSurfaceComposer.cpp
+++ b/widget/gonk/nativewindow/FakeSurfaceComposer.cpp
@@ -18,16 +18,20 @@
 #include <stdint.h>
 #include <sys/types.h>
 #include <errno.h>
 #include <cutils/log.h>
 
 #include <gui/IDisplayEventConnection.h>
 #include <gui/GraphicBufferAlloc.h>
 
+#if ANDROID_VERSION >= 21
+#include <ui/Rect.h>
+#endif
+
 #include "FakeSurfaceComposer.h"
 
 namespace android {
 
 /* static */
 void FakeSurfaceComposer::instantiate() {
     defaultServiceManager()->addService(
             String16("SurfaceFlinger"), new FakeSurfaceComposer());
@@ -84,36 +88,89 @@ bool FakeSurfaceComposer::authenticateSu
         const sp<IGraphicBufferProducer>& bufferProducer) const {
     return false;
 }
 
 sp<IDisplayEventConnection> FakeSurfaceComposer::createDisplayEventConnection() {
     return nullptr;
 }
 
-status_t FakeSurfaceComposer::captureScreen(const sp<IBinder>& display,
-        const sp<IGraphicBufferProducer>& producer,
-        uint32_t reqWidth, uint32_t reqHeight,
-        uint32_t minLayerZ, uint32_t maxLayerZ,
-        bool isCpuConsumer) {
+status_t
+FakeSurfaceComposer::captureScreen(const sp<IBinder>& display
+                                 , const sp<IGraphicBufferProducer>& producer
+#if ANDROID_VERSION >= 21
+                                 , Rect sourceCrop
+#endif
+                                 , uint32_t reqWidth
+                                 , uint32_t reqHeight
+                                 , uint32_t minLayerZ
+                                 , uint32_t maxLayerZ
+#if ANDROID_VERSION >= 21
+                                 , bool useIdentityTransform
+                                 , Rotation rotation
+#elif ANDROID_VERSION < 19
+                                 , bool isCpuConsumer
+#endif
+                                  )
+{
+    return INVALID_OPERATION;
+}
+
+#if ANDROID_VERSION >= 21
+void
+FakeSurfaceComposer::setPowerMode(const sp<IBinder>& display, int mode)
+{
+}
+
+status_t
+FakeSurfaceComposer::getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayInfo>* configs)
+{
     return INVALID_OPERATION;
 }
 
-#if ANDROID_VERSION >= 19
-status_t FakeSurfaceComposer::captureScreen(const sp<IBinder>& display,
-    const sp<IGraphicBufferProducer>& producer,
-    uint32_t reqWidth, uint32_t reqHeight,
-    uint32_t minLayerZ, uint32_t maxLayerZ) {
+status_t
+FakeSurfaceComposer::getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats)
+{
+    return INVALID_OPERATION;
+}
+
+int
+FakeSurfaceComposer::getActiveConfig(const sp<IBinder>& display)
+{
+    return INVALID_OPERATION;
+}
+
+status_t
+FakeSurfaceComposer::setActiveConfig(const sp<IBinder>& display, int id)
+{
+    return INVALID_OPERATION;
+}
+
+status_t
+FakeSurfaceComposer::clearAnimationFrameStats()
+{
+    return INVALID_OPERATION;
+}
+
+status_t
+FakeSurfaceComposer::getAnimationFrameStats(FrameStats* outStats) const
+{
+    return INVALID_OPERATION;
+}
+#else
+void
+FakeSurfaceComposer::blank(const sp<IBinder>& display)
+{
+}
+
+void
+FakeSurfaceComposer::unblank(const sp<IBinder>& display)
+{
+}
+
+status_t
+FakeSurfaceComposer::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info)
+{
     return INVALID_OPERATION;
 }
 #endif
 
-void FakeSurfaceComposer::blank(const sp<IBinder>& display) {
-}
-
-void FakeSurfaceComposer::unblank(const sp<IBinder>& display) {
-}
-
-status_t FakeSurfaceComposer::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) {
-    return INVALID_OPERATION;
-}
-
 }; // namespace android
--- a/widget/gonk/nativewindow/FakeSurfaceComposer.h
+++ b/widget/gonk/nativewindow/FakeSurfaceComposer.h
@@ -40,20 +40,38 @@ class FakeSurfaceComposer : public Binde
 public:
     static char const* getServiceName() {
         return "FakeSurfaceComposer";
     }
 
     // Instantiate MediaResourceManagerService and register to service manager.
     // If service manager is not present, wait until service manager becomes present.
     static  void instantiate();
+
 #if ANDROID_VERSION >= 19
     virtual void destroyDisplay(const sp<android::IBinder>& display);
-    virtual status_t captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer,
-            uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ);
+#endif
+
+#if ANDROID_VERSION >= 21
+    virtual status_t captureScreen(const sp<IBinder>& display,
+                                   const sp<IGraphicBufferProducer>& producer,
+                                   Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+                                   uint32_t minLayerZ, uint32_t maxLayerZ,
+                                   bool useIdentityTransform,
+                                   Rotation rotation = eRotateNone);
+#elif ANDROID_VERSION >= 19
+    virtual status_t captureScreen(const sp<IBinder>& display,
+                                   const sp<IGraphicBufferProducer>& producer,
+                                   uint32_t reqWidth, uint32_t reqHeight,
+                                   uint32_t minLayerZ, uint32_t maxLayerZ);
+#else
+    virtual status_t captureScreen(const sp<IBinder>& display,
+                                   const sp<IGraphicBufferProducer>& producer,
+                                   uint32_t reqWidth, uint32_t reqHeight,
+                                   uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer);
 #endif
 
 private:
     FakeSurfaceComposer();
     // We're reference counted, never destroy FakeSurfaceComposer directly
     virtual ~FakeSurfaceComposer();
 
     /* ------------------------------------------------------------------------
@@ -64,24 +82,30 @@ private:
     virtual sp<IBinder> createDisplay(const String8& displayName, bool secure);
     virtual sp<IBinder> getBuiltInDisplay(int32_t id);
     virtual void setTransactionState(const Vector<ComposerState>& state,
             const Vector<DisplayState>& displays, uint32_t flags);
     virtual void bootFinished();
     virtual bool authenticateSurfaceTexture(
         const sp<IGraphicBufferProducer>& bufferProducer) const;
     virtual sp<IDisplayEventConnection> createDisplayEventConnection();
-    virtual status_t captureScreen(const sp<IBinder>& display,
-            const sp<IGraphicBufferProducer>& producer,
-            uint32_t reqWidth, uint32_t reqHeight,
-            uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer);
+#if ANDROID_VERSION >= 21
+    virtual void setPowerMode(const sp<IBinder>& display, int mode);
+    virtual status_t getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayInfo>* configs);
+    virtual status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats);
+    virtual int getActiveConfig(const sp<IBinder>& display);
+    virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
+    virtual status_t clearAnimationFrameStats();
+    virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
+#elif ANDROID_VERSION >= 17
     // called when screen needs to turn off
     virtual void blank(const sp<IBinder>& display);
     // called when screen is turning back on
     virtual void unblank(const sp<IBinder>& display);
     virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info);
+#endif
 
 };
 
 // ---------------------------------------------------------------------------
 }; // namespace android
 
 #endif // NATIVEWINDOW_FAKE_SURFACE_COMPOSER_H
old mode 100755
new mode 100644
--- a/widget/gonk/nativewindow/GonkBufferQueue.h
+++ b/widget/gonk/nativewindow/GonkBufferQueue.h
@@ -8,13 +8,15 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
+# include "GonkBufferQueueLL.h"
+#elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19
 # include "GonkBufferQueueKK.h"
 #elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
 # include "GonkBufferQueueJB.h"
 #endif
old mode 100755
new mode 100644
old mode 100755
new mode 100644
--- a/widget/gonk/nativewindow/GonkBufferQueueKK.h
+++ b/widget/gonk/nativewindow/GonkBufferQueueKK.h
@@ -329,17 +329,16 @@ public:
 
 private:
     // freeBufferLocked frees the GraphicBuffer and sync resources for the
     // given slot.
     //void freeBufferLocked(int index);
 
     // freeAllBuffersLocked frees the GraphicBuffer and sync resources for
     // all slots.
-    //void freeAllBuffersLocked();
     void freeAllBuffersLocked();
 
     // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
     // that will be used if the producer does not override the buffer slot
     // count.  The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
     // The initial default is 2.
     status_t setDefaultMaxBufferCountLocked(int count);
 
new file mode 100644
--- /dev/null
+++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ * Copyright (C) 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GonkBufferItem.h"
+
+#include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
+
+#include <system/window.h>
+
+namespace android {
+
+GonkBufferItem::GonkBufferItem() :
+    mTransform(0),
+    mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
+    mTimestamp(0),
+    mIsAutoTimestamp(false),
+    mFrameNumber(0),
+    mSlot(INVALID_BUFFER_SLOT),
+    mIsDroppable(false),
+    mAcquireCalled(false),
+    mTransformToDisplayInverse(false) {
+    mCrop.makeInvalid();
+}
+
+GonkBufferItem::operator IGonkGraphicBufferConsumer::BufferItem() const {
+    IGonkGraphicBufferConsumer::BufferItem bufferItem;
+    bufferItem.mGraphicBuffer = mGraphicBuffer;
+    bufferItem.mFence = mFence;
+    bufferItem.mCrop = mCrop;
+    bufferItem.mTransform = mTransform;
+    bufferItem.mScalingMode = mScalingMode;
+    bufferItem.mTimestamp = mTimestamp;
+    bufferItem.mIsAutoTimestamp = mIsAutoTimestamp;
+    bufferItem.mFrameNumber = mFrameNumber;
+    bufferItem.mBuf = mSlot;
+    bufferItem.mIsDroppable = mIsDroppable;
+    bufferItem.mAcquireCalled = mAcquireCalled;
+    bufferItem.mTransformToDisplayInverse = mTransformToDisplayInverse;
+    return bufferItem;
+}
+
+size_t GonkBufferItem::getPodSize() const {
+    size_t c =  sizeof(mCrop) +
+            sizeof(mTransform) +
+            sizeof(mScalingMode) +
+            sizeof(mTimestamp) +
+            sizeof(mIsAutoTimestamp) +
+            sizeof(mFrameNumber) +
+            sizeof(mSlot) +
+            sizeof(mIsDroppable) +
+            sizeof(mAcquireCalled) +
+            sizeof(mTransformToDisplayInverse);
+    return c;
+}
+
+size_t GonkBufferItem::getFlattenedSize() const {
+    size_t c = 0;
+    if (mGraphicBuffer != 0) {
+        c += mGraphicBuffer->getFlattenedSize();
+        FlattenableUtils::align<4>(c);
+    }
+    if (mFence != 0) {
+        c += mFence->getFlattenedSize();
+        FlattenableUtils::align<4>(c);
+    }
+    return sizeof(int32_t) + c + getPodSize();
+}
+
+size_t GonkBufferItem::getFdCount() const {
+    size_t c = 0;
+    if (mGraphicBuffer != 0) {
+        c += mGraphicBuffer->getFdCount();
+    }
+    if (mFence != 0) {
+        c += mFence->getFdCount();
+    }
+    return c;
+}
+
+status_t GonkBufferItem::flatten(
+        void*& buffer, size_t& size, int*& fds, size_t& count) const {
+
+    // make sure we have enough space
+    if (count < GonkBufferItem::getFlattenedSize()) {
+        return NO_MEMORY;
+    }
+
+    // content flags are stored first
+    uint32_t& flags = *static_cast<uint32_t*>(buffer);
+
+    // advance the pointer
+    FlattenableUtils::advance(buffer, size, sizeof(uint32_t));
+
+    flags = 0;
+    if (mGraphicBuffer != 0) {
+        status_t err = mGraphicBuffer->flatten(buffer, size, fds, count);
+        if (err) return err;
+        size -= FlattenableUtils::align<4>(buffer);
+        flags |= 1;
+    }
+    if (mFence != 0) {
+        status_t err = mFence->flatten(buffer, size, fds, count);
+        if (err) return err;
+        size -= FlattenableUtils::align<4>(buffer);
+        flags |= 2;
+    }
+
+    // check we have enough space (in case flattening the fence/graphicbuffer lied to us)
+    if (size < getPodSize()) {
+        return NO_MEMORY;
+    }
+
+    FlattenableUtils::write(buffer, size, mCrop);
+    FlattenableUtils::write(buffer, size, mTransform);
+    FlattenableUtils::write(buffer, size, mScalingMode);
+    FlattenableUtils::write(buffer, size, mTimestamp);
+    FlattenableUtils::write(buffer, size, mIsAutoTimestamp);
+    FlattenableUtils::write(buffer, size, mFrameNumber);
+    FlattenableUtils::write(buffer, size, mSlot);
+    FlattenableUtils::write(buffer, size, mIsDroppable);
+    FlattenableUtils::write(buffer, size, mAcquireCalled);
+    FlattenableUtils::write(buffer, size, mTransformToDisplayInverse);
+
+    return NO_ERROR;
+}
+
+status_t GonkBufferItem::unflatten(
+        void const*& buffer, size_t& size, int const*& fds, size_t& count) {
+
+    if (size < sizeof(uint32_t))
+        return NO_MEMORY;
+
+    uint32_t flags = 0;
+    FlattenableUtils::read(buffer, size, flags);
+
+    if (flags & 1) {
+        mGraphicBuffer = new GraphicBuffer();
+        status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count);
+        if (err) return err;
+        size -= FlattenableUtils::align<4>(buffer);
+    }
+
+    if (flags & 2) {
+        mFence = new Fence();
+        status_t err = mFence->unflatten(buffer, size, fds, count);
+        if (err) return err;
+        size -= FlattenableUtils::align<4>(buffer);
+    }
+
+    // check we have enough space
+    if (size < getPodSize()) {
+        return NO_MEMORY;
+    }
+
+    FlattenableUtils::read(buffer, size, mCrop);
+    FlattenableUtils::read(buffer, size, mTransform);
+    FlattenableUtils::read(buffer, size, mScalingMode);
+    FlattenableUtils::read(buffer, size, mTimestamp);
+    FlattenableUtils::read(buffer, size, mIsAutoTimestamp);
+    FlattenableUtils::read(buffer, size, mFrameNumber);
+    FlattenableUtils::read(buffer, size, mSlot);
+    FlattenableUtils::read(buffer, size, mIsDroppable);
+    FlattenableUtils::read(buffer, size, mAcquireCalled);
+    FlattenableUtils::read(buffer, size, mTransformToDisplayInverse);
+
+    return NO_ERROR;
+}
+
+const char* GonkBufferItem::scalingModeName(uint32_t scalingMode) {
+    switch (scalingMode) {
+        case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
+        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
+        case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
+        default: return "Unknown";
+    }
+}
+
+} // namespace android
new file mode 100644
--- /dev/null
+++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferItem.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ * Copyright (C) 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NATIVEWINDOW_GONKBUFFERITEM_LL_H
+#define NATIVEWINDOW_GONKBUFFERITEM_LL_H
+
+#include "IGonkGraphicBufferConsumerLL.h"
+
+#include <ui/Rect.h>
+
+#include <utils/Flattenable.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+class Fence;
+class GraphicBuffer;
+
+class GonkBufferItem : public Flattenable<GonkBufferItem> {
+    friend class Flattenable<GonkBufferItem>;
+    size_t getPodSize() const;
+    size_t getFlattenedSize() const;
+    size_t getFdCount() const;
+    status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
+    status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
+
+    public:
+    // The default value of mBuf, used to indicate this doesn't correspond to a slot.
+    enum { INVALID_BUFFER_SLOT = -1 };
+    GonkBufferItem();
+    operator IGonkGraphicBufferConsumer::BufferItem() const;
+
+    static const char* scalingModeName(uint32_t scalingMode);
+
+    // mGraphicBuffer points to the buffer allocated for this slot, or is NULL
+    // if the buffer in this slot has been acquired in the past (see
+    // BufferSlot.mAcquireCalled).
+    sp<GraphicBuffer> mGraphicBuffer;
+
+    // mFence is a fence that will signal when the buffer is idle.
+    sp<Fence> mFence;
+
+    // mCrop is the current crop rectangle for this buffer slot.
+    Rect mCrop;
+
+    // mTransform is the current transform flags for this buffer slot.
+    // refer to NATIVE_WINDOW_TRANSFORM_* in <window.h>
+    uint32_t mTransform;
+
+    // mScalingMode is the current scaling mode for this buffer slot.
+    // refer to NATIVE_WINDOW_SCALING_* in <window.h>
+    uint32_t mScalingMode;
+
+    // mTimestamp is the current timestamp for this buffer slot. This gets
+    // to set by queueBuffer each time this slot is queued. This value
+    // is guaranteed to be monotonically increasing for each newly
+    // acquired buffer.
+    int64_t mTimestamp;
+
+    // mIsAutoTimestamp indicates whether mTimestamp was generated
+    // automatically when the buffer was queued.
+    bool mIsAutoTimestamp;
+
+    // mFrameNumber is the number of the queued frame for this slot.
+    uint64_t mFrameNumber;
+
+    // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT).
+    int mSlot;
+
+    // mIsDroppable whether this buffer was queued with the
+    // property that it can be replaced by a new buffer for the purpose of
+    // making sure dequeueBuffer() won't block.
+    // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer
+    // was queued.
+    bool mIsDroppable;
+
+    // Indicates whether this buffer has been seen by a consumer yet
+    bool mAcquireCalled;
+
+    // Indicates this buffer must be transformed by the inverse transform of the screen
+    // it is displayed onto. This is applied after mTransform.
+    bool mTransformToDisplayInverse;
+};
+
+} // namespace android
+
+#endif
new file mode 100644
--- /dev/null
+++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp
@@ -0,0 +1,557 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ * Copyright (C) 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
+
+#define LOG_TAG "GonkBufferQueueConsumer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define LOG_NDEBUG 0
+
+#include "GonkBufferItem.h"
+#include "GonkBufferQueueConsumer.h"
+#include "GonkBufferQueueCore.h"
+#include <gui/IConsumerListener.h>
+#include <gui/IProducerListener.h>
+
+namespace android {
+
+GonkBufferQueueConsumer::GonkBufferQueueConsumer(const sp<GonkBufferQueueCore>& core) :
+    mCore(core),
+    mSlots(core->mSlots),
+    mConsumerName() {}
+
+GonkBufferQueueConsumer::~GonkBufferQueueConsumer() {}
+
+status_t GonkBufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
+        nsecs_t expectedPresent) {
+    ATRACE_CALL();
+    Mutex::Autolock lock(mCore->mMutex);
+
+    // Check that the consumer doesn't currently have the maximum number of
+    // buffers acquired. We allow the max buffer count to be exceeded by one
+    // buffer so that the consumer can successfully set up the newly acquired
+    // buffer before releasing the old one.
+    int numAcquiredBuffers = 0;
+    for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
+        if (mSlots[s].mBufferState == GonkBufferSlot::ACQUIRED) {
+            ++numAcquiredBuffers;
+        }
+    }
+    if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
+        ALOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
+                numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
+        return INVALID_OPERATION;
+    }
+
+    // Check if the queue is empty.
+    // In asynchronous mode the list is guaranteed to be one buffer deep,
+    // while in synchronous mode we use the oldest buffer.
+    if (mCore->mQueue.empty()) {
+        return NO_BUFFER_AVAILABLE;
+    }
+
+    GonkBufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
+
+    // If expectedPresent is specified, we may not want to return a buffer yet.
+    // If it's specified and there's more than one buffer queued, we may want
+    // to drop a buffer.
+    if (expectedPresent != 0) {
+        const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
+
+        // The 'expectedPresent' argument indicates when the buffer is expected
+        // to be presented on-screen. If the buffer's desired present time is
+        // earlier (less) than expectedPresent -- meaning it will be displayed
+        // on time or possibly late if we show it as soon as possible -- we
+        // acquire and return it. If we don't want to display it until after the
+        // expectedPresent time, we return PRESENT_LATER without acquiring it.
+        //
+        // To be safe, we don't defer acquisition if expectedPresent is more
+        // than one second in the future beyond the desired present time
+        // (i.e., we'd be holding the buffer for a long time).
+        //
+        // NOTE: Code assumes monotonic time values from the system clock
+        // are positive.
+
+        // Start by checking to see if we can drop frames. We skip this check if
+        // the timestamps are being auto-generated by Surface. If the app isn't
+        // generating timestamps explicitly, it probably doesn't want frames to
+        // be discarded based on them.
+        while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
+            // If entry[1] is timely, drop entry[0] (and repeat). We apply an
+            // additional criterion here: we only drop the earlier buffer if our
+            // desiredPresent falls within +/- 1 second of the expected present.
+            // Otherwise, bogus desiredPresent times (e.g., 0 or a small
+            // relative timestamp), which normally mean "ignore the timestamp
+            // and acquire immediately", would cause us to drop frames.
+            //
+            // We may want to add an additional criterion: don't drop the
+            // earlier buffer if entry[1]'s fence hasn't signaled yet.
+            const BufferItem& bufferItem(mCore->mQueue[1]);
+            nsecs_t desiredPresent = bufferItem.mTimestamp;
+            if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
+                    desiredPresent > expectedPresent) {
+                // This buffer is set to display in the near future, or
+                // desiredPresent is garbage. Either way we don't want to drop
+                // the previous buffer just to get this on the screen sooner.
+                ALOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%"
+                        PRId64 " (%" PRId64 ") now=%" PRId64,
+                        desiredPresent, expectedPresent,
+                        desiredPresent - expectedPresent,
+                        systemTime(CLOCK_MONOTONIC));
+                break;
+            }
+
+            ALOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
+                    " size=%zu",
+                    desiredPresent, expectedPresent, mCore->mQueue.size());
+            if (mCore->stillTracking(front)) {
+                // Front buffer is still in mSlots, so mark the slot as free
+                mSlots[front->mSlot].mBufferState = GonkBufferSlot::FREE;
+            }
+            mCore->mQueue.erase(front);
+            front = mCore->mQueue.begin();
+        }
+
+        // See if the front buffer is due
+        nsecs_t desiredPresent = front->mTimestamp;
+        if (desiredPresent > expectedPresent &&
+                desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) {
+            ALOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
+                    " (%" PRId64 ") now=%" PRId64,
+                    desiredPresent, expectedPresent,
+                    desiredPresent - expectedPresent,
+                    systemTime(CLOCK_MONOTONIC));
+            return PRESENT_LATER;
+        }
+
+        ALOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " "
+                "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent,
+                desiredPresent - expectedPresent,
+                systemTime(CLOCK_MONOTONIC));
+    }
+
+    int slot = front->mSlot;
+    //*outBuffer = *front;
+    outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer;
+    outBuffer->mFrameNumber = mSlots[slot].mFrameNumber;
+    outBuffer->mBuf = slot;
+    outBuffer->mFence = mSlots[slot].mFence;
+
+    ATRACE_BUFFER_INDEX(slot);
+
+    ALOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
+            slot, front->mFrameNumber, front->mGraphicBuffer->handle);
+    // If the front buffer is still being tracked, update its slot state
+    if (mCore->stillTracking(front)) {
+        mSlots[slot].mAcquireCalled = true;
+        mSlots[slot].mNeedsCleanupOnRelease = false;
+        mSlots[slot].mBufferState = GonkBufferSlot::ACQUIRED;
+        mSlots[slot].mFence = Fence::NO_FENCE;
+    }
+
+    // If the buffer has previously been acquired by the consumer, set
+    // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
+    // on the consumer side
+    //if (outBuffer->mAcquireCalled) {
+    //    outBuffer->mGraphicBuffer = NULL;
+    //}
+
+    mCore->mQueue.erase(front);
+
+    // We might have freed a slot while dropping old buffers, or the producer
+    // may be blocked waiting for the number of buffers in the queue to
+    // decrease.
+    mCore->mDequeueCondition.broadcast();
+
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueConsumer::detachBuffer(int slot) {
+    ATRACE_CALL();
+    ATRACE_BUFFER_INDEX(slot);
+    ALOGV("detachBuffer(C): slot %d", slot);
+    Mutex::Autolock lock(mCore->mMutex);
+
+    if (mCore->mIsAbandoned) {
+        ALOGE("detachBuffer(C): GonkBufferQueue has been abandoned");
+        return NO_INIT;
+    }
+
+    if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) {
+        ALOGE("detachBuffer(C): slot index %d out of range [0, %d)",
+                slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS);
+        return BAD_VALUE;
+    } else if (mSlots[slot].mBufferState != GonkBufferSlot::ACQUIRED) {
+        ALOGE("detachBuffer(C): slot %d is not owned by the consumer "
+                "(state = %d)", slot, mSlots[slot].mBufferState);
+        return BAD_VALUE;
+    }
+
+    mCore->freeBufferLocked(slot);
+    mCore->mDequeueCondition.broadcast();
+
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueConsumer::attachBuffer(int* outSlot,
+        const sp<android::GraphicBuffer>& buffer) {
+    ATRACE_CALL();
+
+    if (outSlot == NULL) {
+        ALOGE("attachBuffer(P): outSlot must not be NULL");
+        return BAD_VALUE;
+    } else if (buffer == NULL) {
+        ALOGE("attachBuffer(P): cannot attach NULL buffer");
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mCore->mMutex);
+
+    // Make sure we don't have too many acquired buffers and find a free slot
+    // to put the buffer into (the oldest if there are multiple).
+    int numAcquiredBuffers = 0;
+    int found = GonkBufferQueueCore::INVALID_BUFFER_SLOT;
+    for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
+        if (mSlots[s].mBufferState == GonkBufferSlot::ACQUIRED) {
+            ++numAcquiredBuffers;
+        } else if (mSlots[s].mBufferState == GonkBufferSlot::FREE) {
+            if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT ||
+                    mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
+                found = s;
+            }
+        }
+    }
+
+    if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
+        ALOGE("attachBuffer(P): max acquired buffer count reached: %d "
+                "(max %d)", numAcquiredBuffers,
+                mCore->mMaxAcquiredBufferCount);
+        return INVALID_OPERATION;
+    }
+    if (found == GonkBufferQueueCore::INVALID_BUFFER_SLOT) {
+        ALOGE("attachBuffer(P): could not find free buffer slot");
+        return NO_MEMORY;
+    }
+
+    *outSlot = found;
+    ATRACE_BUFFER_INDEX(*outSlot);
+    ALOGV("attachBuffer(C): returning slot %d", *outSlot);
+
+    mSlots[*outSlot].mGraphicBuffer = buffer;
+    mSlots[*outSlot].mBufferState = GonkBufferSlot::ACQUIRED;
+    mSlots[*outSlot].mAttachedByConsumer = true;
+    mSlots[*outSlot].mNeedsCleanupOnRelease = false;
+    mSlots[*outSlot].mFence = Fence::NO_FENCE;
+    mSlots[*outSlot].mFrameNumber = 0;
+
+    // mAcquireCalled tells GonkBufferQueue that it doesn't need to send a valid
+    // GraphicBuffer pointer on the next acquireBuffer call, which decreases
+    // Binder traffic by not un/flattening the GraphicBuffer. However, it
+    // requires that the consumer maintain a cached copy of the slot <--> buffer
+    // mappings, which is why the consumer doesn't need the valid pointer on
+    // acquire.
+    //
+    // The StreamSplitter is one of the primary users of the attach/detach
+    // logic, and while it is running, all buffers it acquires are immediately
+    // detached, and all buffers it eventually releases are ones that were
+    // attached (as opposed to having been obtained from acquireBuffer), so it
+    // doesn't make sense to maintain the slot/buffer mappings, which would
+    // become invalid for every buffer during detach/attach. By setting this to
+    // false, the valid GraphicBuffer pointer will always be sent with acquire
+    // for attached buffers.
+    mSlots[*outSlot].mAcquireCalled = false;
+
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
+        const sp<Fence>& releaseFence) {
+    ATRACE_CALL();
+
+    if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS ||
+            releaseFence == NULL) {
+        return BAD_VALUE;
+    }
+
+    sp<IProducerListener> listener;
+    { // Autolock scope
+        Mutex::Autolock lock(mCore->mMutex);
+
+        // If the frame number has changed because the buffer has been reallocated,
+        // we can ignore this releaseBuffer for the old buffer
+        //if (frameNumber != mSlots[slot].mFrameNumber) {
+        //    return STALE_BUFFER_SLOT;
+        //}
+
+        // Make sure this buffer hasn't been queued while acquired by the consumer
+        GonkBufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
+        while (current != mCore->mQueue.end()) {
+            if (current->mSlot == slot) {
+                ALOGE("releaseBuffer: buffer slot %d pending release is "
+                        "currently queued", slot);
+                return BAD_VALUE;
+            }
+            ++current;
+        }
+
+        if (mSlots[slot].mBufferState == GonkBufferSlot::ACQUIRED) {
+            mSlots[slot].mFence = releaseFence;
+            mSlots[slot].mBufferState = GonkBufferSlot::FREE;
+            listener = mCore->mConnectedProducerListener;
+            ALOGV("releaseBuffer: releasing slot %d", slot);
+        } else if (mSlots[slot].mNeedsCleanupOnRelease) {
+            ALOGV("releaseBuffer: releasing a stale buffer slot %d "
+                    "(state = %d)", slot, mSlots[slot].mBufferState);
+            mSlots[slot].mNeedsCleanupOnRelease = false;
+            return STALE_BUFFER_SLOT;
+        } else {
+            ALOGV("releaseBuffer: attempted to release buffer slot %d "
+                    "but its state was %d", slot, mSlots[slot].mBufferState);
+            return BAD_VALUE;
+        }
+
+        mCore->mDequeueCondition.broadcast();
+    } // Autolock scope
+
+    // Call back without lock held
+    if (listener != NULL) {
+        listener->onBufferReleased();
+    }
+
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueConsumer::connect(
+        const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
+    ATRACE_CALL();
+
+    if (consumerListener == NULL) {
+        ALOGE("connect(C): consumerListener may not be NULL");
+        return BAD_VALUE;
+    }
+
+    ALOGV("connect(C): controlledByApp=%s",
+            controlledByApp ? "true" : "false");
+
+    Mutex::Autolock lock(mCore->mMutex);
+
+    if (mCore->mIsAbandoned) {
+        ALOGE("connect(C): GonkBufferQueue has been abandoned");
+        return NO_INIT;
+    }
+
+    mCore->mConsumerListener = consumerListener;
+    mCore->mConsumerControlledByApp = controlledByApp;
+
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueConsumer::disconnect() {
+    ATRACE_CALL();
+
+    ALOGV("disconnect(C)");
+
+    Mutex::Autolock lock(mCore->mMutex);
+
+    if (mCore->mConsumerListener == NULL) {
+        ALOGE("disconnect(C): no consumer is connected");
+        return BAD_VALUE;
+    }
+
+    mCore->mIsAbandoned = true;
+    mCore->mConsumerListener = NULL;
+    mCore->mQueue.clear();
+    mCore->freeAllBuffersLocked();
+    mCore->mDequeueCondition.broadcast();
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) {
+    ATRACE_CALL();
+
+    if (outSlotMask == NULL) {
+        ALOGE("getReleasedBuffers: outSlotMask may not be NULL");
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mCore->mMutex);
+
+    if (mCore->mIsAbandoned) {
+        ALOGE("getReleasedBuffers: GonkBufferQueue has been abandoned");
+        return NO_INIT;
+    }
+
+    uint64_t mask = 0;
+    for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
+        if (!mSlots[s].mAcquireCalled) {
+            mask |= (1ULL << s);
+        }
+    }
+
+    // Remove from the mask queued buffers for which acquire has been called,
+    // since the consumer will not receive their buffer addresses and so must
+    // retain their cached information
+    GonkBufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
+    while (current != mCore->mQueue.end()) {
+        if (current->mAcquireCalled) {
+            mask &= ~(1ULL << current->mSlot);
+        }
+        ++current;
+    }
+
+    ALOGV("getReleasedBuffers: returning mask %#" PRIx64, mask);
+    *outSlotMask = mask;
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueConsumer::setDefaultBufferSize(uint32_t width,
+        uint32_t height) {
+    ATRACE_CALL();
+
+    if (width == 0 || height == 0) {
+        ALOGV("setDefaultBufferSize: dimensions cannot be 0 (width=%u "
+                "height=%u)", width, height);
+        return BAD_VALUE;
+    }
+
+    ALOGV("setDefaultBufferSize: width=%u height=%u", width, height);
+
+    Mutex::Autolock lock(mCore->mMutex);
+    mCore->mDefaultWidth = width;
+    mCore->mDefaultHeight = height;
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueConsumer::setDefaultMaxBufferCount(int bufferCount) {
+    ATRACE_CALL();
+    Mutex::Autolock lock(mCore->mMutex);
+    return mCore->setDefaultMaxBufferCountLocked(bufferCount);
+}
+
+status_t GonkBufferQueueConsumer::disableAsyncBuffer() {
+    ATRACE_CALL();
+
+    Mutex::Autolock lock(mCore->mMutex);
+
+    if (mCore->mConsumerListener != NULL) {
+        ALOGE("disableAsyncBuffer: consumer already connected");
+        return INVALID_OPERATION;
+    }
+
+    ALOGV("disableAsyncBuffer");
+    mCore->mUseAsyncBuffer = false;
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueConsumer::setMaxAcquiredBufferCount(
+        int maxAcquiredBuffers) {
+    ATRACE_CALL();
+
+    if (maxAcquiredBuffers < 1 ||
+            maxAcquiredBuffers > GonkBufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) {
+        ALOGE("setMaxAcquiredBufferCount: invalid count %d",
+                maxAcquiredBuffers);
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mCore->mMutex);
+
+    if (mCore->mConnectedApi != GonkBufferQueueCore::NO_CONNECTED_API) {
+        ALOGE("setMaxAcquiredBufferCount: producer is already connected");
+        return INVALID_OPERATION;
+    }
+
+    ALOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
+    mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
+    return NO_ERROR;
+}
+
+void GonkBufferQueueConsumer::setConsumerName(const String8& name) {
+    ATRACE_CALL();
+    ALOGV("setConsumerName: '%s'", name.string());
+    Mutex::Autolock lock(mCore->mMutex);
+    mCore->mConsumerName = name;
+    mConsumerName = name;
+}
+
+status_t GonkBufferQueueConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
+    ATRACE_CALL();
+    ALOGV("setDefaultBufferFormat: %u", defaultFormat);
+    Mutex::Autolock lock(mCore->mMutex);
+    mCore->mDefaultBufferFormat = defaultFormat;
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueConsumer::setConsumerUsageBits(uint32_t usage) {
+    ATRACE_CALL();
+    ALOGV("setConsumerUsageBits: %#x", usage);
+    Mutex::Autolock lock(mCore->mMutex);
+    mCore->mConsumerUsageBits = usage;
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueConsumer::setTransformHint(uint32_t hint) {
+    ATRACE_CALL();
+    ALOGV("setTransformHint: %#x", hint);
+    Mutex::Autolock lock(mCore->mMutex);
+    mCore->mTransformHint = hint;
+    return NO_ERROR;
+}
+
+sp<NativeHandle> GonkBufferQueueConsumer::getSidebandStream() const {
+    return mCore->mSidebandStream;
+}
+
+void GonkBufferQueueConsumer::dump(String8& result, const char* prefix) const {
+    mCore->dump(result, prefix);
+}
+
+TemporaryRef<GonkBufferSlot::TextureClient>
+GonkBufferQueueConsumer::getTextureClientFromBuffer(ANativeWindowBuffer* buffer)
+{
+    Mutex::Autolock _l(mCore->mMutex);
+    if (buffer == NULL) {
+        ALOGE("getSlotFromBufferLocked: encountered NULL buffer");
+        return nullptr;
+    }
+
+    for (int i = 0; i < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
+        if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) {
+            return mSlots[i].mTextureClient;
+        }
+    }
+    ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
+    return nullptr;
+}
+
+int
+GonkBufferQueueConsumer::getSlotFromTextureClientLocked(GonkBufferSlot::TextureClient* client) const
+{
+    if (client == NULL) {
+        ALOGE("getSlotFromBufferLocked: encountered NULL buffer");
+        return BAD_VALUE;
+    }
+
+    for (int i = 0; i < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
+        if (mSlots[i].mTextureClient == client) {
+            return i;
+        }
+    }
+    ALOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client);
+    return BAD_VALUE;
+}
+} // namespace android
new file mode 100644
--- /dev/null
+++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ * Copyright (C) 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NATIVEWINDOW_GONKBUFFERQUEUECONSUMER_LL_H
+#define NATIVEWINDOW_GONKBUFFERQUEUECONSUMER_LL_H
+
+#include "GonkBufferQueueDefs.h"
+#include "IGonkGraphicBufferConsumerLL.h"
+
+namespace android {
+
+class GonkBufferQueueCore;
+
+class GonkBufferQueueConsumer : public BnGonkGraphicBufferConsumer {
+
+public:
+    GonkBufferQueueConsumer(const sp<GonkBufferQueueCore>& core);
+    virtual ~GonkBufferQueueConsumer();
+
+    // acquireBuffer attempts to acquire ownership of the next pending buffer in
+    // the GonkBufferQueue. If no buffer is pending then it returns
+    // NO_BUFFER_AVAILABLE. If a buffer is successfully acquired, the
+    // information about the buffer is returned in BufferItem.  If the buffer
+    // returned had previously been acquired then the BufferItem::mGraphicBuffer
+    // field of buffer is set to NULL and it is assumed that the consumer still
+    // holds a reference to the buffer.
+    //
+    // If expectedPresent is nonzero, it indicates the time when the buffer
+    // will be displayed on screen. If the buffer's timestamp is farther in the
+    // future, the buffer won't be acquired, and PRESENT_LATER will be
+    // returned.  The presentation time is in nanoseconds, and the time base
+    // is CLOCK_MONOTONIC.
+    virtual status_t acquireBuffer(BufferItem* outBuffer,
+            nsecs_t expectedPresent);
+
+    // See IGonkGraphicBufferConsumer::detachBuffer
+    virtual status_t detachBuffer(int slot);
+
+    // See IGonkGraphicBufferConsumer::attachBuffer
+    virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer);
+
+    // releaseBuffer releases a buffer slot from the consumer back to the
+    // GonkBufferQueue.  This may be done while the buffer's contents are still
+    // being accessed.  The fence will signal when the buffer is no longer
+    // in use. frameNumber is used to indentify the exact buffer returned.
+    //
+    // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
+    // any references to the just-released buffer that it might have, as if it
+    // had received a onBuffersReleased() call with a mask set for the released
+    // buffer.
+    virtual status_t releaseBuffer(int slot, uint64_t frameNumber,
+            const sp<Fence>& releaseFence);
+
+    // connect connects a consumer to the GonkBufferQueue.  Only one
+    // consumer may be connected, and when that consumer disconnects the
+    // GonkBufferQueue is placed into the "abandoned" state, causing most
+    // interactions with the GonkBufferQueue by the producer to fail.
+    // controlledByApp indicates whether the consumer is controlled by
+    // the application.
+    //
+    // consumerListener may not be NULL.
+    virtual status_t connect(const sp<IConsumerListener>& consumerListener,
+            bool controlledByApp);
+
+    // disconnect disconnects a consumer from the GonkBufferQueue. All
+    // buffers will be freed and the GonkBufferQueue is placed in the "abandoned"
+    // state, causing most interactions with the GonkBufferQueue by the producer to
+    // fail.
+    virtual status_t disconnect();
+
+    // getReleasedBuffers sets the value pointed to by outSlotMask to a bit mask
+    // indicating which buffer slots have been released by the GonkBufferQueue
+    // but have not yet been released by the consumer.
+    //
+    // This should be called from the onBuffersReleased() callback.
+    virtual status_t getReleasedBuffers(uint64_t* outSlotMask);
+
+    // setDefaultBufferSize is used to set the size of buffers returned by
+    // dequeueBuffer when a width and height of zero is requested.  Default
+    // is 1x1.
+    virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height);
+
+    // setDefaultMaxBufferCount sets the default value for the maximum buffer
+    // count (the initial default is 2). If the producer has requested a
+    // buffer count using setBufferCount, the default buffer count will only
+    // take effect if the producer sets the count back to zero.
+    //
+    // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
+    virtual status_t setDefaultMaxBufferCount(int bufferCount);
+
+    // disableAsyncBuffer disables the extra buffer used in async mode
+    // (when both producer and consumer have set their "isControlledByApp"
+    // flag) and has dequeueBuffer() return WOULD_BLOCK instead.
+    //
+    // This can only be called before connect().
+    virtual status_t disableAsyncBuffer();
+
+    // setMaxAcquiredBufferCount sets the maximum number of buffers that can
+    // be acquired by the consumer at one time (default 1).  This call will
+    // fail if a producer is connected to the GonkBufferQueue.
+    virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
+
+    // setConsumerName sets the name used in logging
+    virtual void setConsumerName(const String8& name);
+
+    // setDefaultBufferFormat allows the GonkBufferQueue to create
+    // GraphicBuffers of a defaultFormat if no format is specified
+    // in dequeueBuffer.  Formats are enumerated in graphics.h; the
+    // initial default is HAL_PIXEL_FORMAT_RGBA_8888.
+    virtual status_t setDefaultBufferFormat(uint32_t defaultFormat);
+
+    // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
+    // These are merged with the bits passed to dequeueBuffer.  The values are
+    // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
+    virtual status_t setConsumerUsageBits(uint32_t usage);
+
+    // setTransformHint bakes in rotation to buffers so overlays can be used.
+    // The values are enumerated in window.h, e.g.
+    // NATIVE_WINDOW_TRANSFORM_ROT_90.  The default is 0 (no transform).
+    virtual status_t setTransformHint(uint32_t hint);
+
+    // Retrieve the sideband buffer stream, if any.
+    virtual sp<NativeHandle> getSidebandStream() const;
+
+    // dump our state in a String
+    virtual void dump(String8& result, const char* prefix) const;
+
+    // Added by mozilla
+    virtual mozilla::TemporaryRef<GonkBufferSlot::TextureClient> getTextureClientFromBuffer(ANativeWindowBuffer* buffer);
+
+    virtual int getSlotFromTextureClientLocked(GonkBufferSlot::TextureClient* client) const;
+
+    // Functions required for backwards compatibility.
+    // These will be modified/renamed in IGonkGraphicBufferConsumer and will be
+    // removed from this class at that time. See b/13306289.
+    virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
+            bool controlledByApp) {
+        return connect(consumer, controlledByApp);
+    }
+
+    virtual status_t consumerDisconnect() { return disconnect(); }
+
+    // End functions required for backwards compatibility
+
+private:
+    sp<GonkBufferQueueCore> mCore;
+
+    // This references mCore->mSlots. Lock mCore->mMutex while accessing.
+    GonkBufferQueueDefs::SlotsType& mSlots;
+
+    // This is a cached copy of the name stored in the GonkBufferQueueCore.
+    // It's updated during setConsumerName.
+    String8 mConsumerName;
+
+}; // class GonkBufferQueueConsumer
+
+} // namespace android
+
+#endif
new file mode 100644
--- /dev/null
+++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ * Copyright (C) 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GonkBufferQueueCore"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define LOG_NDEBUG 0
+
+#include <inttypes.h>
+
+#include "GonkBufferItem.h"
+#include "GonkBufferQueueCore.h"
+#include <gui/IConsumerListener.h>
+#include <gui/IGraphicBufferAlloc.h>
+#include <gui/IProducerListener.h>
+#include <gui/ISurfaceComposer.h>
+#include <private/gui/ComposerService.h>
+
+#include <cutils/compiler.h>
+#include "mozilla/layers/GrallocTextureClient.h"
+#include "mozilla/layers/ImageBridgeChild.h"
+
+template <typename T>
+static inline T max(T a, T b) { return a > b ? a : b; }
+
+namespace android {
+
+static String8 getUniqueName() {
+    static volatile int32_t counter = 0;
+    return String8::format("unnamed-%d-%d", getpid(),
+            android_atomic_inc(&counter));
+}
+
+GonkBufferQueueCore::GonkBufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
+    mAllocator(allocator),
+    mMutex(),
+    mIsAbandoned(false),
+    mConsumerControlledByApp(false),
+    mConsumerName(getUniqueName()),
+    mConsumerListener(),
+    mConsumerUsageBits(0),
+    mConnectedApi(NO_CONNECTED_API),
+    mConnectedProducerListener(),
+    mSlots(),
+    mQueue(),
+    mOverrideMaxBufferCount(0),
+    mDequeueCondition(),
+    mUseAsyncBuffer(true),
+    mDequeueBufferCannotBlock(false),
+    mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
+    mDefaultWidth(1),
+    mDefaultHeight(1),
+    mDefaultMaxBufferCount(2),
+    mMaxAcquiredBufferCount(1),
+    mBufferHasBeenQueued(false),
+    mFrameCounter(0),
+    mTransformHint(0),
+    mIsAllocating(false),
+    mIsAllocatingCondition()
+{
+    ALOGV("GonkBufferQueueCore");
+}
+
+GonkBufferQueueCore::~GonkBufferQueueCore() {}
+
+void GonkBufferQueueCore::dump(String8& result, const char* prefix) const {
+    Mutex::Autolock lock(mMutex);
+
+    String8 fifo;
+    Fifo::const_iterator current(mQueue.begin());
+    while (current != mQueue.end()) {
+        fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
+                "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n",
+                current->mSlot, current->mGraphicBuffer.get(),
+                current->mCrop.left, current->mCrop.top, current->mCrop.right,
+                current->mCrop.bottom, current->mTransform, current->mTimestamp,
+                GonkBufferItem::scalingModeName(current->mScalingMode));
+        ++current;
+    }
+
+    result.appendFormat("%s-GonkBufferQueue mMaxAcquiredBufferCount=%d, "
+            "mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
+            "default-format=%d, transform-hint=%02x, FIFO(%zu)={%s}\n",
+            prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock,
+            mDefaultWidth, mDefaultHeight, mDefaultBufferFormat, mTransformHint,
+            mQueue.size(), fifo.string());
+
+    // Trim the free buffers so as to not spam the dump
+    int maxBufferCount = 0;
+    for (int s = GonkBufferQueueDefs::NUM_BUFFER_SLOTS - 1; s >= 0; --s) {
+        const GonkBufferSlot& slot(mSlots[s]);
+        if (slot.mBufferState != GonkBufferSlot::FREE ||
+                slot.mGraphicBuffer != NULL) {
+            maxBufferCount = s + 1;
+            break;
+        }
+    }
+
+    for (int s = 0; s < maxBufferCount; ++s) {
+        const GonkBufferSlot& slot(mSlots[s]);
+        const sp<GraphicBuffer>& buffer(slot.mGraphicBuffer);
+        result.appendFormat("%s%s[%02d:%p] state=%-8s", prefix,
+                (slot.mBufferState == GonkBufferSlot::ACQUIRED) ? ">" : " ",
+                s, buffer.get(),
+                GonkBufferSlot::bufferStateName(slot.mBufferState));
+
+        if (buffer != NULL) {
+            result.appendFormat(", %p [%4ux%4u:%4u,%3X]", buffer->handle,
+                    buffer->width, buffer->height, buffer->stride,
+                    buffer->format);
+        }
+
+        result.append("\n");
+    }
+}
+
+int GonkBufferQueueCore::getMinUndequeuedBufferCountLocked(bool async) const {
+    // If dequeueBuffer is allowed to error out, we don't have to add an
+    // extra buffer.
+    if (!mUseAsyncBuffer) {
+        return mMaxAcquiredBufferCount;
+    }
+
+    if (mDequeueBufferCannotBlock || async) {
+        return mMaxAcquiredBufferCount + 1;
+    }
+
+    return mMaxAcquiredBufferCount;
+}
+
+int GonkBufferQueueCore::getMinMaxBufferCountLocked(bool async) const {
+    return getMinUndequeuedBufferCountLocked(async) + 1;
+}
+
+int GonkBufferQueueCore::getMaxBufferCountLocked(bool async) const {
+    int minMaxBufferCount = getMinMaxBufferCountLocked(async);
+
+    int maxBufferCount = max(mDefaultMaxBufferCount, minMaxBufferCount);
+    if (mOverrideMaxBufferCount != 0) {
+        assert(mOverrideMaxBufferCount >= minMaxBufferCount);
+        maxBufferCount = mOverrideMaxBufferCount;
+    }
+
+    // Any buffers that are dequeued by the producer or sitting in the queue
+    // waiting to be consumed need to have their slots preserved. Such buffers
+    // will temporarily keep the max buffer count up until the slots no longer
+    // need to be preserved.
+    for (int s = maxBufferCount; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
+        GonkBufferSlot::BufferState state = mSlots[s].mBufferState;
+        if (state == GonkBufferSlot::QUEUED || state == GonkBufferSlot::DEQUEUED) {
+            maxBufferCount = s + 1;
+        }
+    }
+
+    return maxBufferCount;
+}
+
+status_t GonkBufferQueueCore::setDefaultMaxBufferCountLocked(int count) {
+    const int minBufferCount = 2;
+    if (count < minBufferCount || count > GonkBufferQueueDefs::NUM_BUFFER_SLOTS) {
+        ALOGV("setDefaultMaxBufferCount: invalid count %d, should be in "
+                "[%d, %d]",
+                count, minBufferCount, GonkBufferQueueDefs::NUM_BUFFER_SLOTS);
+        return BAD_VALUE;
+    }
+
+    ALOGV("setDefaultMaxBufferCount: setting count to %d", count);
+    mDefaultMaxBufferCount = count;
+    mDequeueCondition.broadcast();
+
+    return NO_ERROR;
+}
+
+void GonkBufferQueueCore::freeBufferLocked(int slot) {
+    ALOGV("freeBufferLocked: slot %d", slot);
+
+    if (mSlots[slot].mTextureClient) {
+        mSlots[slot].mTextureClient->ClearRecycleCallback();
+        // release TextureClient in ImageBridge thread
+        TextureClientReleaseTask* task = new TextureClientReleaseTask(mSlots[slot].mTextureClient);
+        mSlots[slot].mTextureClient = NULL;
+        ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(FROM_HERE, task);
+    }
+    mSlots[slot].mGraphicBuffer.clear();
+    if (mSlots[slot].mBufferState == GonkBufferSlot::ACQUIRED) {
+        mSlots[slot].mNeedsCleanupOnRelease = true;
+    }
+    mSlots[slot].mBufferState = GonkBufferSlot::FREE;
+    mSlots[slot].mFrameNumber = UINT32_MAX;
+    mSlots[slot].mAcquireCalled = false;
+
+    // Destroy fence as GonkBufferQueue now takes ownership
+    mSlots[slot].mFence = Fence::NO_FENCE;
+}
+
+void GonkBufferQueueCore::freeAllBuffersLocked() {
+    ALOGW_IF(!mQueue.isEmpty(),
+            "freeAllBuffersLocked called but mQueue is not empty");
+    mQueue.clear();
+    mBufferHasBeenQueued = false;
+    for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
+        freeBufferLocked(s);
+    }
+}
+
+bool GonkBufferQueueCore::stillTracking(const GonkBufferItem* item) const {
+    const GonkBufferSlot& slot = mSlots[item->mSlot];
+
+    ALOGV("stillTracking: item { slot=%d/%" PRIu64 " buffer=%p } "
+            "slot { slot=%d/%" PRIu64 " buffer=%p }",
+            item->mSlot, item->mFrameNumber,
+            (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0),
+            item->mSlot, slot.mFrameNumber,
+            (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0));
+
+    // Compare item with its original buffer slot. We can check the slot as
+    // the buffer would not be moved to a different slot by the producer.
+    return (slot.mGraphicBuffer != NULL) &&
+           (item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle);
+}
+
+void GonkBufferQueueCore::waitWhileAllocatingLocked() const {
+    ATRACE_CALL();
+    while (mIsAllocating) {
+        mIsAllocatingCondition.wait(mMutex);
+    }
+}
+
+} // namespace android
new file mode 100644
--- /dev/null
+++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueCore.h
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ * Copyright (C) 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NATIVEWINDOW_GONKBUFFERQUEUECORE_LL_H
+#define NATIVEWINDOW_GONKBUFFERQUEUECORE_LL_H
+
+#include "GonkBufferQueueDefs.h"
+#include "GonkBufferSlot.h"
+
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <utils/NativeHandle.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/StrongPointer.h>
+#include <utils/Trace.h>
+#include <utils/Vector.h>
+
+#include "mozilla/layers/TextureClient.h"
+
+#define ATRACE_BUFFER_INDEX(index)
+
+using namespace mozilla;
+using namespace mozilla::gfx;
+using namespace mozilla::layers;
+
+namespace android {
+
+class GonkBufferItem;
+class IConsumerListener;
+class IGraphicBufferAlloc;
+class IProducerListener;
+
+class GonkBufferQueueCore : public virtual RefBase {
+
+    friend class GonkBufferQueueProducer;
+    friend class GonkBufferQueueConsumer;
+
+public:
+    // Used as a placeholder slot number when the value isn't pointing to an
+    // existing buffer.
+    enum { INVALID_BUFFER_SLOT = -1 }; // TODO: Extract from IGBC::BufferItem
+
+    // We reserve two slots in order to guarantee that the producer and
+    // consumer can run asynchronously.
+    enum { MAX_MAX_ACQUIRED_BUFFERS = GonkBufferQueueDefs::NUM_BUFFER_SLOTS - 2 };
+
+    // The default API number used to indicate that no producer is connected
+    enum { NO_CONNECTED_API = 0 };
+
+    typedef Vector<GonkBufferItem> Fifo;
+    typedef mozilla::layers::TextureClient TextureClient;
+
+    // GonkBufferQueueCore manages a pool of gralloc memory slots to be used by
+    // producers and consumers. allocator is used to allocate all the needed
+    // gralloc buffers.
+    GonkBufferQueueCore(const sp<IGraphicBufferAlloc>& allocator = NULL);
+    virtual ~GonkBufferQueueCore();
+
+private:
+    // Dump our state in a string
+    void dump(String8& result, const char* prefix) const;
+
+    int getSlotFromTextureClientLocked(TextureClient* client) const;
+
+    // getMinUndequeuedBufferCountLocked returns the minimum number of buffers
+    // that must remain in a state other than DEQUEUED. The async parameter
+    // tells whether we're in asynchronous mode.
+    int getMinUndequeuedBufferCountLocked(bool async) const;
+
+    // getMinMaxBufferCountLocked returns the minimum number of buffers allowed
+    // given the current GonkBufferQueue state. The async parameter tells whether
+    // we're in asynchonous mode.
+    int getMinMaxBufferCountLocked(bool async) const;
+
+    // getMaxBufferCountLocked returns the maximum number of buffers that can be
+    // allocated at once. This value depends on the following member variables:
+    //
+    //     mDequeueBufferCannotBlock
+    //     mMaxAcquiredBufferCount
+    //     mDefaultMaxBufferCount
+    //     mOverrideMaxBufferCount
+    //     async parameter
+    //
+    // Any time one of these member variables is changed while a producer is
+    // connected, mDequeueCondition must be broadcast.
+    int getMaxBufferCountLocked(bool async) const;
+
+    // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
+    // that will be used if the producer does not override the buffer slot
+    // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. The
+    // initial default is 2.
+    status_t setDefaultMaxBufferCountLocked(int count);
+
+    // freeBufferLocked frees the GraphicBuffer and sync resources for the
+    // given slot.
+    void freeBufferLocked(int slot);
+
+    // freeAllBuffersLocked frees the GraphicBuffer and sync resources for
+    // all slots.
+    void freeAllBuffersLocked();
+
+    // stillTracking returns true iff the buffer item is still being tracked
+    // in one of the slots.
+    bool stillTracking(const GonkBufferItem* item) const;
+
+    // waitWhileAllocatingLocked blocks until mIsAllocating is false.
+    void waitWhileAllocatingLocked() const;
+
+    // mAllocator is the connection to SurfaceFlinger that is used to allocate
+    // new GraphicBuffer objects.
+    sp<IGraphicBufferAlloc> mAllocator;
+
+    // mMutex is the mutex used to prevent concurrent access to the member
+    // variables of GonkBufferQueueCore objects. It must be locked whenever any
+    // member variable is accessed.
+    mutable Mutex mMutex;
+
+    // mIsAbandoned indicates that the GonkBufferQueue will no longer be used to
+    // consume image buffers pushed to it using the IGraphicBufferProducer
+    // interface. It is initialized to false, and set to true in the
+    // consumerDisconnect method. A GonkBufferQueue that is abandoned will return
+    // the NO_INIT error from all IGraphicBufferProducer methods capable of
+    // returning an error.
+    bool mIsAbandoned;
+
+    // mConsumerControlledByApp indicates whether the connected consumer is
+    // controlled by the application.
+    bool mConsumerControlledByApp;
+
+    // mConsumerName is a string used to identify the GonkBufferQueue in log
+    // messages. It is set by the IGraphicBufferConsumer::setConsumerName
+    // method.
+    String8 mConsumerName;
+
+    // mConsumerListener is used to notify the connected consumer of
+    // asynchronous events that it may wish to react to. It is initially
+    // set to NULL and is written by consumerConnect and consumerDisconnect.
+    sp<IConsumerListener> mConsumerListener;
+
+    // mConsumerUsageBits contains flags that the consumer wants for
+    // GraphicBuffers.
+    uint32_t mConsumerUsageBits;
+
+    // mConnectedApi indicates the producer API that is currently connected
+    // to this GonkBufferQueue. It defaults to NO_CONNECTED_API, and gets updated
+    // by the connect and disconnect methods.
+    int mConnectedApi;
+
+    // mConnectedProducerToken is used to set a binder death notification on
+    // the producer.
+    sp<IProducerListener> mConnectedProducerListener;
+
+    // mSlots is an array of buffer slots that must be mirrored on the producer
+    // side. This allows buffer ownership to be transferred between the producer
+    // and consumer without sending a GraphicBuffer over Binder. The entire
+    // array is initialized to NULL at construction time, and buffers are
+    // allocated for a slot when requestBuffer is called with that slot's index.
+    GonkBufferQueueDefs::SlotsType mSlots;
+
+    // mQueue is a FIFO of queued buffers used in synchronous mode.
+    Fifo mQueue;
+
+    // mOverrideMaxBufferCount is the limit on the number of buffers that will
+    // be allocated at one time. This value is set by the producer by calling
+    // setBufferCount. The default is 0, which means that the producer doesn't
+    // care about the number of buffers in the pool. In that case,
+    // mDefaultMaxBufferCount is used as the limit.
+    int mOverrideMaxBufferCount;
+
+    // mDequeueCondition is a condition variable used for dequeueBuffer in
+    // synchronous mode.
+    mutable Condition mDequeueCondition;
+
+    // mUseAsyncBuffer indicates whether an extra buffer is used in async mode
+    // to prevent dequeueBuffer from blocking.
+    bool mUseAsyncBuffer;
+
+    // mDequeueBufferCannotBlock indicates whether dequeueBuffer is allowed to
+    // block. This flag is set during connect when both the producer and
+    // consumer are controlled by the application.
+    bool mDequeueBufferCannotBlock;
+
+    // mDefaultBufferFormat can be set so it will override the buffer format
+    // when it isn't specified in dequeueBuffer.
+    uint32_t mDefaultBufferFormat;
+
+    // mDefaultWidth holds the default width of allocated buffers. It is used
+    // in dequeueBuffer if a width and height of 0 are specified.
+    int mDefaultWidth;
+
+    // mDefaultHeight holds the default height of allocated buffers. It is used
+    // in dequeueBuffer if a width and height of 0 are specified.
+    int mDefaultHeight;
+
+    // mDefaultMaxBufferCount is the default limit on the number of buffers that
+    // will be allocated at one time. This default limit is set by the consumer.
+    // The limit (as opposed to the default limit) may be overriden by the
+    // producer.
+    int mDefaultMaxBufferCount;
+
+    // mMaxAcquiredBufferCount is the number of buffers that the consumer may
+    // acquire at one time. It defaults to 1, and can be changed by the consumer
+    // via setMaxAcquiredBufferCount, but this may only be done while no
+    // producer is connected to the GonkBufferQueue. This value is used to derive
+    // the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer.
+    int mMaxAcquiredBufferCount;
+
+    // mBufferHasBeenQueued is true once a buffer has been queued. It is reset
+    // when something causes all buffers to be freed (e.g., changing the buffer
+    // count).
+    bool mBufferHasBeenQueued;
+
+    // mFrameCounter is the free running counter, incremented on every
+    // successful queueBuffer call and buffer allocation.
+    uint64_t mFrameCounter;
+
+    // mTransformHint is used to optimize for screen rotations.
+    uint32_t mTransformHint;
+
+    // mSidebandStream is a handle to the sideband buffer stream, if any
+    sp<NativeHandle> mSidebandStream;
+
+    // mIsAllocating indicates whether a producer is currently trying to allocate buffers (which
+    // releases mMutex while doing the allocation proper). Producers should not modify any of the
+    // FREE slots while this is true. mIsAllocatingCondition is signaled when this value changes to
+    // false.
+    bool mIsAllocating;
+
+    // mIsAllocatingCondition is a condition variable used by producers to wait until mIsAllocating
+    // becomes false.
+    mutable Condition mIsAllocatingCondition;
+}; // class GonkBufferQueueCore
+
+} // namespace android
+
+#endif
new file mode 100644
--- /dev/null
+++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueDefs.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ * Copyright (C) 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NATIVEWINDOW_BUFFERQUEUECOREDEFS_H
+#define NATIVEWINDOW_BUFFERQUEUECOREDEFS_H
+
+#include "GonkBufferSlot.h"
+
+namespace android {
+    class GonkBufferQueueCore;
+
+    namespace GonkBufferQueueDefs {
+        // GonkBufferQueue will keep track of at most this value of buffers.
+        // Attempts at runtime to increase the number of buffers past this
+        // will fail.
+        enum { NUM_BUFFER_SLOTS = 64 };
+
+        typedef GonkBufferSlot SlotsType[NUM_BUFFER_SLOTS];
+    } // namespace GonkBufferQueueDefs
+} // namespace android
+
+#endif
new file mode 100644
--- /dev/null
+++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GonkBufferQueue"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#define LOG_NDEBUG 0
+
+#include "GonkBufferQueue.h"
+#include "GonkBufferQueueConsumer.h"
+#include "GonkBufferQueueCore.h"
+#include "GonkBufferQueueProducer.h"
+
+namespace android {
+
+GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener(
+        const wp<ConsumerListener>& consumerListener):
+        mConsumerListener(consumerListener) {}
+
+GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
+
+void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() {
+    sp<ConsumerListener> listener(mConsumerListener.promote());
+    if (listener != NULL) {
+        listener->onFrameAvailable();
+    }
+}
+
+void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() {
+    sp<ConsumerListener> listener(mConsumerListener.promote());
+    if (listener != NULL) {
+        listener->onBuffersReleased();
+    }
+}
+
+void GonkBufferQueue::ProxyConsumerListener::onSidebandStreamChanged() {
+    sp<ConsumerListener> listener(mConsumerListener.promote());
+    if (listener != NULL) {
+        listener->onSidebandStreamChanged();
+    }
+}
+
+void GonkBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
+        sp<IGonkGraphicBufferConsumer>* outConsumer,
+        const sp<IGraphicBufferAlloc>& allocator) {
+    LOG_ALWAYS_FATAL_IF(outProducer == NULL,
+            "GonkBufferQueue: outProducer must not be NULL");
+    LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
+            "GonkBufferQueue: outConsumer must not be NULL");
+
+    sp<GonkBufferQueueCore> core(new GonkBufferQueueCore(allocator));
+    LOG_ALWAYS_FATAL_IF(core == NULL,
+            "GonkBufferQueue: failed to create GonkBufferQueueCore");
+
+    sp<IGraphicBufferProducer> producer(new GonkBufferQueueProducer(core));
+    LOG_ALWAYS_FATAL_IF(producer == NULL,
+            "GonkBufferQueue: failed to create GonkBufferQueueProducer");
+
+    sp<IGonkGraphicBufferConsumer> consumer(new GonkBufferQueueConsumer(core));
+    LOG_ALWAYS_FATAL_IF(consumer == NULL,
+            "GonkBufferQueue: failed to create GonkBufferQueueConsumer");
+
+    *outProducer = producer;
+    *outConsumer = consumer;
+}
+
+}; // namespace android
new file mode 100644
--- /dev/null
+++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueLL.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NATIVEWINDOW_GONKBUFFERQUEUE_LL_H
+#define NATIVEWINDOW_GONKBUFFERQUEUE_LL_H
+
+#include "GonkBufferQueueDefs.h"
+#include "IGonkGraphicBufferConsumerLL.h"
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/IConsumerListener.h>
+
+// These are only required to keep other parts of the framework with incomplete
+// dependencies building successfully
+#include <gui/IGraphicBufferAlloc.h>
+
+namespace android {
+
+class GonkBufferQueue {
+public:
+    // GonkBufferQueue will keep track of at most this value of buffers.
+    // Attempts at runtime to increase the number of buffers past this will fail.
+    enum { NUM_BUFFER_SLOTS = GonkBufferQueueDefs::NUM_BUFFER_SLOTS };
+    // Used as a placeholder slot# when the value isn't pointing to an existing buffer.
+    enum { INVALID_BUFFER_SLOT = IGonkGraphicBufferConsumer::BufferItem::INVALID_BUFFER_SLOT };
+    // Alias to <IGonkGraphicBufferConsumer.h> -- please scope from there in future code!
+    enum {
+        NO_BUFFER_AVAILABLE = IGonkGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
+        PRESENT_LATER = IGonkGraphicBufferConsumer::PRESENT_LATER,
+    };
+
+    // When in async mode we reserve two slots in order to guarantee that the
+    // producer and consumer can run asynchronously.
+    enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 };
+
+    // for backward source compatibility
+    typedef ::android::ConsumerListener ConsumerListener;
+    typedef IGonkGraphicBufferConsumer::BufferItem BufferItem;
+
+    // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak
+    // reference to the actual consumer object.  It forwards all calls to that
+    // consumer object so long as it exists.
+    //
+    // This class exists to avoid having a circular reference between the
+    // GonkBufferQueue object and the consumer object.  The reason this can't be a weak
+    // reference in the GonkBufferQueue class is because we're planning to expose the
+    // consumer side of a GonkBufferQueue as a binder interface, which doesn't support
+    // weak references.
+    class ProxyConsumerListener : public BnConsumerListener {
+    public:
+        ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);
+        virtual ~ProxyConsumerListener();
+        virtual void onFrameAvailable();
+        virtual void onBuffersReleased();
+        virtual void onSidebandStreamChanged();
+    private:
+        // mConsumerListener is a weak reference to the IConsumerListener.  This is
+        // the raison d'etre of ProxyConsumerListener.
+        wp<ConsumerListener> mConsumerListener;
+    };
+
+    // GonkBufferQueue manages a pool of gralloc memory slots to be used by
+    // producers and consumers. allocator is used to allocate all the
+    // needed gralloc buffers.
+    static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
+            sp<IGonkGraphicBufferConsumer>* outConsumer,
+            const sp<IGraphicBufferAlloc>& allocator = NULL);
+
+private:
+    GonkBufferQueue(); // Create through createBufferQueue
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // NATIVEWINDOW_GONKBUFFERQUEUE_LL_H
new file mode 100644
--- /dev/null
+++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp
@@ -0,0 +1,860 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ * Copyright (C) 2014 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
+
+#define LOG_TAG "GonkBufferQueueProducer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define LOG_NDEBUG 0
+
+#include "GonkBufferItem.h"
+#include "GonkBufferQueueCore.h"
+#include "GonkBufferQueueProducer.h"
+#include <gui/IConsumerListener.h>
+#include <gui/IGraphicBufferAlloc.h>
+#include <gui/IProducerListener.h>
+
+#include <cutils/compiler.h>
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "mozilla/layers/GrallocTextureClient.h"
+#include "mozilla/layers/ImageBridgeChild.h"
+#include "mozilla/layers/TextureClient.h"
+
+namespace android {
+
+GonkBufferQueueProducer::GonkBufferQueueProducer(const sp<GonkBufferQueueCore>& core) :
+    mCore(core),
+    mSlots(core->mSlots),
+    mConsumerName(),
+    mStickyTransform(0) {}
+
+GonkBufferQueueProducer::~GonkBufferQueueProducer() {}
+
+status_t GonkBufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
+    ATRACE_CALL();
+    ALOGV("requestBuffer: slot %d", slot);
+    Mutex::Autolock lock(mCore->mMutex);
+
+    if (mCore->mIsAbandoned) {
+        ALOGE("requestBuffer: GonkBufferQueue has been abandoned");
+        return NO_INIT;
+    }
+
+    if (slot < 0 || slot >= GonkBufferQueueDefs::NUM_BUFFER_SLOTS) {
+        ALOGE("requestBuffer: slot index %d out of range [0, %d)",
+                slot, GonkBufferQueueDefs::NUM_BUFFER_SLOTS);
+        return BAD_VALUE;
+    } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) {
+        ALOGE("requestBuffer: slot %d is not owned by the producer "
+                "(state = %d)", slot, mSlots[slot].mBufferState);
+        return BAD_VALUE;
+    }
+
+    mSlots[slot].mRequestBufferCalled = true;
+    *buf = mSlots[slot].mGraphicBuffer;
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueProducer::setBufferCount(int bufferCount) {
+    ATRACE_CALL();
+    ALOGV("setBufferCount: count = %d", bufferCount);
+
+    sp<IConsumerListener> listener;
+    { // Autolock scope
+        Mutex::Autolock lock(mCore->mMutex);
+        mCore->waitWhileAllocatingLocked();
+
+        if (mCore->mIsAbandoned) {
+            ALOGE("setBufferCount: GonkBufferQueue has been abandoned");
+            return NO_INIT;
+        }
+
+        if (bufferCount > GonkBufferQueueDefs::NUM_BUFFER_SLOTS) {
+            ALOGE("setBufferCount: bufferCount %d too large (max %d)",
+                    bufferCount, GonkBufferQueueDefs::NUM_BUFFER_SLOTS);
+            return BAD_VALUE;
+        }
+
+        // There must be no dequeued buffers when changing the buffer count.
+        for (int s = 0; s < GonkBufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
+            if (mSlots[s].mBufferState == GonkBufferSlot::DEQUEUED) {
+                ALOGE("setBufferCount: buffer owned by producer");
+                return BAD_VALUE;
+            }
+        }
+
+        if (bufferCount == 0) {
+            mCore->mOverrideMaxBufferCount = 0;
+            mCore->mDequeueCondition.broadcast();
+            return NO_ERROR;
+        }
+
+        const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false);
+        if (bufferCount < minBufferSlots) {
+            ALOGE("setBufferCount: requested buffer count %d is less than "
+                    "minimum %d", bufferCount, minBufferSlots);
+            return BAD_VALUE;
+        }
+
+        // Here we are guaranteed that the producer doesn't have any dequeued
+        // buffers and will release all of its buffer references. We don't
+        // clear the queue, however, so that currently queued buffers still
+        // get displayed.
+        mCore->freeAllBuffersLocked();
+        mCore->mOverrideMaxBufferCount = bufferCount;
+        mCore->mDequeueCondition.broadcast();
+        listener = mCore->mConsumerListener;
+    } // Autolock scope
+
+    // Call back without lock held
+    if (listener != NULL) {
+        listener->onBuffersReleased();
+    }
+
+    return NO_ERROR;
+}
+
+status_t GonkBufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
+        bool async, int* found, status_t* returnFlags) const {
+    bool tryAgain = true;
+    while (tryAgain) {
+        if (mCore->mIsAbandoned) {
+            ALOGE("%s: GonkBufferQueue has been abandoned", caller);