merge b2g-inbound to mozilla-central
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 20 Mar 2014 14:07:58 +0100
changeset 193013 cf485c48b52f283ceab119341b965dcf75234721
parent 192957 2d20e6067412c12c6788397108dc7103037f07be (current diff)
parent 193012 9b44086c1d1c0c449cbf7d18836ffa862ff60c24 (diff)
child 193032 41265909a0fa23feb5cbc80638f6fe4efda5492a
child 193058 131277cc768d8c9fcceeb018188432808d11a731
child 193080 e360e47421248a4bef03bed841b4f9fa19b2a9c0
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone31.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 b2g-inbound to mozilla-central
b2g/app/b2g.js
configure.in
dom/ipc/ContentParent.cpp
dom/mobilemessage/src/MessageUtils.h
dom/tests/mochitest/general/test_interfaces.html
dom/webidl/moz.build
hal/Hal.cpp
hal/HalTypes.h
hal/gonk/GonkHal.cpp
testing/mochitest/b2g-debug.json
testing/mochitest/b2g-desktop.json
testing/mochitest/b2g.json
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -645,16 +645,19 @@ pref("dom.ipc.processPriorityManager.bac
 // The kernel can only accept 6 (OomScoreAdjust, KillUnderKB) pairs. But it is
 // okay, kernel will still kill processes with larger OomScoreAdjust first even
 // its OomScoreAdjust don't have a corresponding KillUnderKB.
 
 pref("hal.processPriorityManager.gonk.MASTER.OomScoreAdjust", 0);
 pref("hal.processPriorityManager.gonk.MASTER.KillUnderKB", 4096);
 pref("hal.processPriorityManager.gonk.MASTER.Nice", 0);
 
+pref("hal.processPriorityManager.gonk.PREALLOC.OomScoreAdjust", 67);
+pref("hal.processPriorityManager.gonk.PREALLOC.Nice", 18);
+
 pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.OomScoreAdjust", 67);
 pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.KillUnderKB", 5120);
 pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.Nice", 0);
 
 pref("hal.processPriorityManager.gonk.FOREGROUND.OomScoreAdjust", 134);
 pref("hal.processPriorityManager.gonk.FOREGROUND.KillUnderKB", 6144);
 pref("hal.processPriorityManager.gonk.FOREGROUND.Nice", 1);
 
new file mode 100644
--- /dev/null
+++ b/b2g/chrome/content/desktop.css
@@ -0,0 +1,59 @@
+#controls {
+  position: absolute;
+  left: 0;
+  bottom:0;
+  right: 0;
+  height: 30px;
+  background-color: -moz-dialog;
+}
+
+#home-button {
+  margin: auto;
+  margin-top: 3px;
+  width: 24px;
+  height: 24px;
+  background: #eee url("images/desktop/home-black.png") center no-repeat;
+  border: 1px solid #888;
+  border-radius: 12px;
+  display: block;
+}
+
+#home-button::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+
+#home-button:hover {
+  background-image: url("images/desktop/home-white.png");
+  background-color: #ccc;
+  border-color: #555;
+}
+
+#home-button.active {
+  background-image: url("images/desktop/home-white.png");
+  background-color: #888;
+  border-color: black;
+}
+
+#rotate-button {
+  position: absolute;
+  top: 3px;
+  bottom: 3px;
+  right: 3px;
+  width: 24px;
+  height: 24px;
+  background: #eee url("images/desktop/rotate.png") center no-repeat;
+  border: 1px solid #888;
+  border-radius: 12px;
+  display: block;
+}
+
+#rotate-button:hover {
+  background-color: #ccc;
+  border-color: #555;
+}
+
+#rotate-button.active {
+  background-color: #888;
+  border-color: black;
+}
--- a/b2g/chrome/content/desktop.js
+++ b/b2g/chrome/content/desktop.js
@@ -1,17 +1,52 @@
 /* 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/. */
 
-window.addEventListener("ContentStart", function(evt) {
-  // Enable touch event shim on desktop that translates mouse events
-  // into touch ones
-  let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {})
+// Enable touch event shim on desktop that translates mouse events
+// into touch ones
+function enableTouch() {
+  let require = Cu.import('resource://gre/modules/devtools/Loader.jsm', {})
                   .devtools.require;
-  let { TouchEventHandler } = require("devtools/touch-events");
+  let { TouchEventHandler } = require('devtools/touch-events');
   let chromeEventHandler = window.QueryInterface(Ci.nsIInterfaceRequestor)
                                  .getInterface(Ci.nsIWebNavigation)
                                  .QueryInterface(Ci.nsIDocShell)
                                  .chromeEventHandler || window;
   let touchEventHandler = new TouchEventHandler(chromeEventHandler);
   touchEventHandler.start();
+}
+
+function setupButtons() {
+  let homeButton = document.getElementById('home-button');
+  if (!homeButton) {
+    // The toolbar only exists in b2g desktop build with
+    // FXOS_SIMULATOR turned on.
+    return;
+  }
+  // The touch event helper is enabled on shell.html document,
+  // so that click events are delayed and it is better to
+  // listen for touch events.
+  homeButton.addEventListener('touchstart', function() {
+    shell.sendChromeEvent({type: 'home-button-press'});
+    homeButton.classList.add('active');
+  });
+  homeButton.addEventListener('touchend', function() {
+    shell.sendChromeEvent({type: 'home-button-release'});
+    homeButton.classList.remove('active');
+  });
+
+  Cu.import("resource://gre/modules/GlobalSimulatorScreen.jsm");
+  let rotateButton = document.getElementById('rotate-button');
+  rotateButton.addEventListener('touchstart', function () {
+    rotateButton.classList.add('active');
+  });
+  rotateButton.addEventListener('touchend', function() {
+    GlobalSimulatorScreen.flipScreen();
+    rotateButton.classList.remove('active');
+  });
+}
+
+window.addEventListener('ContentStart', function() {
+  enableTouch();
+  setupButtons();
 });
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c51187ed49e128d49b64adabf003fd140411477d
GIT binary patch
literal 331
zc$@)C0kr;!P)<h;3K|Lk000e1NJLTq000aC000aK1^@s6R&`wG00006VoOIv0RI60
z0RN!9r;`8x0RTxvK~yNutx&s7#6T3BdER{{^R7fdf-DnI05J(Y5F7<SjA-K|L<|Ku
zL81gIfD*6_2^reVTKl{t=aU6@BH<<PH}ghsfPaY0Ik$AqEdgXdmz+06QFvp_gSGYy
z0Q$av9){sEgz)u?P!z?Hsy-TH4pnsp05QgF7>17+<9P_-4U?qz{xr|?Cu{A#wRR;U
ziDX)5Cn5_~ed)UHJ@ejQsp`G8RwwXAp2V88M{=R6fhnb904G&d-H{x(xsXzlrfIGL
zyl#Fd%koo1#*`A9rnv!ts;X{Drg0plZQBC?kl7VZnPg3}p3f$nY?0@-dMDwpm|we?
dxl`|&eFNOMWnB{Vk-q={002ovPDHLkV1gK|iDUo(
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..43379d0e949ccb5b6664f6e230f47d448e723254
GIT binary patch
literal 276
zc%17D@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&kwj^(N7l!{JxM1({$v}~lo-U3d
z8t0ex8|EEy5ODp!eJ4YxMo{2|bt&5|{j*%W=V}E_X)a({m*BmxRqzyVg524>6je3N
zAD1%Rjo+Vt<I&HxqVc=T*ZL1a77X#0d<Q<s?dj{VQ#yBmqerl?uR|_EeBG%J-AfiP
zN%s_2XqZrPa%*y0$^+4g$t_E=>y~d?5;ZCJ{oJ5i3}+2^=2yPbzqu~REBf|cb@QH^
z54Po&Pr6ciw_PPCd|P;Gtl^x7*IOdnZmi3-ua&p`{CsE3cb@vJz)8z8x7p7w-YUIt
Xdi(biYu9-KJ;mVZ>gTe~DWM4f`2KW(
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9da1b5674dbbf78ed3446dac86f43e81f8e687be
GIT binary patch
literal 657
zc$@)|0&e|@P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00006VoOIv0RI60
z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru-UAH}3<e*d*!BPb0v<_3
zK~y-)rIXD|R8bhlf9K8_7zdgUbu29`TV)|3>7dy^U?GkpmX(o7i(2W%Hf@EVHf^GX
zAyOh{R+>X&LQom@F&aULQ6?BnTH4H=FSQx(+!ozHN+s!qhqHKjp7T8KIj_)lo&PCe
zw&!h{l$Z%v01L1z|7b|S2DktRU<Oiv3d{phKmvO!J@pO#{+?@c71;_D-01A`^xhpf
z^loC(8HvWscH5Rz(Z0g)(c0?gXB!)a0L%I23oVbIjO+#mh1s4*VkTgX#pA_I=UQ3^
zeEuCk8qf_01B$2Wa4^&9Sn0UgoeyY9HF!xR)u03ly~oeA`TWCM0d0f$Cgaoql4|gZ
z1ngZseIB2GI15MuY|q`M73|uneOp*iK79PNdQN|dOCa}lUw;XZ%yDI>uU>AOtE;IR
z10sOq+33r1Z+&A{BpMTIS&~4`*qgT&DP^knR{K;%x%-ZQDIGL)iXQle4o0G}-!oZL
zAme)|oc2~9S*j>=4+$7g>uA89=GKc1*V{Yo##6GMz)E&j=8rOWNeGw*;y`BYiKe>2
zhmW#><#m4{M5O@rK=FRnWK!mV#f<z?eQ_p`y4T%tA9xQq0c8#TEHEvBxw@LFv60bN
zF5So}1PNfmaHOnbAO$2Og89=Yk3D_ydb~^+Su^rWH6USN<7HZj1ceT^FSB25p-?#P
rt~?dq^foSi4k&=sL9_n4{h#Y6+p5l88?BLt00000NkvXXu0mjfSMwh@
--- a/b2g/chrome/content/screen.js
+++ b/b2g/chrome/content/screen.js
@@ -13,17 +13,17 @@ window.addEventListener('ContentStart', 
   // The <browser> element inside it
   let browser = document.getElementById('systemapp');
 
   // Figure out the native resolution of the screen
   let windowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
     .getInterface(Components.interfaces.nsIDOMWindowUtils);
   let hostDPI = windowUtils.displayDPI;
 
-  let DEFAULT_SCREEN = "320x480";
+  let DEFAULT_SCREEN = '320x480';
 
   // This is a somewhat random selection of named screens.
   // Add more to this list when we support more hardware.
   // Data from: http://en.wikipedia.org/wiki/List_of_displays_by_pixel_density
   let screens = {
     iphone: {
       name: 'Apple iPhone', width:320, height:480,  dpi:163
     },
@@ -115,54 +115,111 @@ window.addEventListener('ContentStart', 
       dpi = parseInt(match[4], 10);
     else    // If no DPI, use the actual dpi of the host screen
       dpi = hostDPI;
 
     // If any of the values came out 0 or NaN or undefined, display usage
     if (!width || !height || !dpi)
       usage();
   }
-  
-  // In order to do rescaling, we set the <browser> tag to the specified
-  // width and height, and then use a CSS transform to scale it so that
-  // it appears at the correct size on the host display.  We also set
-  // the size of the <window> element to that scaled target size.
-  let scale = rescale ? hostDPI / dpi : 1;
+
+  Cu.import("resource://gre/modules/GlobalSimulatorScreen.jsm");
+  function resize(width, height, dpi, shouldFlip) {
+    GlobalSimulatorScreen.width = width;
+    GlobalSimulatorScreen.height = height;
+
+    // In order to do rescaling, we set the <browser> tag to the specified
+    // width and height, and then use a CSS transform to scale it so that
+    // it appears at the correct size on the host display.  We also set
+    // the size of the <window> element to that scaled target size.
+    let scale = rescale ? hostDPI / dpi : 1;
+
+    // Set the window width and height to desired size plus chrome
+    // Include the size of the toolbox displayed under the system app
+    let controls = document.getElementById('controls');
+    let controlsHeight = 0;
+    if (controls) {
+      controlsHeight = controls.getBoundingClientRect().height;
+    }
+    let chromewidth = window.outerWidth - window.innerWidth;
+    let chromeheight = window.outerHeight - window.innerHeight + controlsHeight;
+    window.resizeTo(Math.round(width * scale) + chromewidth,
+                    Math.round(height * scale) + chromeheight);
 
-  // Set the window width and height to desired size plus chrome
-  let chromewidth = window.outerWidth - window.innerWidth;
-  let chromeheight = window.outerHeight - window.innerHeight;
-  window.resizeTo(Math.round(width * scale) + chromewidth,
-                  Math.round(height * scale) + chromeheight);
+    let frameWidth = width, frameHeight = height;
+    if (shouldFlip) {
+      frameWidth = height;
+      frameHeight = width;
+    }
+
+    // Set the browser element to the full unscaled size of the screen
+    let style = browser.style;
+    style.width = style.minWidth = style.maxWidth =
+      frameWidth + 'px';
+    style.height = style.minHeight = style.maxHeight =
+      frameHeight + 'px';
+    browser.setAttribute('flex', '0');  // Don't let it stretch
+
+    style.transformOrigin = '';
+    style.transform = '';
 
-  // Set the browser element to the full unscaled size of the screen
-  browser.style.width = browser.style.minWidth = browser.style.maxWidth =
-    width + 'px';
-  browser.style.height = browser.style.minHeight = browser.style.maxHeight =
-    height + 'px';
-  browser.setAttribute('flex', '0');  // Don't let it stretch
+    // Now scale the browser element as needed
+    if (scale !== 1) {
+      style.transformOrigin = 'top left';
+      style.transform += ' scale(' + scale + ',' + scale + ')';
+    }
 
-  // Now scale the browser element as needed
-  if (scale !== 1) {
-    browser.style.transformOrigin = 'top left';
-    browser.style.transform = 'scale(' + scale + ',' + scale + ')';
+    if (shouldFlip) {
+      // Display the system app with a 90° clockwise rotation
+      let shift = Math.floor(Math.abs(frameWidth-frameHeight) / 2);
+      style.transform +=
+        ' rotate(0.25turn) translate(-' + shift + 'px, -' + shift + 'px)';
+    }
+
+    // Set the pixel density that we want to simulate.
+    // This doesn't change the on-screen size, but makes
+    // CSS media queries and mozmm units work right.
+    Services.prefs.setIntPref('layout.css.dpi', dpi);
   }
 
-  // Set the pixel density that we want to simulate.
-  // This doesn't change the on-screen size, but makes
-  // CSS media queries and mozmm units work right.
-  Services.prefs.setIntPref('layout.css.dpi', dpi);
+  // Resize on startup
+  resize(width, height, dpi, false);
+
+  let defaultOrientation = width < height ? 'portrait' : 'landscape';
+
+  // Then resize on each rotation button click,
+  // or when the system app lock/unlock the orientation
+  Services.obs.addObserver(function orientationChangeListener(subject) {
+    let screen = subject.wrappedJSObject;
+    let { mozOrientation, screenOrientation } = screen;
+
+    let newWidth = width;
+    let newHeight = height;
+    // If we have an orientation different than the startup one,
+    // we switch the sizes
+    if (screenOrientation != defaultOrientation) {
+      newWidth = height;
+      newHeight = width;
+    }
+
+    // If the current app doesn't supports the current screen orientation
+    // still resize the window, but rotate its frame so that
+    // it is displayed rotated on the side
+    let shouldFlip = mozOrientation != screenOrientation;
+
+    resize(newWidth, newHeight, dpi, shouldFlip);
+  }, 'simulator-adjust-window-size', false);
 
   // A utility function like console.log() for printing to the terminal window
   // Uses dump(), but enables it first, if necessary
   function print() {
     let dump_enabled =
       Services.prefs.getBoolPref('browser.dom.window.dump.enabled');
 
-    if (!dump_enabled) 
+    if (!dump_enabled)
       Services.prefs.setBoolPref('browser.dom.window.dump.enabled', true);
 
     dump(Array.prototype.join.call(arguments, ' ') + '\n');
 
     if (!dump_enabled) 
       Services.prefs.setBoolPref('browser.dom.window.dump.enabled', false);
   }
 
--- a/b2g/chrome/content/shell.html
+++ b/b2g/chrome/content/shell.html
@@ -7,17 +7,21 @@
       id="shell"
       windowtype="navigator:browser"
 #ifdef ANDROID
       sizemode="fullscreen"
 #endif
       >
 
 <head>
-  <link rel="stylesheet" href="shell.css" type="text/css" media="all" />
+  <link rel="stylesheet" href="shell.css" type="text/css">
+#ifdef FXOS_SIMULATOR
+  <link rel="stylesheet" href="desktop.css" type="text/css">
+#endif
+
   <script type="application/javascript;version=1.8"
           src="chrome://b2g/content/settings.js"> </script>
   <script type="application/javascript;version=1.8"
           src="chrome://b2g/content/shell.js"> </script>
 
 #ifndef MOZ_WIDGET_GONK
   <!-- various task that has to happen only on desktop -->
   <script type="application/javascript;version=1.8"
@@ -26,17 +30,25 @@
   <script type="application/javascript;version=1.8"
           src="chrome://b2g/content/screen.js"> </script>
   <!-- this script handles the "runapp" argument for desktop builds -->
   <script type="application/javascript;version=1.8"
           src="chrome://b2g/content/runapp.js"> </script>
 #endif
 </head>
   <body id="container">
-#ifdef MOZ_WIDGET_COCOA
+#ifdef FXOS_SIMULATOR
+    <!--
+     Some additional buttons are displayed on desktop to fake hardware buttons.
+    -->
+    <footer id="controls">
+      <button id="home-button"></button>
+      <button id="rotate-button"></button>
+    </footer>
+#elifdef MOZ_WIDGET_COCOA
     <!--
      If the document is empty at startup, we don't display the window
      at all on Mac OS...
     -->
     <h1 id="placeholder">wtf mac os!</h1>
 #endif
     <!-- The html:iframe containing the UI is created here. -->
   </body>
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -298,17 +298,21 @@ var shell = {
     systemAppFrame.setAttribute('id', 'systemapp');
     systemAppFrame.setAttribute('mozbrowser', 'true');
     systemAppFrame.setAttribute('mozapp', manifestURL);
     systemAppFrame.setAttribute('allowfullscreen', 'true');
     systemAppFrame.setAttribute('style', "overflow: hidden; height: 100%; width: 100%; border: none;");
     systemAppFrame.setAttribute('src', "data:text/html;charset=utf-8,%3C!DOCTYPE html>%3Cbody style='background:black;");
     let container = document.getElementById('container');
 #ifdef MOZ_WIDGET_COCOA
-    container.removeChild(document.getElementById('placeholder'));
+    // See shell.html
+    let hotfix = document.getElementById('placeholder');
+    if (hotfix) {
+      container.removeChild(hotfix);
+    }
 #endif
     container.appendChild(systemAppFrame);
 
     systemAppFrame.contentWindow
                   .QueryInterface(Ci.nsIInterfaceRequestor)
                   .getInterface(Ci.nsIWebNavigation)
                   .sessionHistory = Cc["@mozilla.org/browser/shistory;1"]
                                       .createInstance(Ci.nsISHistory);
--- a/b2g/chrome/jar.mn
+++ b/b2g/chrome/jar.mn
@@ -9,17 +9,23 @@ chrome.jar:
 % content b2g %content/
 
   content/arrow.svg                     (content/arrow.svg)
 * content/settings.js                   (content/settings.js)
 * content/shell.html                    (content/shell.html)
 * content/shell.js                      (content/shell.js)
   content/shell.css                     (content/shell.css)
   content/devtools.js                   (content/devtools.js)
-#ifndef ANDROID
+#ifdef FXOS_SIMULATOR
+  content/desktop.css                   (content/desktop.css)
+  content/images/desktop/home-black.png (content/images/desktop/home-black.png)
+  content/images/desktop/home-white.png (content/images/desktop/home-white.png)
+  content/images/desktop/rotate.png     (content/images/desktop/rotate.png)
+#endif
+#ifndef MOZ_WIDGET_GONK
   content/desktop.js                    (content/desktop.js)
   content/screen.js                     (content/screen.js)
   content/runapp.js                     (content/runapp.js)
 #endif
 * content/content.css                   (content/content.css)
   content/touchcontrols.css             (content/touchcontrols.css)
 
 * content/payment.js                    (content/payment.js)
--- a/b2g/components/B2GComponents.manifest
+++ b/b2g/components/B2GComponents.manifest
@@ -76,8 +76,14 @@ category update-timer WebappsUpdateTimer
 # FxAccountsUIGlue.js
 component {51875c14-91d7-4b8c-b65d-3549e101228c} FxAccountsUIGlue.js
 contract @mozilla.org/fxaccounts/fxaccounts-ui-glue;1 {51875c14-91d7-4b8c-b65d-3549e101228c}
 #endif
 
 # HelperAppDialog.js
 component {710322af-e6ae-4b0c-b2c9-1474a87b077e} HelperAppDialog.js
 contract @mozilla.org/helperapplauncherdialog;1 {710322af-e6ae-4b0c-b2c9-1474a87b077e}
+
+#ifndef MOZ_WIDGET_GONK
+component {c83c02c0-5d43-4e3e-987f-9173b313e880} SimulatorScreen.js
+contract @mozilla.org/simulator-screen;1 {c83c02c0-5d43-4e3e-987f-9173b313e880}
+category profile-after-change SimulatorScreen @mozilla.org/simulator-screen;1
+#endif
new file mode 100644
--- /dev/null
+++ b/b2g/components/GlobalSimulatorScreen.jsm
@@ -0,0 +1,90 @@
+/* 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 = [ 'GlobalSimulatorScreen' ];
+
+const Cu = Components.utils;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
+
+this.GlobalSimulatorScreen = {
+  mozOrientationLocked: false,
+
+  // Actual orientation of apps
+  mozOrientation: 'portrait',
+
+  // The restricted list of actual orientation that can be used
+  // if mozOrientationLocked is true
+  lockedOrientation: [],
+
+  // The faked screen orientation
+  // if screenOrientation doesn't match mozOrientation due
+  // to lockedOrientation restriction, the app will be displayed
+  // on the side on desktop
+  screenOrientation: 'portrait',
+
+  // Updated by screen.js
+  width: 0, height: 0,
+
+  lock: function(orientation) {
+    this.mozOrientationLocked = true;
+
+    // Normalize to portrait or landscape,
+    // i.e. the possible values of screenOrientation
+    function normalize(str) {
+      if (str.match(/^portrait/)) {
+        return 'portrait';
+      } else if (str.match(/^landscape/)) {
+        return 'landscape';
+      } else {
+        return 'portrait';
+      }
+    }
+    this.lockedOrientation = orientation.map(normalize);
+
+    this.updateOrientation();
+  },
+
+  unlock: function() {
+    this.mozOrientationLocked = false;
+    this.updateOrientation();
+  },
+
+  updateOrientation: function () {
+    let orientation = this.screenOrientation;
+
+    // If the orientation is locked, we have to ensure ending up with a value
+    // of lockedOrientation. If none of lockedOrientation values matches
+    // the screen orientation we just choose the first locked orientation.
+    // This will be the precise scenario where the app is displayed on the
+    // side on desktop!
+    if (this.mozOrientationLocked &&
+        this.lockedOrientation.indexOf(this.screenOrientation) == -1) {
+      orientation = this.lockedOrientation[0];
+    }
+
+    // If the actual orientation changed,
+    // we have to fire mozorientation DOM events
+    if (this.mozOrientation != orientation) {
+      this.mozOrientation = orientation;
+
+      // Notify each app screen object to fire the event
+      Services.obs.notifyObservers(null, 'simulator-orientation-change', null);
+    }
+
+    // Finally, in any case, we update the window size and orientation
+    // (Use wrappedJSObject trick to be able to pass a raw JS object)
+    Services.obs.notifyObservers({wrappedJSObject:this}, 'simulator-adjust-window-size', null);
+  },
+
+  flipScreen: function() {
+    if (this.screenOrientation == 'portrait') {
+      this.screenOrientation = 'landscape';
+    } else if (this.screenOrientation == 'landscape') {
+      this.screenOrientation = 'portrait';
+    }
+    this.updateOrientation();
+  }
+}
new file mode 100644
--- /dev/null
+++ b/b2g/components/SimulatorScreen.js
@@ -0,0 +1,112 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+let Ci = Components.interfaces;
+let Cu = Components.utils;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
+Cu.import('resource://gre/modules/DOMRequestHelper.jsm');
+
+XPCOMUtils.defineLazyModuleGetter(this, 'GlobalSimulatorScreen',
+                                  'resource://gre/modules/GlobalSimulatorScreen.jsm');
+
+let DEBUG_PREFIX = 'SimulatorScreen.js - ';
+function debug() {
+  //dump(DEBUG_PREFIX + Array.slice(arguments) + '\n');
+}
+
+function fireOrientationEvent(window) {
+  let e = new window.Event('mozorientationchange');
+  window.screen.dispatchEvent(e);
+}
+
+function hookScreen(window) {
+  let nodePrincipal = window.document.nodePrincipal;
+  let origin = nodePrincipal.origin;
+  if (nodePrincipal.appStatus == nodePrincipal.APP_STATUS_NOT_INSTALLED) {
+    Cu.reportError('deny mozLockOrientation:' + origin + 'is not installed');
+    return;
+  }
+
+  let screen = window.wrappedJSObject.screen;
+
+  screen.mozLockOrientation = function (orientation) {
+    debug('mozLockOrientation:', orientation, 'from', origin);
+
+    // Normalize and do some checks against orientation input
+    if (typeof(orientation) == 'string') {
+      orientation = [orientation];
+    }
+
+    function isInvalidOrientationString(str) {
+      return typeof(str) != 'string' ||
+        !str.match(/^default$|^(portrait|landscape)(-(primary|secondary))?$/);
+    }
+    if (!Array.isArray(orientation) ||
+        orientation.some(isInvalidOrientationString)) {
+      Cu.reportError('Invalid orientation "' + orientation + '"');
+      return false;
+    }
+
+    GlobalSimulatorScreen.lock(orientation);
+
+    return true;
+  };
+
+  screen.mozUnlockOrientation = function() {
+    debug('mozOrientationUnlock from', origin);
+    GlobalSimulatorScreen.unlock();
+    return true;
+  };
+
+  Object.defineProperty(screen, 'width', {
+    get: function () GlobalSimulatorScreen.width
+  });
+  Object.defineProperty(screen, 'height', {
+    get: function () GlobalSimulatorScreen.height
+  });
+  Object.defineProperty(screen, 'mozOrientation', {
+    get: function () GlobalSimulatorScreen.mozOrientation
+  });
+}
+
+function SimulatorScreen() {}
+SimulatorScreen.prototype = {
+  classID:         Components.ID('{c83c02c0-5d43-4e3e-987f-9173b313e880}'),
+  QueryInterface:  XPCOMUtils.generateQI([Ci.nsIObserver,
+                                          Ci.nsISupportsWeakReference]),
+  _windows: new Set(),
+
+  observe: function (subject, topic, data) {
+    switch (topic) {
+      case 'profile-after-change':
+        Services.obs.addObserver(this, 'document-element-inserted', false);
+        Services.obs.addObserver(this, 'simulator-orientation-change', false);
+        break;
+
+      case 'document-element-inserted':
+        let window = subject.defaultView;
+        if (!window) {
+          return;
+        }
+
+        hookScreen(window);
+
+        let windows = this._windows;
+        window.addEventListener('unload', function unload() {
+          window.removeEventListener('unload', unload);
+          windows.delete(window);
+        });
+        windows.add(window);
+        break;
+
+      case 'simulator-orientation-change':
+        this._windows.forEach(fireOrientationEvent);
+        break;
+    }
+  }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SimulatorScreen]);
--- a/b2g/components/UpdatePrompt.js
+++ b/b2g/components/UpdatePrompt.js
@@ -41,16 +41,31 @@ XPCOMUtils.defineLazyServiceGetter(Servi
 XPCOMUtils.defineLazyServiceGetter(Services, "idle",
                                    "@mozilla.org/widget/idleservice;1",
                                    "nsIIdleService");
 
 XPCOMUtils.defineLazyServiceGetter(Services, "settings",
                                    "@mozilla.org/settingsService;1",
                                    "nsISettingsService");
 
+XPCOMUtils.defineLazyServiceGetter(Services, 'env',
+                                   '@mozilla.org/process/environment;1',
+                                   'nsIEnvironment');
+
+function useSettings() {
+  // When we're running in the real phone, then we can use settings.
+  // But when we're running as part of xpcshell, there is no settings database
+  // and trying to use settings in this scenario causes lots of weird
+  // assertions at shutdown time.
+  if (typeof useSettings.result === "undefined") {
+    useSettings.result = !Services.env.get("XPCSHELL_TEST_PROFILE_DIR");
+  }
+  return useSettings.result;
+}
+
 function UpdateCheckListener(updatePrompt) {
   this._updatePrompt = updatePrompt;
 }
 
 UpdateCheckListener.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdateCheckListener]),
 
   _updatePrompt: null,
@@ -178,37 +193,41 @@ UpdatePrompt.prototype = {
     log("Update error, state: " + aUpdate.state + ", errorCode: " +
         aUpdate.errorCode);
     this.sendUpdateEvent("update-error", aUpdate);
     this.setUpdateStatus(aUpdate.statusText);
   },
 
   showUpdateHistory: function UP_showUpdateHistory(aParent) { },
   showUpdateInstalled: function UP_showUpdateInstalled() {
-    let lock = Services.settings.createLock();
-    lock.set("deviceinfo.last_updated", Date.now(), null, null);
+    if (useSettings()) {
+      let lock = Services.settings.createLock();
+      lock.set("deviceinfo.last_updated", Date.now(), null, null);
+    }
   },
 
   // Custom functions
 
   waitForIdle: function UP_waitForIdle() {
     if (this._waitingForIdle) {
       return;
     }
 
     this._waitingForIdle = true;
     Services.idle.addIdleObserver(this, this.applyIdleTimeout / 1000);
     Services.obs.addObserver(this, "quit-application", false);
   },
 
   setUpdateStatus: function UP_setUpdateStatus(aStatus) {
-    log("Setting gecko.updateStatus: " + aStatus);
+     if (useSettings()) {
+       log("Setting gecko.updateStatus: " + aStatus);
 
-    let lock = Services.settings.createLock();
-    lock.set("gecko.updateStatus", aStatus, null);
+       let lock = Services.settings.createLock();
+       lock.set("gecko.updateStatus", aStatus, null);
+     }
   },
 
   showApplyPrompt: function UP_showApplyPrompt(aUpdate) {
     if (!this.sendUpdateEvent("update-prompt-apply", aUpdate)) {
       log("Unable to prompt, forcing restart");
       this.restartProcess();
       return;
     }
@@ -374,30 +393,32 @@ UpdatePrompt.prototype = {
 #else
       // NB: on Gonk, we rely on the system process manager to restart us.
       let pmService = Cc["@mozilla.org/power/powermanagerservice;1"]
                       .getService(Ci.nsIPowerManagerService);
       pmService.restart();
 #endif
     }
 
-    // Save current os version in deviceinfo.previous_os
-    let lock = Services.settings.createLock({
-      handle: callbackAfterSet,
-      handleAbort: function(error) {
-        log("Abort callback when trying to set previous_os: " + error);
-        callbackAfterSet();
-      }
-    });
-    lock.get("deviceinfo.os", {
-      handle: function(name, value) {
-        log("Set previous_os to: " + value);
-        lock.set("deviceinfo.previous_os", value, null, null);
-      }
-    });
+    if (useSettings()) {
+      // Save current os version in deviceinfo.previous_os
+      let lock = Services.settings.createLock({
+        handle: callbackAfterSet,
+        handleAbort: function(error) {
+          log("Abort callback when trying to set previous_os: " + error);
+          callbackAfterSet();
+        }
+      });
+      lock.get("deviceinfo.os", {
+        handle: function(name, value) {
+          log("Set previous_os to: " + value);
+          lock.set("deviceinfo.previous_os", value, null, null);
+        }
+      });
+    }
   },
 
   forceUpdateCheck: function UP_forceUpdateCheck() {
     log("Forcing update check");
 
     let checker = Cc["@mozilla.org/updates/update-checker;1"]
                     .createInstance(Ci.nsIUpdateChecker);
     checker.checkForUpdates(this._updateCheckListener, true);
--- a/b2g/components/moz.build
+++ b/b2g/components/moz.build
@@ -18,16 +18,21 @@ EXTRA_COMPONENTS += [
     'PaymentGlue.js',
     'ProcessGlobal.js',
     'SmsProtocolHandler.js',
     'TelProtocolHandler.js',
     'WebappsUpdateTimer.js',
     'YoutubeProtocolHandler.js',
 ]
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
+    EXTRA_COMPONENTS += [
+      'SimulatorScreen.js'
+    ]
+
 EXTRA_PP_COMPONENTS += [
     'B2GComponents.manifest',
     'DirectoryProvider.js',
     'RecoveryService.js',
 ]
 
 if CONFIG['MOZ_UPDATER']:
     EXTRA_PP_COMPONENTS += [
@@ -36,15 +41,20 @@ if CONFIG['MOZ_UPDATER']:
 
 EXTRA_JS_MODULES += [
     'ErrorPage.jsm',
     'SignInToWebsite.jsm',
     'TelURIParser.jsm',
     'WebappsUpdater.jsm',
 ]
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
+    EXTRA_JS_MODULES += [
+      'GlobalSimulatorScreen.jsm'
+    ]
+
 if CONFIG['MOZ_SERVICES_FXACCOUNTS']:
     EXTRA_COMPONENTS += [
         'FxAccountsUIGlue.js'
     ]
     EXTRA_JS_MODULES += [
         'FxAccountsMgmtService.jsm'
     ]
--- 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="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <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="db2ef2b61c70889533a0837fa3e053d24e95fdea"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="456499c44d1ef39b602ea02e9ed460b6aab85b44"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>
   <!-- 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="15d69a6789c638709911507f74d25c0425963636">
     <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="db2ef2b61c70889533a0837fa3e053d24e95fdea"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="a9e08b91e9cd1f0930f16cfc49ec72f63575d5fe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="db2ef2b61c70889533a0837fa3e053d24e95fdea"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
   <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="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>
   <!-- Stock Android things -->
--- 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="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <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="db2ef2b61c70889533a0837fa3e053d24e95fdea"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="456499c44d1ef39b602ea02e9ed460b6aab85b44"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "remote": "", 
         "branch": "", 
         "revision": ""
     }, 
-    "revision": "91e5760ff948d3bef3959866c6a1744991560ef6", 
+    "revision": "6d2a2c5c58fce4b2263a7e5e654f6c4ccee5875a", 
     "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="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <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="db2ef2b61c70889533a0837fa3e053d24e95fdea"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -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="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <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="db2ef2b61c70889533a0837fa3e053d24e95fdea"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -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="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <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="db2ef2b61c70889533a0837fa3e053d24e95fdea"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -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="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <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="db2ef2b61c70889533a0837fa3e053d24e95fdea"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -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="15d69a6789c638709911507f74d25c0425963636">
     <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="db2ef2b61c70889533a0837fa3e053d24e95fdea"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>
   <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="1ad48c4be51b279f7f63c1a13025b52fe087d231">
     <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="db2ef2b61c70889533a0837fa3e053d24e95fdea"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="06d3242182370ba93db9acbe54cbe6cc8f7b239f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="cb16958e41105d7c551d9941f522db97b8312538"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="485846b2a40d8ac7d6c1c5f8af6d15b0c10af19d"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/configure.in
+++ b/configure.in
@@ -171,17 +171,21 @@ fi
 AC_SUBST(GAIADIR)
 if test -n "$GAIADIR" ; then
     AC_DEFINE(PACKAGE_GAIA)
 fi
 
 if test -n "$FXOS_SIMULATOR" -a -z "$GAIADIR" ; then
     AC_MSG_ERROR([FXOS_SIMULATOR=1 requires GAIADIR to be defined])
 fi
-AC_SUBST(FXOS_SIMULATOR)
+
+if test -n "$FXOS_SIMULATOR" ; then
+    AC_DEFINE(FXOS_SIMULATOR)
+    AC_SUBST(FXOS_SIMULATOR)
+fi
 
 MOZ_ARG_WITH_STRING(gonk,
 [  --with-gonk=DIR
                location of gonk dir],
     gonkdir=$withval)
 
 MOZ_ARG_WITH_STRING(gonk-toolchain-prefix,
 [  --with-gonk-toolchain-prefix=DIR
--- a/content/media/MediaRecorder.cpp
+++ b/content/media/MediaRecorder.cpp
@@ -11,17 +11,18 @@
 #include "nsError.h"
 #include "nsIDocument.h"
 #include "nsIDOMRecordErrorEvent.h"
 #include "nsTArray.h"
 #include "DOMMediaStream.h"
 #include "EncodedBufferCache.h"
 #include "nsIDOMFile.h"
 #include "mozilla/dom/BlobEvent.h"
-
+#include "nsIPrincipal.h"
+#include "nsMimeTypes.h"
 
 #include "mozilla/dom/AudioStreamTrack.h"
 #include "mozilla/dom/VideoStreamTrack.h"
 
 namespace mozilla {
 
 namespace dom {
 
@@ -315,17 +316,29 @@ private:
   }
 
   void AfterTracksAdded(uint8_t aTrackTypes)
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     // Allocate encoder and bind with union stream.
     // At this stage, the API doesn't allow UA to choose the output mimeType format.
-    mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""), aTrackTypes);
+
+    nsCOMPtr<nsIDocument> doc = mRecorder->GetOwner()->GetExtantDoc();
+    uint16_t appStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
+    if (doc) {
+      doc->NodePrincipal()->GetAppStatus(&appStatus);
+    }
+    // Only allow certificated application can assign AUDIO_3GPP
+    if (appStatus == nsIPrincipal::APP_STATUS_CERTIFIED &&
+         mRecorder->mMimeType.EqualsLiteral(AUDIO_3GPP)) {
+      mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(AUDIO_3GPP), aTrackTypes);
+    } else {
+      mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""), aTrackTypes);
+    }
 
     if (!mEncoder) {
       DoSessionEndTask(NS_ERROR_ABORT);
       return;
     }
 
     // Media stream is ready but UA issues a stop method follow by start method.
     // The Session::stop would clean the mTrackUnionStream. If the AfterTracksAdded
@@ -574,31 +587,34 @@ MediaRecorder::RequestData(ErrorResult& 
 JSObject*
 MediaRecorder::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return MediaRecorderBinding::Wrap(aCx, aScope, this);
 }
 
 /* static */ already_AddRefed<MediaRecorder>
 MediaRecorder::Constructor(const GlobalObject& aGlobal,
-                           DOMMediaStream& aStream, ErrorResult& aRv)
+                           DOMMediaStream& aStream,
+                           const MediaRecorderOptions& aInitDict,
+                           ErrorResult& aRv)
 {
   nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aGlobal.GetAsSupports());
   if (!sgo) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsCOMPtr<nsPIDOMWindow> ownerWindow = do_QueryInterface(aGlobal.GetAsSupports());
   if (!ownerWindow) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsRefPtr<MediaRecorder> object = new MediaRecorder(aStream, ownerWindow);
+  object->SetMimeType(aInitDict.mMimeType);
   return object.forget();
 }
 
 nsresult
 MediaRecorder::CreateAndDispatchBlobEvent(already_AddRefed<nsIDOMBlob>&& aBlob)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
--- a/content/media/MediaRecorder.h
+++ b/content/media/MediaRecorder.h
@@ -15,16 +15,17 @@
 namespace mozilla {
 
 class ErrorResult;
 class DOMMediaStream;
 class EncodedBufferCache;
 class MediaEncoder;
 class ProcessedMediaStream;
 class MediaInputPort;
+struct MediaRecorderOptions;
 
 namespace dom {
 
 /**
  * Implementation of https://dvcs.w3.org/hg/dap/raw-file/default/media-stream-capture/MediaRecorder.html
  * The MediaRecorder accepts a mediaStream as input source passed from UA. When recorder starts,
  * a MediaEncoder will be created and accept the mediaStream as input source.
  * Encoder will get the raw data by track data changes, encode it by selected MIME Type, then store the encoded in EncodedBufferCache object.
@@ -70,17 +71,19 @@ public:
   DOMMediaStream* Stream() const { return mStream; }
   // The current state of the MediaRecorder object.
   RecordingState State() const { return mState; }
   // Return the current encoding MIME type selected by the MediaEncoder.
   void GetMimeType(nsString &aMimeType);
 
   static already_AddRefed<MediaRecorder>
   Constructor(const GlobalObject& aGlobal,
-              DOMMediaStream& aStream, ErrorResult& aRv);
+              DOMMediaStream& aStream,
+              const MediaRecorderOptions& aInitDict,
+              ErrorResult& aRv);
 
   // EventHandler
   IMPL_EVENT_HANDLER(dataavailable)
   IMPL_EVENT_HANDLER(error)
   IMPL_EVENT_HANDLER(stop)
   IMPL_EVENT_HANDLER(warning)
 
 protected:
--- a/content/media/encoder/MediaEncoder.cpp
+++ b/content/media/encoder/MediaEncoder.cpp
@@ -110,24 +110,32 @@ MediaEncoder::CreateEncoder(const nsAStr
     mimeType = NS_LITERAL_STRING(VIDEO_WEBM);
   }
 #endif //MOZ_WEBM_ENCODER
 #ifdef MOZ_OMX_ENCODER
   else if (MediaEncoder::IsOMXEncoderEnabled() &&
           (aMIMEType.EqualsLiteral(VIDEO_MP4) ||
           (aTrackTypes & ContainerWriter::CREATE_VIDEO_TRACK))) {
     if (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK) {
-      audioEncoder = new OmxAudioTrackEncoder();
+      audioEncoder = new OmxAACAudioTrackEncoder();
       NS_ENSURE_TRUE(audioEncoder, nullptr);
     }
     videoEncoder = new OmxVideoTrackEncoder();
     writer = new ISOMediaWriter(aTrackTypes);
     NS_ENSURE_TRUE(writer, nullptr);
     NS_ENSURE_TRUE(videoEncoder, nullptr);
     mimeType = NS_LITERAL_STRING(VIDEO_MP4);
+  } else if (MediaEncoder::IsOMXEncoderEnabled() &&
+            (aMIMEType.EqualsLiteral(AUDIO_3GPP))) {
+    audioEncoder = new OmxAMRAudioTrackEncoder();
+    NS_ENSURE_TRUE(audioEncoder, nullptr);
+
+    writer = new ISOMediaWriter(aTrackTypes, ISOMediaWriter::TYPE_FRAG_3GP);
+    NS_ENSURE_TRUE(writer, nullptr);
+    mimeType = NS_LITERAL_STRING(AUDIO_3GPP);
   }
 #endif // MOZ_OMX_ENCODER
   else if (MediaDecoder::IsOggEnabled() && MediaDecoder::IsOpusEnabled() &&
            (aMIMEType.EqualsLiteral(AUDIO_OGG) ||
            (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK))) {
     writer = new OggWriter();
     audioEncoder = new OpusTrackEncoder();
     NS_ENSURE_TRUE(writer, nullptr);
--- a/content/media/encoder/OmxTrackEncoder.cpp
+++ b/content/media/encoder/OmxTrackEncoder.cpp
@@ -62,16 +62,18 @@ OmxVideoTrackEncoder::GetMetadata()
 
   if (mCanceled || mEncodingComplete) {
     return nullptr;
   }
 
   nsRefPtr<AVCTrackMetadata> meta = new AVCTrackMetadata();
   meta->mWidth = mFrameWidth;
   meta->mHeight = mFrameHeight;
+  meta->mDisplayWidth = mDisplayWidth;
+  meta->mDisplayHeight = mDisplayHeight;
   meta->mFrameRate = ENCODER_CONFIG_FRAME_RATE;
   return meta.forget();
 }
 
 nsresult
 OmxVideoTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
 {
   VideoSegment segment;
@@ -151,59 +153,16 @@ OmxVideoTrackEncoder::GetEncodedTrack(En
     mEncodingComplete = true;
     OMX_LOG("Done encoding video.");
   }
 
   return NS_OK;
 }
 
 nsresult
-OmxAudioTrackEncoder::Init(int aChannels, int aSamplingRate)
-{
-  mChannels = aChannels;
-  mSamplingRate = aSamplingRate;
-
-  mEncoder = OMXCodecWrapper::CreateAACEncoder();
-  NS_ENSURE_TRUE(mEncoder, NS_ERROR_FAILURE);
-
-  nsresult rv = mEncoder->Configure(mChannels, mSamplingRate);
-
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-  mInitialized = (rv == NS_OK);
-
-  mReentrantMonitor.NotifyAll();
-
-  return NS_OK;
-}
-
-already_AddRefed<TrackMetadataBase>
-OmxAudioTrackEncoder::GetMetadata()
-{
-  {
-    // Wait if mEncoder is not initialized nor is being canceled.
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-    while (!mCanceled && !mInitialized) {
-      mReentrantMonitor.Wait();
-    }
-  }
-
-  if (mCanceled || mEncodingComplete) {
-    return nullptr;
-  }
-
-  nsRefPtr<AACTrackMetadata> meta = new AACTrackMetadata();
-  meta->mChannels = mChannels;
-  meta->mSampleRate = mSamplingRate;
-  meta->mFrameSize = OMXCodecWrapper::kAACFrameSize;
-  meta->mFrameDuration = OMXCodecWrapper::kAACFrameDuration;
-
-  return meta.forget();
-}
-
-nsresult
 OmxAudioTrackEncoder::AppendEncodedFrames(EncodedFrameContainer& aContainer)
 {
   nsTArray<uint8_t> frameData;
   int outFlags = 0;
   int64_t outTimeUs = -1;
 
   nsresult rv = mEncoder->GetNextEncodedFrame(&frameData, &outTimeUs, &outFlags,
                                               3000); // wait up to 3ms
@@ -213,18 +172,25 @@ OmxAudioTrackEncoder::AppendEncodedFrame
     bool isCSD = false;
     if (outFlags & OMXCodecWrapper::BUFFER_CODEC_CONFIG) { // codec specific data
       isCSD = true;
     } else if (outFlags & OMXCodecWrapper::BUFFER_EOS) { // last frame
       mEncodingComplete = true;
     }
 
     nsRefPtr<EncodedFrame> audiodata = new EncodedFrame();
-    audiodata->SetFrameType(isCSD ?
-      EncodedFrame::AAC_CSD : EncodedFrame::AAC_AUDIO_FRAME);
+    if (mEncoder->GetCodecType() == OMXCodecWrapper::AAC_ENC) {
+      audiodata->SetFrameType(isCSD ?
+        EncodedFrame::AAC_CSD : EncodedFrame::AAC_AUDIO_FRAME);
+    } else if (mEncoder->GetCodecType() == OMXCodecWrapper::AMR_NB_ENC){
+      audiodata->SetFrameType(isCSD ?
+        EncodedFrame::AMR_AUDIO_CSD : EncodedFrame::AMR_AUDIO_FRAME);
+    } else {
+      MOZ_ASSERT("audio codec not supported");
+    }
     audiodata->SetTimeStamp(outTimeUs);
     rv = audiodata->SwapInFrameData(frameData);
     NS_ENSURE_SUCCESS(rv, rv);
     aContainer.AppendEncodedFrame(audiodata);
   }
 
   return NS_OK;
 }
@@ -272,9 +238,87 @@ OmxAudioTrackEncoder::GetEncodedTrack(En
 
     rv = AppendEncodedFrames(aData);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
+nsresult
+OmxAACAudioTrackEncoder::Init(int aChannels, int aSamplingRate)
+{
+  mChannels = aChannels;
+  mSamplingRate = aSamplingRate;
+
+  mEncoder = OMXCodecWrapper::CreateAACEncoder();
+  NS_ENSURE_TRUE(mEncoder, NS_ERROR_FAILURE);
+
+  nsresult rv = mEncoder->Configure(mChannels, mSamplingRate, mSamplingRate);
+
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+  mInitialized = (rv == NS_OK);
+
+  mReentrantMonitor.NotifyAll();
+
+  return NS_OK;
 }
+
+already_AddRefed<TrackMetadataBase>
+OmxAACAudioTrackEncoder::GetMetadata()
+{
+  {
+    // Wait if mEncoder is not initialized nor is being canceled.
+    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+    while (!mCanceled && !mInitialized) {
+      mReentrantMonitor.Wait();
+    }
+  }
+
+  if (mCanceled || mEncodingComplete) {
+    return nullptr;
+  }
+  nsRefPtr<AACTrackMetadata> meta = new AACTrackMetadata();
+  meta->mChannels = mChannels;
+  meta->mSampleRate = mSamplingRate;
+  meta->mFrameSize = OMXCodecWrapper::kAACFrameSize;
+  meta->mFrameDuration = OMXCodecWrapper::kAACFrameDuration;
+  return meta.forget();
+}
+
+nsresult
+OmxAMRAudioTrackEncoder::Init(int aChannels, int aSamplingRate)
+{
+  mChannels = aChannels;
+  mSamplingRate = aSamplingRate;
+
+  mEncoder = OMXCodecWrapper::CreateAMRNBEncoder();
+  NS_ENSURE_TRUE(mEncoder, NS_ERROR_FAILURE);
+
+  nsresult rv = mEncoder->Configure(mChannels, mSamplingRate, AMR_NB_SAMPLERATE);
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+  mInitialized = (rv == NS_OK);
+
+  mReentrantMonitor.NotifyAll();
+
+  return NS_OK;
+}
+
+already_AddRefed<TrackMetadataBase>
+OmxAMRAudioTrackEncoder::GetMetadata()
+{
+  {
+    // Wait if mEncoder is not initialized nor is being canceled.
+    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+    while (!mCanceled && !mInitialized) {
+      mReentrantMonitor.Wait();
+    }
+  }
+
+  if (mCanceled || mEncodingComplete) {
+    return nullptr;
+  }
+
+  nsRefPtr<AMRTrackMetadata> meta = new AMRTrackMetadata();
+  return meta.forget();
+}
+
+}
--- a/content/media/encoder/OmxTrackEncoder.h
+++ b/content/media/encoder/OmxTrackEncoder.h
@@ -38,31 +38,59 @@ protected:
   nsresult Init(int aWidth, int aHeight,
                 int aDisplayWidth, int aDisplayHeight,
                 TrackRate aTrackRate) MOZ_OVERRIDE;
 
 private:
   nsAutoPtr<android::OMXVideoEncoder> mEncoder;
 };
 
-class OmxAudioTrackEncoder MOZ_FINAL : public AudioTrackEncoder
+class OmxAudioTrackEncoder : public AudioTrackEncoder
 {
 public:
   OmxAudioTrackEncoder()
     : AudioTrackEncoder()
   {}
 
-  already_AddRefed<TrackMetadataBase> GetMetadata() MOZ_OVERRIDE;
+  already_AddRefed<TrackMetadataBase> GetMetadata() = 0;
 
   nsresult GetEncodedTrack(EncodedFrameContainer& aData) MOZ_OVERRIDE;
 
 protected:
-  nsresult Init(int aChannels, int aSamplingRate) MOZ_OVERRIDE;
+  nsresult Init(int aChannels, int aSamplingRate) = 0;
 
-private:
   // Append encoded frames to aContainer.
   nsresult AppendEncodedFrames(EncodedFrameContainer& aContainer);
 
   nsAutoPtr<android::OMXAudioEncoder> mEncoder;
 };
 
+class OmxAACAudioTrackEncoder MOZ_FINAL : public OmxAudioTrackEncoder
+{
+public:
+  OmxAACAudioTrackEncoder()
+    : OmxAudioTrackEncoder()
+  {}
+
+  already_AddRefed<TrackMetadataBase> GetMetadata() MOZ_OVERRIDE;
+
+protected:
+  nsresult Init(int aChannels, int aSamplingRate) MOZ_OVERRIDE;
+};
+
+class OmxAMRAudioTrackEncoder MOZ_FINAL : public OmxAudioTrackEncoder
+{
+public:
+  OmxAMRAudioTrackEncoder()
+    : OmxAudioTrackEncoder()
+  {}
+
+  enum {
+    AMR_NB_SAMPLERATE = 8000,
+  };
+  already_AddRefed<TrackMetadataBase> GetMetadata() MOZ_OVERRIDE;
+
+protected:
+  nsresult Init(int aChannels, int aSamplingRate) MOZ_OVERRIDE;
+};
+
 }
 #endif
--- a/content/media/encoder/TrackMetadataBase.h
+++ b/content/media/encoder/TrackMetadataBase.h
@@ -44,19 +44,23 @@ public:
   virtual uint32_t GetAudioSampleRate() = 0;
 
   virtual uint32_t GetAudioChannels() = 0;
 };
 
 // The base class for video metadata.
 class VideoTrackMetadata : public TrackMetadataBase {
 public:
+  // VideoHeight and VideoWidth are the frame size of the elementary stream.
   virtual uint32_t GetVideoHeight() = 0;
+  virtual uint32_t GetVideoWidth() = 0;
 
-  virtual uint32_t GetVideoWidth() = 0;
+  // VideoDisplayHeight and VideoDisplayWidth are the display frame size.
+  virtual uint32_t GetVideoDisplayHeight() = 0;
+  virtual uint32_t GetVideoDisplayWidth() = 0;
 
   // VideoClockRate is the number of samples per second in video frame's
   // timestamp.
   // For example, if VideoClockRate is 90k Hz and VideoFrameRate is
   // 30 fps, each frame's sample duration will be 3000 Hz.
   virtual uint32_t GetVideoClockRate() = 0;
 
   // VideoFrameRate is numner of frames per second.
--- a/content/media/encoder/fmp4_muxer/ISOControl.cpp
+++ b/content/media/encoder/fmp4_muxer/ISOControl.cpp
@@ -162,28 +162,30 @@ ISOControl::GetTrackID(TrackMetadataBase
   MOZ_ASSERT(0);
   return 0;
 }
 
 nsresult
 ISOControl::SetMetadata(TrackMetadataBase* aTrackMeta)
 {
   if (aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AAC ||
+      aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AMR ||
       aTrackMeta->GetKind() == TrackMetadataBase::METADATA_AVC) {
     mMetaArray.AppendElement(aTrackMeta);
     return NS_OK;
   }
   return NS_ERROR_FAILURE;
 }
 
 nsresult
 ISOControl::GetAudioMetadata(nsRefPtr<AudioTrackMetadata>& aAudMeta)
 {
   for (uint32_t i = 0; i < mMetaArray.Length() ; i++) {
-    if (mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AAC) {
+    if (mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AAC ||
+        mMetaArray[i]->GetKind() == TrackMetadataBase::METADATA_AMR) {
       aAudMeta = static_cast<AudioTrackMetadata*>(mMetaArray[i].get());
       return NS_OK;
     }
   }
   return NS_ERROR_FAILURE;
 }
 
 nsresult
--- a/content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp
+++ b/content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp
@@ -1174,18 +1174,23 @@ TrackHeaderBox::Generate(uint32_t* aBoxS
                 mControl->GetTrackID(mVideoMeta->GetKind()));
   // fragmented mp4
   duration = 0;
 
   // volume, audiotrack is always 0x0100 in 14496-12 8.3.2.2
   volume = (mTrackType == Audio_Track ? 0x0100 : 0);
 
   if (mTrackType == Video_Track) {
-    width = mVideoMeta->GetVideoWidth() << 16;
-    height = mVideoMeta->GetVideoHeight() << 16;
+    width = mVideoMeta->GetVideoDisplayWidth() << 16;
+    height = mVideoMeta->GetVideoDisplayHeight() << 16;
+    // Check display size, using the pixel size if any of them is invalid.
+    if (!width || !height) {
+      width = mVideoMeta->GetVideoWidth() << 16;
+      height = mVideoMeta->GetVideoHeight() << 16;
+    }
   }
 
   size += sizeof(creation_time) +
           sizeof(modification_time) +
           sizeof(track_ID) +
           sizeof(reserved) +
           sizeof(duration) +
           sizeof(reserved2) +
--- a/content/media/encoder/fmp4_muxer/ISOTrackMetadata.h
+++ b/content/media/encoder/fmp4_muxer/ISOTrackMetadata.h
@@ -40,33 +40,39 @@ public:
 // AVC clock rate is 90k Hz.
 #define AVC_CLOCK_RATE 90000
 
 class AVCTrackMetadata : public VideoTrackMetadata {
 public:
   // VideoTrackMetadata members
   uint32_t GetVideoHeight() MOZ_OVERRIDE { return mHeight; }
   uint32_t GetVideoWidth() MOZ_OVERRIDE {return mWidth; }
+  uint32_t GetVideoDisplayHeight() MOZ_OVERRIDE { return mDisplayHeight; }
+  uint32_t GetVideoDisplayWidth() MOZ_OVERRIDE { return mDisplayWidth;  }
   uint32_t GetVideoClockRate() MOZ_OVERRIDE { return AVC_CLOCK_RATE; }
   uint32_t GetVideoFrameRate() MOZ_OVERRIDE { return mFrameRate; }
 
   // TrackMetadataBase member
   MetadataKind GetKind() const MOZ_OVERRIDE { return METADATA_AVC; }
 
   // AVCTrackMetadata
   AVCTrackMetadata()
     : mHeight(0)
     , mWidth(0)
+    , mDisplayHeight(0)
+    , mDisplayWidth(0)
     , mFrameRate(0) {
     MOZ_COUNT_CTOR(AVCTrackMetadata);
   }
   ~AVCTrackMetadata() { MOZ_COUNT_DTOR(AVCTrackMetadata); }
 
   uint32_t mHeight;
   uint32_t mWidth;
+  uint32_t mDisplayHeight;
+  uint32_t mDisplayWidth;
   uint32_t mFrameRate;       // frames per second
 };
 
 
 // AMR sample rate is 8000 samples/s.
 #define AMR_SAMPLE_RATE 8000
 
 // Channel number is always 1.
--- a/content/media/omx/OMXCodecWrapper.cpp
+++ b/content/media/omx/OMXCodecWrapper.cpp
@@ -22,16 +22,18 @@ using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
 #define ENCODER_CONFIG_BITRATE 2000000 // bps
 // How many seconds between I-frames.
 #define ENCODER_CONFIG_I_FRAME_INTERVAL 1
 // Wait up to 5ms for input buffers.
 #define INPUT_BUFFER_TIMEOUT_US (5 * 1000ll)
+// AMR NB kbps
+#define AMRNB_BITRATE 12200
 
 #define CODEC_ERROR(args...)                                                   \
   do {                                                                         \
     __android_log_print(ANDROID_LOG_ERROR, "OMXCodecWrapper", ##args);         \
   } while (0)
 
 namespace android {
 
@@ -40,36 +42,50 @@ OMXCodecWrapper::CreateAACEncoder()
 {
   nsAutoPtr<OMXAudioEncoder> aac(new OMXAudioEncoder(CodecType::AAC_ENC));
   // Return the object only when media codec is valid.
   NS_ENSURE_TRUE(aac->IsValid(), nullptr);
 
   return aac.forget();
 }
 
+OMXAudioEncoder*
+OMXCodecWrapper::CreateAMRNBEncoder()
+{
+  nsAutoPtr<OMXAudioEncoder> amr(new OMXAudioEncoder(CodecType::AMR_NB_ENC));
+  // Return the object only when media codec is valid.
+  NS_ENSURE_TRUE(amr->IsValid(), nullptr);
+
+  return amr.forget();
+}
+
 OMXVideoEncoder*
 OMXCodecWrapper::CreateAVCEncoder()
 {
   nsAutoPtr<OMXVideoEncoder> avc(new OMXVideoEncoder(CodecType::AVC_ENC));
   // Return the object only when media codec is valid.
   NS_ENSURE_TRUE(avc->IsValid(), nullptr);
 
   return avc.forget();
 }
 
 OMXCodecWrapper::OMXCodecWrapper(CodecType aCodecType)
-  : mStarted(false)
+  : mCodecType(aCodecType)
+  , mStarted(false)
+  , mAMRCSDProvided(false)
 {
   ProcessState::self()->startThreadPool();
 
   mLooper = new ALooper();
   mLooper->start();
 
   if (aCodecType == CodecType::AVC_ENC) {
     mCodec = MediaCodec::CreateByType(mLooper, MEDIA_MIMETYPE_VIDEO_AVC, true);
+  } else if (aCodecType == CodecType::AMR_NB_ENC) {
+    mCodec = MediaCodec::CreateByType(mLooper, MEDIA_MIMETYPE_AUDIO_AMR_NB, true);
   } else if (aCodecType == CodecType::AAC_ENC) {
     mCodec = MediaCodec::CreateByType(mLooper, MEDIA_MIMETYPE_AUDIO_AAC, true);
   } else {
     NS_ERROR("Unknown codec type.");
   }
 }
 
 OMXCodecWrapper::~OMXCodecWrapper()
@@ -375,38 +391,63 @@ void OMXVideoEncoder::AppendFrame(nsTArr
     aSize & 0xFF,
   };
   aOutputBuf->SetCapacity(aSize);
   aOutputBuf->AppendElements(length, sizeof(length));
   aOutputBuf->AppendElements(aData + sizeof(length), aSize);
 }
 
 nsresult
-OMXAudioEncoder::Configure(int aChannels, int aSamplingRate)
+OMXAudioEncoder::Configure(int aChannels, int aInputSampleRate,
+                           int aEncodedSampleRate)
 {
   MOZ_ASSERT(!mStarted);
 
-  NS_ENSURE_TRUE(aChannels > 0 && aSamplingRate > 0, NS_ERROR_INVALID_ARG);
+  NS_ENSURE_TRUE(aChannels > 0 && aInputSampleRate > 0 && aEncodedSampleRate >= 0,
+                 NS_ERROR_INVALID_ARG);
 
+  if (aInputSampleRate != aEncodedSampleRate) {
+    int error;
+    mResampler = speex_resampler_init(aChannels,
+                                      aInputSampleRate,
+                                      aEncodedSampleRate,
+                                      SPEEX_RESAMPLER_QUALITY_DEFAULT,
+                                      &error);
+
+    if (error != RESAMPLER_ERR_SUCCESS) {
+      return NS_ERROR_FAILURE;
+    }
+    speex_resampler_skip_zeros(mResampler);
+  }
   // Set up configuration parameters for AAC encoder.
   sp<AMessage> format = new AMessage;
   // Fixed values.
-  format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
-  format->setInt32("bitrate", kAACBitrate);
-  format->setInt32("aac-profile", OMX_AUDIO_AACObjectLC);
+  if (mCodecType == AAC_ENC) {
+    format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
+    format->setInt32("aac-profile", OMX_AUDIO_AACObjectLC);
+    format->setInt32("bitrate", kAACBitrate);
+    format->setInt32("sample-rate", aInputSampleRate);
+  } else if (mCodecType == AMR_NB_ENC) {
+    format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
+    format->setInt32("bitrate", AMRNB_BITRATE);
+    format->setInt32("sample-rate", aEncodedSampleRate);
+  } else {
+    MOZ_ASSERT(false, "Can't support this codec type!!");
+  }
   // Input values.
   format->setInt32("channel-count", aChannels);
-  format->setInt32("sample-rate", aSamplingRate);
 
   status_t result = mCodec->configure(format, nullptr, nullptr,
                                       MediaCodec::CONFIGURE_FLAG_ENCODE);
   NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
 
   mChannels = aChannels;
-  mSampleDuration = 1000000 / aSamplingRate;
+  mSampleDuration = 1000000 / aInputSampleRate;
+  mResamplingRatio = aEncodedSampleRate > 0 ? 1.0 *
+                      aEncodedSampleRate / aInputSampleRate : 1.0;
   result = Start();
 
   return result == OK ? NS_OK : NS_ERROR_FAILURE;
 }
 
 class InputBufferHelper MOZ_FINAL {
 public:
   InputBufferHelper(sp<MediaCodec>& aCodec, Vector<sp<ABuffer> >& aBuffers)
@@ -469,16 +510,24 @@ private:
   sp<MediaCodec>& mCodec;
   Vector<sp<ABuffer> >& mBuffers;
   size_t mIndex;
   uint8_t* mData;
   size_t mCapicity;
   size_t mOffset;
 };
 
+OMXAudioEncoder::~OMXAudioEncoder()
+{
+  if (mResampler) {
+    speex_resampler_destroy(mResampler);
+    mResampler = nullptr;
+  }
+}
+
 nsresult
 OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
 {
 #ifndef MOZ_SAMPLE_TYPE_S16
 #error MediaCodec accepts only 16-bit PCM data.
 #endif
 
   MOZ_ASSERT(mStarted, "Configure() should be called before Encode().");
@@ -490,82 +539,97 @@ OMXAudioEncoder::Encode(AudioSegment& aS
   status_t result = buffer.Dequeue();
   if (result == -EAGAIN) {
     // All input buffers are full. Caller can try again later after consuming
     // some output buffers.
     return NS_OK;
   }
   NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
 
-  size_t samplesCopied = 0; // Number of copied samples.
+  size_t sourceSamplesCopied = 0; // Number of copied samples.
 
   if (numSamples > 0) {
     // Copy input PCM data to input buffer until queue is empty.
     AudioSegment::ChunkIterator iter(const_cast<AudioSegment&>(aSegment));
     while (!iter.IsEnded()) {
       AudioChunk chunk = *iter;
-      size_t samplesToCopy = chunk.GetDuration(); // Number of samples to copy.
-      size_t bytesToCopy = samplesToCopy * mChannels * sizeof(AudioDataValue);
-
+      size_t sourceSamplesToCopy = chunk.GetDuration(); // Number of samples to copy.
+      size_t bytesToCopy = sourceSamplesToCopy * mChannels *
+                           sizeof(AudioDataValue) * mResamplingRatio;
       if (bytesToCopy > buffer.AvailableSize()) {
         // Not enough space left in input buffer. Send it to encoder and get a
         // new one.
         result = buffer.Enqueue(mTimestamp, aInputFlags & ~BUFFER_EOS);
         NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
 
         result = buffer.Dequeue();
         if (result == -EAGAIN) {
           // All input buffers are full. Caller can try again later after
           // consuming some output buffers.
-          aSegment.RemoveLeading(samplesCopied);
+          aSegment.RemoveLeading(sourceSamplesCopied);
           return NS_OK;
         }
 
-        mTimestamp += samplesCopied * mSampleDuration;
-        samplesCopied = 0;
+        mTimestamp += sourceSamplesCopied * mSampleDuration;
+        sourceSamplesCopied = 0;
 
         NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
       }
 
       AudioDataValue* dst = reinterpret_cast<AudioDataValue*>(buffer.GetPointer());
+      uint32_t dstSamplesCopied = sourceSamplesToCopy;
       if (!chunk.IsNull()) {
-        // Append the interleaved data to input buffer.
-        AudioTrackEncoder::InterleaveTrackData(chunk, samplesToCopy, mChannels,
-                                               dst);
+        if (mResampler) {
+          nsAutoTArray<AudioDataValue, 9600> pcm;
+          pcm.SetLength(bytesToCopy);
+          // Append the interleaved data to input buffer.
+          AudioTrackEncoder::InterleaveTrackData(chunk, sourceSamplesToCopy,
+                                                 mChannels,
+                                                 pcm.Elements());
+          uint32_t inframes = sourceSamplesToCopy;
+          short* in = reinterpret_cast<short*>(pcm.Elements());
+          speex_resampler_process_interleaved_int(mResampler, in, &inframes,
+                                                              dst, &dstSamplesCopied);
+        } else {
+          AudioTrackEncoder::InterleaveTrackData(chunk, sourceSamplesToCopy,
+                                                 mChannels,
+                                                 dst);
+          dstSamplesCopied = sourceSamplesToCopy * mChannels;
+        }
       } else {
         // Silence.
-        memset(dst, 0, bytesToCopy);
+        memset(dst, 0, mResamplingRatio * sourceSamplesToCopy * sizeof(AudioDataValue));
       }
 
-      samplesCopied += samplesToCopy;
-      buffer.IncreaseOffset(bytesToCopy);
+      sourceSamplesCopied += sourceSamplesToCopy;
+      buffer.IncreaseOffset(dstSamplesCopied * sizeof(AudioDataValue));
       iter.Next();
     }
-    if (samplesCopied > 0) {
-      aSegment.RemoveLeading(samplesCopied);
+    if (sourceSamplesCopied > 0) {
+      aSegment.RemoveLeading(sourceSamplesCopied);
     }
   } else if (aInputFlags & BUFFER_EOS) {
     // No audio data left in segment but we still have to feed something to
     // MediaCodec in order to notify EOS.
     size_t bytesToCopy = mChannels * sizeof(AudioDataValue);
     memset(buffer.GetPointer(), 0, bytesToCopy);
     buffer.IncreaseOffset(bytesToCopy);
-    samplesCopied = 1;
+    sourceSamplesCopied = 1;
   }
 
-  if (samplesCopied > 0) {
+  if (sourceSamplesCopied > 0) {
     int flags = aInputFlags;
     if (aSegment.GetDuration() > 0) {
       // Don't signal EOS until source segment is empty.
       flags &= ~BUFFER_EOS;
     }
     result = buffer.Enqueue(mTimestamp, flags);
     NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
 
-    mTimestamp += samplesCopied * mSampleDuration;
+    mTimestamp += sourceSamplesCopied * mSampleDuration;
   }
 
   return NS_OK;
 }
 
 // Generate decoder config descriptor (defined in ISO/IEC 14496-1 8.3.4.1) for
 // AAC. The hard-coded bytes are copied from
 // MPEG4Writer::Track::writeMp4aEsdsBox() implementation in libstagefright.
@@ -658,16 +722,30 @@ OMXCodecWrapper::GetNextEncodedFrame(nsT
     aOutputBuf->Clear();
     const sp<ABuffer> omxBuf = mOutputBufs.itemAt(index);
     if (outFlags & MediaCodec::BUFFER_FLAG_CODECCONFIG) {
       // Codec specific data.
       if (AppendDecoderConfig(aOutputBuf, omxBuf.get()) != OK) {
         mCodec->releaseOutputBuffer(index);
         return NS_ERROR_FAILURE;
       }
+    } else if ((mCodecType == AMR_NB_ENC) && !mAMRCSDProvided){
+      // OMX AMR codec won't provide csd data, need to generate a fake one.
+      nsRefPtr<EncodedFrame> audiodata = new EncodedFrame();
+      // Decoder config descriptor
+      const uint8_t decConfig[] = {
+        0x0, 0x0, 0x0, 0x0, // vendor: 4 bytes
+        0x0,                // decoder version
+        0x83, 0xFF,         // mode set: all enabled
+        0x00,               // mode change period
+        0x01,               // frames per sample
+      };
+      aOutputBuf->AppendElements(decConfig, sizeof(decConfig));
+      outFlags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
+      mAMRCSDProvided = true;
     } else {
       AppendFrame(aOutputBuf, omxBuf->data(), omxBuf->size());
     }
   }
   mCodec->releaseOutputBuffer(index);
 
   if (aOutputTimestamp) {
     *aOutputTimestamp = outTimeUs;
--- a/content/media/omx/OMXCodecWrapper.h
+++ b/content/media/omx/OMXCodecWrapper.h
@@ -10,16 +10,18 @@
 #include <stagefright/foundation/ABuffer.h>
 #include <stagefright/foundation/AMessage.h>
 #include <stagefright/MediaCodec.h>
 
 #include "AudioSegment.h"
 #include "GonkNativeWindow.h"
 #include "GonkNativeWindowClient.h"
 
+#include <speex/speex_resampler.h>
+
 namespace android {
 
 class OMXAudioEncoder;
 class OMXVideoEncoder;
 
 /**
  * This class (and its subclasses) wraps the video and audio codec from
  * MediaCodec API in libstagefright. Currently only AVC/H.264 video encoder and
@@ -48,16 +50,17 @@ class OMXVideoEncoder;
  * fail.
  */
 class OMXCodecWrapper
 {
 public:
   // Codec types.
   enum CodecType {
     AAC_ENC, // AAC encoder.
+    AMR_NB_ENC, // AMR_NB encoder.
     AVC_ENC, // AVC/H.264 encoder.
     TYPE_COUNT
   };
 
   // Input and output flags.
   enum {
     // For Encode() and Encode, it indicates the end of input stream;
     // For GetNextEncodedFrame(), it indicates the end of output
@@ -78,31 +81,37 @@ public:
     kAACBitrate = 96000,      // kbps
     kAACFrameSize = 768,      // bytes
     kAACFrameDuration = 1024, // How many samples per AAC frame.
   };
 
   /** Create a AAC audio encoder. Returns nullptr when failed. */
   static OMXAudioEncoder* CreateAACEncoder();
 
+  /** Create a AMR audio encoder. Returns nullptr when failed. */
+  static OMXAudioEncoder* CreateAMRNBEncoder();
+
   /** Create a AVC/H.264 video encoder. Returns nullptr when failed. */
   static OMXVideoEncoder* CreateAVCEncoder();
 
   virtual ~OMXCodecWrapper();
 
   /**
    * Get the next available encoded data from MediaCodec. The data will be
    * copied into aOutputBuf array, with its timestamp (in microseconds) in
    * aOutputTimestamp.
    * Wait at most aTimeout microseconds to dequeue a output buffer.
    */
   nsresult GetNextEncodedFrame(nsTArray<uint8_t>* aOutputBuf,
                                int64_t* aOutputTimestamp, int* aOutputFlags,
                                int64_t aTimeOut);
-
+  /*
+   * Get the codec type
+   */
+  int GetCodecType() { return mCodecType; }
 protected:
   /**
    * See whether the object has been initialized successfully and is ready to
    * use.
    */
   virtual bool IsValid() { return mCodec != nullptr; }
 
   /**
@@ -155,64 +164,76 @@ private:
   sp<MediaCodec> mCodec;
 
   // A dedicate message loop with its own thread used by MediaCodec.
   sp<ALooper> mLooper;
 
   Vector<sp<ABuffer> > mInputBufs;  // MediaCodec buffers to hold input data.
   Vector<sp<ABuffer> > mOutputBufs; // MediaCodec buffers to hold output data.
 
+  int mCodecType;
   bool mStarted; // Has MediaCodec been started?
+  bool mAMRCSDProvided;
 };
 
 /**
  * Audio encoder.
  */
 class OMXAudioEncoder MOZ_FINAL : public OMXCodecWrapper
 {
 public:
   /**
    * Configure audio codec parameters and start media codec. It must be called
    * before calling Encode() and GetNextEncodedFrame().
+   * aReSamplingRate = 0 means no resampler required
    */
-  nsresult Configure(int aChannelCount, int aSampleRate);
+  nsresult Configure(int aChannelCount, int aInputSampleRate, int aEncodedSampleRate);
 
   /**
    * Encode 16-bit PCM audio samples stored in aSegment. To notify end of
    * stream, set aInputFlags to BUFFER_EOS. Since encoder has limited buffers,
    * this function might not be able to encode all chunks in one call, however
    * it will remove chunks it consumes from aSegment.
    */
   nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0);
 
+  ~OMXAudioEncoder();
 protected:
   virtual status_t AppendDecoderConfig(nsTArray<uint8_t>* aOutputBuf,
                                        ABuffer* aData) MOZ_OVERRIDE;
-
 private:
   // Hide these. User should always use creator functions to get a media codec.
   OMXAudioEncoder() MOZ_DELETE;
   OMXAudioEncoder(const OMXAudioEncoder&) MOZ_DELETE;
   OMXAudioEncoder& operator=(const OMXAudioEncoder&) MOZ_DELETE;
 
   /**
    * Create a audio codec. It will be a AAC encoder if aCodecType is
    * CODEC_AAC_ENC.
    */
   OMXAudioEncoder(CodecType aCodecType)
     : OMXCodecWrapper(aCodecType)
+    , mResampler(nullptr)
     , mChannels(0)
     , mTimestamp(0)
-    , mSampleDuration(0) {}
+    , mSampleDuration(0)
+    , mResamplingRatio(0) {}
 
   // For creator function to access hidden constructor.
   friend class OMXCodecWrapper;
 
+  /**
+   * If the input sample rate does not divide 48kHz evenly, the input data are
+   * resampled.
+   */
+  SpeexResamplerState* mResampler;
   // Number of audio channels.
   size_t mChannels;
+
+  float mResamplingRatio;
   // The total duration of audio samples that have been encoded in microseconds.
   int64_t mTimestamp;
   // Time per audio sample in microseconds.
   int64_t mSampleDuration;
 };
 
 /**
  * Video encoder.
--- a/content/media/test/test_new_audio.html
+++ b/content/media/test/test_new_audio.html
@@ -25,22 +25,20 @@ var manager = new MediaTestManager;
 var player = new Audio();
 
 function startTest(test, token) {
   if (!player.canPlayType(test.type)) {
     return;
   }
   manager.started(token);
   var a = new Audio(test.name);
-  a.addEventListener("canplaythrough",
-                     function(e){ e.target.play(); },
-                      false);
+  a.autoplay = true;
   a.addEventListener("ended",
                      function(e){
-                        ok(true, "We should get to the end. Oh look we did.");
+                        ok(true, "[" + a.src + "]We should get to the end. Oh look we did.");
                         manager.finished(token);
                      },
                      false);
 }
 
 manager.runTests(gAudioTests, startTest);
 
 </script>
--- a/dom/browser-element/mochitest/priority/test_Preallocated.html
+++ b/dom/browser-element/mochitest/priority/test_Preallocated.html
@@ -56,17 +56,17 @@ function runTest()
               "false for this test to work.");
     SimpleTest.finish();
     return;
   }
 
   // Ensure that the preallocated process initially gets BACKGROUND priority.
   // That's it.
   expectProcessCreated().then(function(childID) {
-    return expectPriorityChange(childID, 'BACKGROUND');
+    return expectPriorityChange(childID, 'PREALLOC');
   }).then(function() {
     cleanUp();
     SimpleTest.finish();
   });
 
   // Setting this pref to true should cause us to prelaunch a process.
   SpecialPowers.setBoolPref('dom.ipc.processPrelaunch.enabled', true);
 }
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -443,17 +443,17 @@ ContentParent::RunNuwaProcess()
 // MaybeTakePreallocatedAppProcess.
 /*static*/ already_AddRefed<ContentParent>
 ContentParent::PreallocateAppProcess()
 {
     nsRefPtr<ContentParent> process =
         new ContentParent(/* app = */ nullptr,
                           /* isForBrowserElement = */ false,
                           /* isForPreallocated = */ true,
-                          PROCESS_PRIORITY_BACKGROUND);
+                          PROCESS_PRIORITY_PREALLOC);
     process->Init();
     return process.forget();
 }
 
 /*static*/ already_AddRefed<ContentParent>
 ContentParent::MaybeTakePreallocatedAppProcess(const nsAString& aAppManifestURL,
                                                ProcessPriority aInitialPriority)
 {
@@ -1448,17 +1448,17 @@ ContentParent::ContentParent(ContentPare
     Open(mSubprocess->GetChannel(),
          mSubprocess->GetChildProcessHandle());
 
     // Set the subprocess's priority (bg if we're a preallocated process, fg
     // otherwise).  We do this first because we're likely /lowering/ its CPU and
     // memory priority, which it has inherited from this process.
     ProcessPriority priority;
     if (IsPreallocated()) {
-        priority = PROCESS_PRIORITY_BACKGROUND;
+        priority = PROCESS_PRIORITY_PREALLOC;
     } else {
         priority = PROCESS_PRIORITY_FOREGROUND;
     }
 
     InitInternal(priority,
                  false, /* Setup Off-main thread compositing */
                  false  /* Send registered chrome */);
 }
--- a/dom/ipc/ProcessPriorityManager.cpp
+++ b/dom/ipc/ProcessPriorityManager.cpp
@@ -940,16 +940,20 @@ ParticularProcessPriorityManager::Comput
   return HasAppType("homescreen") ?
          PROCESS_PRIORITY_BACKGROUND_HOMESCREEN :
          PROCESS_PRIORITY_BACKGROUND;
 }
 
 ProcessCPUPriority
 ParticularProcessPriorityManager::ComputeCPUPriority()
 {
+  if (mPriority == PROCESS_PRIORITY_PREALLOC) {
+    return PROCESS_CPU_PRIORITY_LOW;
+  }
+
   if (mPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH) {
     return PROCESS_CPU_PRIORITY_NORMAL;
   }
 
   return ProcessPriorityManagerImpl::GetSingleton()->
     OtherProcessHasHighPriority(this) ?
     PROCESS_CPU_PRIORITY_LOW :
     PROCESS_CPU_PRIORITY_NORMAL;
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -331,17 +331,19 @@ MediaElementChecker.prototype = {
  */
 function isNetworkReady() {
   // for gonk platform
   if ("nsINetworkInterfaceListService" in SpecialPowers.Ci) {
     var listService = SpecialPowers.Cc["@mozilla.org/network/interface-list-service;1"]
                         .getService(SpecialPowers.Ci.nsINetworkInterfaceListService);
     var itfList = listService.getDataInterfaceList(
           SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_MMS_INTERFACES |
-          SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_SUPL_INTERFACES);
+          SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_SUPL_INTERFACES |
+          SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_IMS_INTERFACES |
+          SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_DUN_INTERFACES);
     var num = itfList.getNumberOfInterface();
     for (var i = 0; i < num; i++) {
       if (itfList.getInterface(i).ip) {
         info("Network interface is ready with address: " + itfList.getInterface(i).ip);
         return true;
       }
     }
     // ip address is not available
--- a/dom/mobilemessage/interfaces/nsIMobileMessageService.idl
+++ b/dom/mobilemessage/interfaces/nsIMobileMessageService.idl
@@ -9,56 +9,56 @@ interface nsIDOMMozMmsMessage;
 interface nsIDOMMozMobileMessageThread;
 interface nsIDOMMozSmsSegmentInfo;
 
 %{C++
 #define MOBILE_MESSAGE_SERVICE_CID { 0x829c1dd6, 0x0466, 0x4591, { 0x83, 0x6f, 0xb8, 0xf6, 0xfd, 0x1f, 0x7b, 0xa5 } }
 #define MOBILE_MESSAGE_SERVICE_CONTRACTID "@mozilla.org/mobilemessage/mobilemessageservice;1"
 %}
 
-[scriptable, builtinclass, uuid(67d038b2-0039-11e3-9fd3-83de190730f7)]
+[scriptable, builtinclass, uuid(17fce9e4-af56-11e3-83d9-b71055e95493)]
 interface nsIMobileMessageService : nsISupports
 {
   [implicit_jscontext]
-  nsIDOMMozSmsMessage createSmsMessage(in long      id,
+  nsIDOMMozSmsMessage createSmsMessage(in long               id,
                                        in unsigned long long threadId,
-                                       in DOMString iccId,
-                                       in DOMString delivery,
-                                       in DOMString deliveryStatus,
-                                       in DOMString sender,
-                                       in DOMString receiver,
-                                       in DOMString body,
-                                       in DOMString messageClass,
-                                       in jsval     timestamp,
-                                       in jsval     sentTimestamp,
-                                       in jsval     deliveryTimestamp,
-                                       in bool      read);
+                                       in DOMString          iccId,
+                                       in DOMString          delivery,
+                                       in DOMString          deliveryStatus,
+                                       in DOMString          sender,
+                                       in DOMString          receiver,
+                                       in DOMString          body,
+                                       in DOMString          messageClass,
+                                       in unsigned long long timestamp,
+                                       in unsigned long long sentTimestamp,
+                                       in unsigned long long deliveryTimestamp,
+                                       in bool               read);
 
   [implicit_jscontext]
-  nsIDOMMozMmsMessage createMmsMessage(in long      id,
+  nsIDOMMozMmsMessage createMmsMessage(in long               id,
                                        in unsigned long long threadId,
-                                       in DOMString iccId,
-                                       in DOMString delivery,
-                                       in jsval     deliveryInfo,
-                                       in DOMString sender,
-                                       in jsval     receivers,
-                                       in jsval     timestamp,
-                                       in jsval     sentTimestamp,
-                                       in boolean   read,
-                                       in DOMString subject,
-                                       in DOMString smil,
-                                       in jsval     attachments,
-                                       in jsval     expiryDate,
-                                       in boolean   readReportRequested);
+                                       in DOMString          iccId,
+                                       in DOMString          delivery,
+                                       in jsval              deliveryInfo,
+                                       in DOMString          sender,
+                                       in jsval              receivers,
+                                       in unsigned long long timestamp,
+                                       in unsigned long long sentTimestamp,
+                                       in boolean            read,
+                                       in DOMString          subject,
+                                       in DOMString          smil,
+                                       in jsval              attachments,
+                                       in unsigned long long expiryDate,
+                                       in boolean            readReportRequested);
 
   nsIDOMMozSmsSegmentInfo createSmsSegmentInfo(in long segments,
                                                in long charsPerSegment,
                                                in long charsAvailableInLastSegment);
 
   [implicit_jscontext]
   nsIDOMMozMobileMessageThread createThread(in unsigned long long id,
                                             in jsval              participants,
-                                            in jsval              timestamp,
+                                            in unsigned long long timestamp,
                                             in DOMString          lastMessageSubject,
                                             in DOMString          body,
                                             in unsigned long long unreadCount,
                                             in DOMString          aLastMessageType);
 };
deleted file mode 100644
--- a/dom/mobilemessage/src/MessageUtils.h
+++ /dev/null
@@ -1,42 +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/. */
-
-#ifndef MessageUtils_h
-#define MessageUtils_h
-
-/**
- * A helper function to convert the JS value to an integer value for time.
- *
- * @params aCx
- *         The JS context.
- * @params aTime
- *         Can be an object or a number.
- * @params aReturn
- *         The integer value to return.
- * @return NS_OK if the convertion succeeds.
- */
-static nsresult
-convertTimeToInt(JSContext* aCx, const JS::Value& aTime, uint64_t& aReturn)
-{
-  if (aTime.isObject()) {
-    JS::Rooted<JSObject*> timestampObj(aCx, &aTime.toObject());
-    if (!JS_ObjectIsDate(aCx, timestampObj)) {
-      return NS_ERROR_INVALID_ARG;
-    }
-    aReturn = js_DateGetMsecSinceEpoch(timestampObj);
-  } else {
-    if (!aTime.isNumber()) {
-      return NS_ERROR_INVALID_ARG;
-    }
-    double number = aTime.toNumber();
-    if (static_cast<uint64_t>(number) != number) {
-      return NS_ERROR_INVALID_ARG;
-    }
-    aReturn = static_cast<uint64_t>(number);
-  }
-  return NS_OK;
-}
-
-#endif
--- a/dom/mobilemessage/src/MmsMessage.cpp
+++ b/dom/mobilemessage/src/MmsMessage.cpp
@@ -11,17 +11,16 @@
 #include "nsContentUtils.h"
 #include "nsIDOMFile.h"
 #include "nsTArrayHelpers.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/mobilemessage/Constants.h" // For MessageType
 #include "mozilla/dom/mobilemessage/SmsTypes.h"
 #include "nsDOMFile.h"
 #include "nsCxPusher.h"
-#include "MessageUtils.h"
 
 using namespace mozilla::dom::mobilemessage;
 
 DOMCI_DATA(MozMmsMessage, mozilla::dom::MmsMessage)
 
 namespace mozilla {
 namespace dom {
 
@@ -162,32 +161,32 @@ MmsMessage::MmsMessage(const mobilemessa
     // Prepare |info.mReadTimestamp|.
     info.mReadTimestamp = infoData.readTimestamp();
 
     mDeliveryInfo.AppendElement(info);
   }
 }
 
 /* static */ nsresult
-MmsMessage::Create(int32_t               aId,
-                   uint64_t              aThreadId,
-                   const nsAString&      aIccId,
-                   const nsAString&      aDelivery,
-                   const JS::Value&      aDeliveryInfo,
-                   const nsAString&      aSender,
-                   const JS::Value&      aReceivers,
-                   const JS::Value&      aTimestamp,
-                   const JS::Value&      aSentTimestamp,
-                   bool                  aRead,
-                   const nsAString&      aSubject,
-                   const nsAString&      aSmil,
-                   const JS::Value&      aAttachments,
-                   const JS::Value&      aExpiryDate,
-                   bool                  aIsReadReportRequested,
-                   JSContext*            aCx,
+MmsMessage::Create(int32_t aId,
+                   uint64_t aThreadId,
+                   const nsAString& aIccId,
+                   const nsAString& aDelivery,
+                   const JS::Value& aDeliveryInfo,
+                   const nsAString& aSender,
+                   const JS::Value& aReceivers,
+                   uint64_t aTimestamp,
+                   uint64_t aSentTimestamp,
+                   bool aRead,
+                   const nsAString& aSubject,
+                   const nsAString& aSmil,
+                   const JS::Value& aAttachments,
+                   uint64_t aExpiryDate,
+                   bool aIsReadReportRequested,
+                   JSContext* aCx,
                    nsIDOMMozMmsMessage** aMessage)
 {
   *aMessage = nullptr;
 
   // Set |delivery|.
   DeliveryState delivery;
   if (aDelivery.Equals(DELIVERY_SENT)) {
     delivery = eDeliveryState_Sent;
@@ -250,26 +249,16 @@ MmsMessage::Create(int32_t              
       return NS_ERROR_INVALID_ARG;
     }
 
     nsDependentJSString receiverStr;
     receiverStr.init(aCx, receiverJsVal.toString());
     receivers.AppendElement(receiverStr);
   }
 
-  // Set |timestamp|.
-  uint64_t timestamp;
-  nsresult rv = convertTimeToInt(aCx, aTimestamp, timestamp);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Set |sentTimestamp|.
-  uint64_t sentTimestamp;
-  rv = convertTimeToInt(aCx, aSentTimestamp, sentTimestamp);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   // Set |attachments|.
   if (!aAttachments.isObject()) {
     return NS_ERROR_INVALID_ARG;
   }
   JS::Rooted<JSObject*> attachmentsObj(aCx, &aAttachments.toObject());
   if (!JS_IsArrayObject(aCx, attachmentsObj)) {
     return NS_ERROR_INVALID_ARG;
   }
@@ -286,35 +275,30 @@ MmsMessage::Create(int32_t              
     MmsAttachment attachment;
     if (!attachment.Init(aCx, attachmentJsVal)) {
       return NS_ERROR_TYPE_ERR;
     }
 
     attachments.AppendElement(attachment);
   }
 
-  // Set |expiryDate|.
-  uint64_t expiryDate;
-  rv = convertTimeToInt(aCx, aExpiryDate, expiryDate);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   nsCOMPtr<nsIDOMMozMmsMessage> message = new MmsMessage(aId,
                                                          aThreadId,
                                                          aIccId,
                                                          delivery,
                                                          deliveryInfo,
                                                          aSender,
                                                          receivers,
-                                                         timestamp,
-                                                         sentTimestamp,
+                                                         aTimestamp,
+                                                         aSentTimestamp,
                                                          aRead,
                                                          aSubject,
                                                          aSmil,
                                                          attachments,
-                                                         expiryDate,
+                                                         aExpiryDate,
                                                          aIsReadReportRequested);
   message.forget(aMessage);
   return NS_OK;
 }
 
 bool
 MmsMessage::GetData(ContentParent* aParent,
                     mobilemessage::MmsMessageData& aData)
--- a/dom/mobilemessage/src/MmsMessage.h
+++ b/dom/mobilemessage/src/MmsMessage.h
@@ -36,70 +36,70 @@ public:
 
     explicit Attachment(const MmsAttachment& aAttachment) :
       content(aAttachment.mContent),
       id(aAttachment.mId),
       location(aAttachment.mLocation)
     {}
   };
 
-  MmsMessage(int32_t                               aId,
-             uint64_t                              aThreadId,
-             const nsAString&                      aIccId,
-             mobilemessage::DeliveryState          aDelivery,
-             const nsTArray<MmsDeliveryInfo>&      aDeliveryInfo,
-             const nsAString&                      aSender,
-             const nsTArray<nsString>&             aReceivers,
-             uint64_t                              aTimestamp,
-             uint64_t                              aSentTimestamp,
-             bool                                  aRead,
-             const nsAString&                      aSubject,
-             const nsAString&                      aSmil,
-             const nsTArray<Attachment>&           aAttachments,
-             uint64_t                              aExpiryDate,
-             bool                                  aReadReportRequested);
+  MmsMessage(int32_t aId,
+             uint64_t aThreadId,
+             const nsAString& aIccId,
+             mobilemessage::DeliveryState aDelivery,
+             const nsTArray<MmsDeliveryInfo>& aDeliveryInfo,
+             const nsAString& aSender,
+             const nsTArray<nsString>& aReceivers,
+             uint64_t aTimestamp,
+             uint64_t aSentTimestamp,
+             bool aRead,
+             const nsAString& aSubject,
+             const nsAString& aSmil,
+             const nsTArray<Attachment>& aAttachments,
+             uint64_t aExpiryDate,
+             bool aReadReportRequested);
 
   MmsMessage(const mobilemessage::MmsMessageData& aData);
 
-  static nsresult Create(int32_t               aId,
-                         uint64_t              aThreadId,
-                         const nsAString&      aIccId,
-                         const nsAString&      aDelivery,
-                         const JS::Value&      aDeliveryInfo,
-                         const nsAString&      aSender,
-                         const JS::Value&      aReceivers,
-                         const JS::Value&      aTimestamp,
-                         const JS::Value&      aSentTimestamp,
-                         bool                  aRead,
-                         const nsAString&      aSubject,
-                         const nsAString&      aSmil,
-                         const JS::Value&      aAttachments,
-                         const JS::Value&      aExpiryDate,
-                         bool                  aReadReportRequested,
-                         JSContext*            aCx,
+  static nsresult Create(int32_t aId,
+                         uint64_t aThreadId,
+                         const nsAString& aIccId,
+                         const nsAString& aDelivery,
+                         const JS::Value& aDeliveryInfo,
+                         const nsAString& aSender,
+                         const JS::Value& aReceivers,
+                         uint64_t aTimestamp,
+                         uint64_t aSentTimestamp,
+                         bool aRead,
+                         const nsAString& aSubject,
+                         const nsAString& aSmil,
+                         const JS::Value& aAttachments,
+                         uint64_t aExpiryDate,
+                         bool aReadReportRequested,
+                         JSContext* aCx,
                          nsIDOMMozMmsMessage** aMessage);
 
   bool GetData(ContentParent* aParent,
                mobilemessage::MmsMessageData& aData);
 
 private:
 
-  int32_t                        mId;
-  uint64_t                       mThreadId;
-  nsString                       mIccId;
-  mobilemessage::DeliveryState   mDelivery;
-  nsTArray<MmsDeliveryInfo>      mDeliveryInfo;
-  nsString                       mSender;
-  nsTArray<nsString>             mReceivers;
-  uint64_t                       mTimestamp;
-  uint64_t                       mSentTimestamp;
-  bool                           mRead;
-  nsString                       mSubject;
-  nsString                       mSmil;
-  nsTArray<Attachment>           mAttachments;
-  uint64_t                       mExpiryDate;
-  bool                           mReadReportRequested;
+  int32_t mId;
+  uint64_t mThreadId;
+  nsString mIccId;
+  mobilemessage::DeliveryState mDelivery;
+  nsTArray<MmsDeliveryInfo> mDeliveryInfo;
+  nsString mSender;
+  nsTArray<nsString> mReceivers;
+  uint64_t mTimestamp;
+  uint64_t mSentTimestamp;
+  bool mRead;
+  nsString mSubject;
+  nsString mSmil;
+  nsTArray<Attachment> mAttachments;
+  uint64_t mExpiryDate;
+  bool mReadReportRequested;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_mobilemessage_MmsMessage_h
--- a/dom/mobilemessage/src/MobileMessageService.cpp
+++ b/dom/mobilemessage/src/MobileMessageService.cpp
@@ -33,20 +33,20 @@ MobileMessageService::CreateSmsMessage(i
                                        uint64_t aThreadId,
                                        const nsAString& aIccId,
                                        const nsAString& aDelivery,
                                        const nsAString& aDeliveryStatus,
                                        const nsAString& aSender,
                                        const nsAString& aReceiver,
                                        const nsAString& aBody,
                                        const nsAString& aMessageClass,
-                                       JS::Handle<JS::Value> aTimestamp,
-                                       JS::Handle<JS::Value> aSentTimestamp,
-                                       JS::Handle<JS::Value> aDeliveryTimestamp,
-                                       const bool aRead,
+                                       uint64_t aTimestamp,
+                                       uint64_t aSentTimestamp,
+                                       uint64_t aDeliveryTimestamp,
+                                       bool aRead,
                                        JSContext* aCx,
                                        nsIDOMMozSmsMessage** aMessage)
 {
   return SmsMessage::Create(aId,
                             aThreadId,
                             aIccId,
                             aDelivery,
                             aDeliveryStatus,
@@ -58,32 +58,32 @@ MobileMessageService::CreateSmsMessage(i
                             aSentTimestamp,
                             aDeliveryTimestamp,
                             aRead,
                             aCx,
                             aMessage);
 }
 
 NS_IMETHODIMP
-MobileMessageService::CreateMmsMessage(int32_t               aId,
-                                       uint64_t              aThreadId,
-                                       const nsAString&      aIccId,
-                                       const nsAString&      aDelivery,
+MobileMessageService::CreateMmsMessage(int32_t aId,
+                                       uint64_t aThreadId,
+                                       const nsAString& aIccId,
+                                       const nsAString& aDelivery,
                                        JS::Handle<JS::Value> aDeliveryInfo,
-                                       const nsAString&      aSender,
+                                       const nsAString& aSender,
                                        JS::Handle<JS::Value> aReceivers,
-                                       JS::Handle<JS::Value> aTimestamp,
-                                       JS::Handle<JS::Value> aSentTimestamp,
-                                       bool                  aRead,
-                                       const nsAString&      aSubject,
-                                       const nsAString&      aSmil,
+                                       uint64_t aTimestamp,
+                                       uint64_t aSentTimestamp,
+                                       bool aRead,
+                                       const nsAString& aSubject,
+                                       const nsAString& aSmil,
                                        JS::Handle<JS::Value> aAttachments,
-                                       JS::Handle<JS::Value> aExpiryDate,
-                                       bool                  aReadReportRequested,
-                                       JSContext*            aCx,
+                                       uint64_t aExpiryDate,
+                                       bool aReadReportRequested,
+                                       JSContext* aCx,
                                        nsIDOMMozMmsMessage** aMessage)
 {
   return MmsMessage::Create(aId,
                             aThreadId,
                             aIccId,
                             aDelivery,
                             aDeliveryInfo,
                             aSender,
@@ -110,17 +110,17 @@ MobileMessageService::CreateSmsSegmentIn
       new SmsSegmentInfo(aSegments, aCharsPerSegment, aCharsAvailableInLastSegment);
   info.forget(aSegmentInfo);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MobileMessageService::CreateThread(uint64_t aId,
                                    JS::Handle<JS::Value> aParticipants,
-                                   JS::Handle<JS::Value> aTimestamp,
+                                   uint64_t aTimestamp,
                                    const nsAString& aLastMessageSubject,
                                    const nsAString& aBody,
                                    uint64_t aUnreadCount,
                                    const nsAString& aLastMessageType,
                                    JSContext* aCx,
                                    nsIDOMMozMobileMessageThread** aThread)
 {
   return MobileMessageThread::Create(aId,
--- a/dom/mobilemessage/src/MobileMessageThread.cpp
+++ b/dom/mobilemessage/src/MobileMessageThread.cpp
@@ -23,22 +23,22 @@ NS_INTERFACE_MAP_BEGIN(MobileMessageThre
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozMobileMessageThread)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(MobileMessageThread)
 NS_IMPL_RELEASE(MobileMessageThread)
 
 /* static */ nsresult
-MobileMessageThread::Create(const uint64_t aId,
+MobileMessageThread::Create(uint64_t aId,
                             const JS::Value& aParticipants,
-                            const JS::Value& aTimestamp,
+                            uint64_t aTimestamp,
                             const nsAString& aLastMessageSubject,
                             const nsAString& aBody,
-                            const uint64_t aUnreadCount,
+                            uint64_t aUnreadCount,
                             const nsAString& aLastMessageType,
                             JSContext* aCx,
                             nsIDOMMozMobileMessageThread** aThread)
 {
   *aThread = nullptr;
 
   // ThreadData exposes these as references, so we can simply assign
   // to them.
@@ -71,35 +71,20 @@ MobileMessageThread::Create(const uint64
       }
 
       nsDependentJSString str;
       str.init(aCx, val.toString());
       data.participants().AppendElement(str);
     }
   }
 
-  // We support both a Date object and a millisecond timestamp as a number.
-  if (aTimestamp.isObject()) {
-    JS::Rooted<JSObject*> obj(aCx, &aTimestamp.toObject());
-    if (!JS_ObjectIsDate(aCx, obj)) {
-      return NS_ERROR_INVALID_ARG;
-    }
-    data.timestamp() = js_DateGetMsecSinceEpoch(obj);
-  } else {
-    if (!aTimestamp.isNumber()) {
-      return NS_ERROR_INVALID_ARG;
-    }
-    double number = aTimestamp.toNumber();
-    if (static_cast<uint64_t>(number) != number) {
-      return NS_ERROR_INVALID_ARG;
-    }
-    data.timestamp() = static_cast<uint64_t>(number);
-  }
+  // Set |timestamp|;
+  data.timestamp() = aTimestamp;
 
-  // Set |aLastMessageType|.
+  // Set |lastMessageType|.
   {
     MessageType lastMessageType;
     if (aLastMessageType.Equals(MESSAGE_TYPE_SMS)) {
       lastMessageType = eMessageType_SMS;
     } else if (aLastMessageType.Equals(MESSAGE_TYPE_MMS)) {
       lastMessageType = eMessageType_MMS;
     } else {
       return NS_ERROR_INVALID_ARG;
@@ -107,22 +92,22 @@ MobileMessageThread::Create(const uint64
     data.lastMessageType() = lastMessageType;
   }
 
   nsCOMPtr<nsIDOMMozMobileMessageThread> thread = new MobileMessageThread(data);
   thread.forget(aThread);
   return NS_OK;
 }
 
-MobileMessageThread::MobileMessageThread(const uint64_t aId,
+MobileMessageThread::MobileMessageThread(uint64_t aId,
                                          const nsTArray<nsString>& aParticipants,
-                                         const uint64_t aTimestamp,
+                                         uint64_t aTimestamp,
                                          const nsString& aLastMessageSubject,
                                          const nsString& aBody,
-                                         const uint64_t aUnreadCount,
+                                         uint64_t aUnreadCount,
                                          MessageType aLastMessageType)
   : mData(aId, aParticipants, aTimestamp, aLastMessageSubject, aBody,
           aUnreadCount, aLastMessageType)
 {
   MOZ_ASSERT(aParticipants.Length());
 }
 
 MobileMessageThread::MobileMessageThread(const ThreadData& aData)
--- a/dom/mobilemessage/src/MobileMessageThread.h
+++ b/dom/mobilemessage/src/MobileMessageThread.h
@@ -18,32 +18,32 @@ class MobileMessageThread MOZ_FINAL : pu
 {
 private:
   typedef mobilemessage::ThreadData ThreadData;
 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMMOZMOBILEMESSAGETHREAD
 
-  MobileMessageThread(const uint64_t aId,
+  MobileMessageThread(uint64_t aId,
                       const nsTArray<nsString>& aParticipants,
-                      const uint64_t aTimestamp,
+                      uint64_t aTimestamp,
                       const nsString& aLastMessageSubject,
                       const nsString& aBody,
-                      const uint64_t aUnreadCount,
+                      uint64_t aUnreadCount,
                       mobilemessage::MessageType aLastMessageType);
 
   MobileMessageThread(const ThreadData& aData);
 
-  static nsresult Create(const uint64_t aId,
+  static nsresult Create(uint64_t aId,
                          const JS::Value& aParticipants,
-                         const JS::Value& aTimestamp,
+                         uint64_t aTimestamp,
                          const nsAString& aLastMessageSubject,
                          const nsAString& aBody,
-                         const uint64_t aUnreadCount,
+                         uint64_t aUnreadCount,
                          const nsAString& aLastMessageType,
                          JSContext* aCx,
                          nsIDOMMozMobileMessageThread** aThread);
 
   const ThreadData& GetData() const { return mData; }
 
 private:
   // Don't try to use the default constructor.
--- a/dom/mobilemessage/src/SmsMessage.cpp
+++ b/dom/mobilemessage/src/SmsMessage.cpp
@@ -3,17 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SmsMessage.h"
 #include "nsIDOMClassInfo.h"
 #include "jsapi.h" // For OBJECT_TO_JSVAL and JS_NewDateObjectMsec
 #include "jsfriendapi.h" // For js_DateGetMsecSinceEpoch
 #include "mozilla/dom/mobilemessage/Constants.h" // For MessageType
-#include "MessageUtils.h"
 
 using namespace mozilla::dom::mobilemessage;
 
 DOMCI_DATA(MozSmsMessage, mozilla::dom::SmsMessage)
 
 namespace mozilla {
 namespace dom {
 
@@ -55,20 +54,20 @@ SmsMessage::Create(int32_t aId,
                    uint64_t aThreadId,
                    const nsAString& aIccId,
                    const nsAString& aDelivery,
                    const nsAString& aDeliveryStatus,
                    const nsAString& aSender,
                    const nsAString& aReceiver,
                    const nsAString& aBody,
                    const nsAString& aMessageClass,
-                   const JS::Value& aTimestamp,
-                   const JS::Value& aSentTimestamp,
-                   const JS::Value& aDeliveryTimestamp,
-                   const bool aRead,
+                   uint64_t aTimestamp,
+                   uint64_t aSentTimestamp,
+                   uint64_t aDeliveryTimestamp,
+                   bool aRead,
                    JSContext* aCx,
                    nsIDOMMozSmsMessage** aMessage)
 {
   *aMessage = nullptr;
 
   // SmsMessageData exposes these as references, so we can simply assign
   // to them.
   SmsMessageData data;
@@ -114,26 +113,23 @@ SmsMessage::Create(int32_t aId,
     data.messageClass() = eMessageClass_Class2;
   } else if (aMessageClass.Equals(MESSAGE_CLASS_CLASS_3)) {
     data.messageClass() = eMessageClass_Class3;
   } else {
     return NS_ERROR_INVALID_ARG;
   }
 
   // Set |timestamp|.
-  nsresult rv = convertTimeToInt(aCx, aTimestamp, data.timestamp());
-  NS_ENSURE_SUCCESS(rv, rv);
+  data.timestamp() = aTimestamp;
 
   // Set |sentTimestamp|.
-  rv = convertTimeToInt(aCx, aSentTimestamp, data.sentTimestamp());
-  NS_ENSURE_SUCCESS(rv, rv);
+  data.sentTimestamp() = aSentTimestamp;
 
   // Set |deliveryTimestamp|.
-  rv = convertTimeToInt(aCx, aDeliveryTimestamp, data.deliveryTimestamp());
-  NS_ENSURE_SUCCESS(rv, rv);
+  data.deliveryTimestamp() = aDeliveryTimestamp;
 
   nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(data);
   message.swap(*aMessage);
   return NS_OK;
 }
 
 const SmsMessageData&
 SmsMessage::GetData() const
--- a/dom/mobilemessage/src/SmsMessage.h
+++ b/dom/mobilemessage/src/SmsMessage.h
@@ -29,31 +29,32 @@ public:
              const nsString& aSender,
              const nsString& aReceiver,
              const nsString& aBody,
              mobilemessage::MessageClass aMessageClass,
              uint64_t aTimestamp,
              uint64_t aSentTimestamp,
              uint64_t aDeliveryTimestamp,
              bool aRead);
+
   SmsMessage(const mobilemessage::SmsMessageData& aData);
 
   static nsresult Create(int32_t aId,
                          uint64_t aThreadId,
                          const nsAString& aIccId,
                          const nsAString& aDelivery,
                          const nsAString& aDeliveryStatus,
                          const nsAString& aSender,
                          const nsAString& aReceiver,
                          const nsAString& aBody,
                          const nsAString& aMessageClass,
-                         const JS::Value& aTimestamp,
-                         const JS::Value& aSentTimestamp,
-                         const JS::Value& aDeliveryTimestamp,
-                         const bool aRead,
+                         uint64_t aTimestamp,
+                         uint64_t aSentTimestamp,
+                         uint64_t aDeliveryTimestamp,
+                         bool aRead,
                          JSContext* aCx,
                          nsIDOMMozSmsMessage** aMessage);
   const mobilemessage::SmsMessageData& GetData() const;
 
 private:
   // Don't try to use the default constructor.
   SmsMessage();
 
--- a/dom/mobilemessage/src/android/SmsService.cpp
+++ b/dom/mobilemessage/src/android/SmsService.cpp
@@ -32,20 +32,20 @@ SmsService::GetSegmentInfoForText(const 
 
   nsresult rv = AndroidBridge::Bridge()->GetSegmentInfoForText(aText, aRequest);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-SmsService::Send(uint32_t         aServiceId,
+SmsService::Send(uint32_t aServiceId,
                  const nsAString& aNumber,
                  const nsAString& aMessage,
-                 const bool       aSilent,
+                 bool aSilent,
                  nsIMobileMessageCallback* aRequest)
 {
   if (!AndroidBridge::Bridge()) {
     return NS_OK;
   }
 
   AndroidBridge::Bridge()->SendMessage(aNumber, aMessage, aRequest);
   return NS_OK;
--- a/dom/mobilemessage/src/gonk/SmsService.cpp
+++ b/dom/mobilemessage/src/gonk/SmsService.cpp
@@ -92,20 +92,20 @@ SmsService::GetSegmentInfoForText(const 
     mRil->GetRadioInterface(0, getter_AddRefs(radioInterface));
   }
   NS_ENSURE_TRUE(radioInterface, NS_ERROR_FAILURE);
 
   return radioInterface->GetSegmentInfoForText(aText, aRequest);
 }
 
 NS_IMETHODIMP
-SmsService::Send(uint32_t         aServiceId,
+SmsService::Send(uint32_t aServiceId,
                  const nsAString& aNumber,
                  const nsAString& aMessage,
-                 const bool       aSilent,
+                 bool aSilent,
                  nsIMobileMessageCallback* aRequest)
 {
   nsCOMPtr<nsIRadioInterface> radioInterface;
   if (mRil) {
     mRil->GetRadioInterface(aServiceId, getter_AddRefs(radioInterface));
   }
   NS_ENSURE_TRUE(radioInterface, NS_ERROR_FAILURE);
 
--- a/dom/mobilemessage/src/ipc/SmsIPCService.cpp
+++ b/dom/mobilemessage/src/ipc/SmsIPCService.cpp
@@ -160,17 +160,17 @@ SmsIPCService::GetSmscAddress(uint32_t a
 {
   return SendRequest(GetSmscAddressRequest(aServiceId), aRequest);
 }
 
 NS_IMETHODIMP
 SmsIPCService::Send(uint32_t aServiceId,
                     const nsAString& aNumber,
                     const nsAString& aMessage,
-                    const bool aSilent,
+                    bool aSilent,
                     nsIMobileMessageCallback* aRequest)
 {
   return SendRequest(SendMessageRequest(SendSmsMessageRequest(aServiceId,
                                                               nsString(aNumber),
                                                               nsString(aMessage),
                                                               aSilent)),
                      aRequest);
 }
--- a/dom/mobilemessage/src/ipc/SmsTypes.ipdlh
+++ b/dom/mobilemessage/src/ipc/SmsTypes.ipdlh
@@ -89,22 +89,22 @@ struct SmsFilterData
   nsString[]    numbers;
   DeliveryState delivery;
   ReadState     read;
   uint64_t      threadId;
 };
 
 struct ThreadData
 {
-  uint64_t id;
-  nsString[] participants;
-  uint64_t timestamp;
-  nsString lastMessageSubject;
-  nsString body;
-  uint64_t unreadCount;
+  uint64_t    id;
+  nsString[]  participants;
+  uint64_t    timestamp;
+  nsString    lastMessageSubject;
+  nsString    body;
+  uint64_t    unreadCount;
   MessageType lastMessageType;
 };
 
 union MobileMessageCursorData
 {
   MmsMessageData;
   SmsMessageData;
   ThreadData;
--- a/dom/mobilemessage/tests/test_smsservice_createsmsmessage.js
+++ b/dom/mobilemessage/tests/test_smsservice_createsmsmessage.js
@@ -28,17 +28,17 @@ function run_test() {
   run_next_test();
 }
 
 /**
  * Ensure an SmsMessage object created has sensible initial values.
  */
 add_test(function test_interface() {
   let sms = newMessage(null, null, ICC_ID, "sent", "success", null, null, null,
-                       "normal", new Date(), new Date(), new Date(), true);
+                       "normal", Date.now(), Date.now(), Date.now(), true);
   do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage);
   do_check_eq(sms.id, 0);
   do_check_eq(sms.threadId, 0);
   do_check_eq(sms.iccId, ICC_ID);
   do_check_eq(sms.delivery, "sent");
   do_check_eq(sms.deliveryStatus, "success");
   do_check_eq(sms.receiver, null);
   do_check_eq(sms.sender, null);
@@ -48,17 +48,17 @@ add_test(function test_interface() {
   run_next_test();
 });
 
 /**
  * Test if ICC ID is null when it's not available.
  */
 add_test(function test_icc_id_not_available() {
   let sms = newMessage(null, null, null, "sent", "success", null, null, null,
-                       "normal", new Date(), new Date(), new Date(), true);
+                       "normal", Date.now(), Date.now(), Date.now(), true);
   do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage);
   do_check_eq(sms.id, 0);
   do_check_eq(sms.threadId, 0);
   do_check_eq(sms.iccId, null);
   do_check_eq(sms.delivery, "sent");
   do_check_eq(sms.deliveryStatus, "success");
   do_check_eq(sms.receiver, null);
   do_check_eq(sms.sender, null);
@@ -68,17 +68,17 @@ add_test(function test_icc_id_not_availa
   run_next_test();
 });
 
 /**
  * Verify that attributes are read-only.
  */
 add_test(function test_readonly_attributes() {
   let sms = newMessage(null, null, ICC_ID, "sent", "success", null, null, null,
-                       "normal", new Date(), new Date(), new Date(), true);
+                       "normal", Date.now(), Date.now(), Date.now(), true);
 
   sms.id = 1;
   do_check_eq(sms.id, 0);
 
   sms.threadId = 1;
   do_check_eq(sms.threadId, 0);
 
   sms.iccId = "987654321";
@@ -139,17 +139,18 @@ add_test(function test_timestamp_number(
   do_check_eq(sms.timestamp, ts);
   do_check_eq(sms.sentTimestamp, ts);
   do_check_eq(sms.deliveryTimestamp, ts);
   do_check_true(sms.read);
   run_next_test();
 });
 
 /**
- * Test supplying the timestamp as a Date object.
+ * Test supplying the timestamp as a Date object, which will be automatically
+ * casted to unsigned long long.
  */
 add_test(function test_timestamp_date() {
   let date = new Date();
   let sms = newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
                        "the body", "normal", date, date, date, true);
   do_check_eq(sms.id, 42);
   do_check_eq(sms.threadId, 1);
   do_check_eq(sms.iccId, ICC_ID);
@@ -162,172 +163,72 @@ add_test(function test_timestamp_date() 
   do_check_eq(sms.timestamp, date.getTime());
   do_check_eq(sms.sentTimestamp, date.getTime());
   do_check_eq(sms.deliveryTimestamp, date.getTime());
   do_check_true(sms.read);
   run_next_test();
 });
 
 /**
- * Test that a floating point number for the timestamp is not allowed.
- */
-add_test(function test_invalid_timestamp_float() {
-  // Test timestamp.
-  do_check_throws(function() {
-    newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "normal", 3.1415, new Date(), new Date(), true);
-  }, Cr.NS_ERROR_INVALID_ARG);
-
-  // Test sentTimestamp.
-  do_check_throws(function() {
-    newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "normal", new Date(), 3.1415, new Date(), true);
-  }, Cr.NS_ERROR_INVALID_ARG);
-
-  // Test deliveryTimestamp.
-  do_check_throws(function() {
-    newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "normal", new Date(), new Date(), 3.1415, true);
-  }, Cr.NS_ERROR_INVALID_ARG);
-
-  run_next_test();
-});
-
-/**
- * Test that a null value for the timestamp is not allowed.
- */
-add_test(function test_invalid_timestamp_null() {
-  // Test timestamp.
-  do_check_throws(function() {
-    newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "normal", null, new Date(), new Date(), true);
-  }, Cr.NS_ERROR_INVALID_ARG);
-
-  // Test sentTimestamp.
-  do_check_throws(function() {
-    newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "normal", new Date(), null, new Date(), true);
-  }, Cr.NS_ERROR_INVALID_ARG);
-
-  // Test deliveryTimestamp.
-  do_check_throws(function() {
-    newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "normal", new Date(), new Date(), null, true);
-  }, Cr.NS_ERROR_INVALID_ARG);
-
-  run_next_test();
-});
-
-/**
- * Test that undefined for the timestamp is not allowed.
- */
-add_test(function test_invalid_timestamp_undefined() {
-  // Test timestamp.
-  do_check_throws(function() {
-    newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "normal", undefined, new Date(), new Date(), true);
-  }, Cr.NS_ERROR_INVALID_ARG);
-
-  // Test sentTimestamp.
-  do_check_throws(function() {
-    newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "normal", new Date(), undefined, new Date(), true);
-  }, Cr.NS_ERROR_INVALID_ARG);
-
-  // Test deliveryTimestamp.
-  do_check_throws(function() {
-    newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "normal", new Date(), new Date(), undefined, true);
-  }, Cr.NS_ERROR_INVALID_ARG);
-
-  run_next_test();
-});
-
-/**
- * Test that a random object for the timestamp is not allowed.
- */
-add_test(function test_invalid_timestamp_object() {
-  // Test timestamp.
-  do_check_throws(function() {
-    newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "normal", {}, new Date(), new Date(), true);
-  }, Cr.NS_ERROR_INVALID_ARG);
-
-  // Test sentTimestamp.
-  do_check_throws(function() {
-    newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "normal", new Date(), {}, new Date(), true);
-  }, Cr.NS_ERROR_INVALID_ARG);
-
-  // Test deliveryTimestamp.
-  do_check_throws(function() {
-    newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "normal", new Date(), new Date(), {}, true);
-  }, Cr.NS_ERROR_INVALID_ARG);
-
-  run_next_test();
-});
-
-/**
  * Test that an invalid delivery string is not accepted.
  */
 add_test(function test_invalid_delivery_string() {
   do_check_throws(function() {
     newMessage(42, 1, ICC_ID, "this is invalid", "pending", "the sender",
-               "the receiver", "the body", "normal", new Date(), 0, 0, true);
+               "the receiver", "the body", "normal", Date.now(), 0, 0, true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that a number is not accepted for the 'delivery' argument.
  */
 add_test(function test_invalid_delivery_string() {
   do_check_throws(function() {
     newMessage(42, 1, ICC_ID, 1, "pending", "the sender", "the receiver", "the body",
-               "normal", new Date(), 0, 0, true);
+               "normal", Date.now(), 0, 0, true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that an invalid delivery status string is not accepted.
  */
 add_test(function test_invalid_delivery_status_string() {
   do_check_throws(function() {
     newMessage(42, 1, ICC_ID, "sent", "this is invalid", "the sender", "the receiver",
-               "the body", "normal", new Date(), new Date(), 0, true);
+               "the body", "normal", Date.now(), Date.now(), 0, true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that a number is not accepted for the 'deliveryStatus' argument.
  */
 add_test(function test_invalid_delivery_status_string() {
   do_check_throws(function() {
     newMessage(42, 1, ICC_ID, "sent", 1, "the sender", "the receiver", "the body",
-               "normal", new Date(), new Date(), 0, true);
+               "normal", Date.now(), Date.now(), 0, true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that an invalid message class string is not accepted.
  */
 add_test(function test_invalid_message_class_string() {
   do_check_throws(function() {
     newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", "this is invalid", new Date(), new Date(), new Date(), true);
+               "the body", "this is invalid", Date.now(), Date.now(), Date.now(), true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that a number is not accepted for the 'messageClass' argument.
  */
 add_test(function test_invalid_message_class_string() {
   do_check_throws(function() {
     newMessage(42, 1, ICC_ID, "sent", "success", "the sender", "the receiver",
-               "the body", 1, new Date(), new Date(), new Date(), true);
+               "the body", 1, Date.now(), Date.now(), Date.now(), true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
--- a/dom/permission/tests/test_wifi-manage.html
+++ b/dom/permission/tests/test_wifi-manage.html
@@ -25,17 +25,17 @@ function verifier(success, failure) {
   }
 }
 
 var gData = [
   {
     perm: ["wifi-manage"],
     needParentPerm: true,
     obj: "mozWifiManager",
-    idl: "nsIDOMWifiManager",
+    webidl: "MozWifiManager",
     verifier: verifier.toSource(),
   },
 ]
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/system/gonk/NetworkInterfaceListService.js
+++ b/dom/system/gonk/NetworkInterfaceListService.js
@@ -33,17 +33,20 @@ NetworkInterfaceListService.prototype = 
           excludeSupl: (aConditions &
                         Ci.nsINetworkInterfaceListService.
                         LIST_NOT_INCLUDE_SUPL_INTERFACES) != 0,
           excludeMms: (aConditions &
                        Ci.nsINetworkInterfaceListService.
                        LIST_NOT_INCLUDE_MMS_INTERFACES) != 0,
           excludeIms: (aConditions &
                        Ci.nsINetworkInterfaceListService.
-                       LIST_NOT_INCLUDE_IMS_INTERFACES) != 0
+                       LIST_NOT_INCLUDE_IMS_INTERFACES) != 0,
+          excludeDun: (aConditions &
+                       Ci.nsINetworkInterfaceListService.
+                       LIST_NOT_INCLUDE_DUN_INTERFACES) != 0
         }
       )[0]);
   }
 };
 
 function NetworkInterfaceList (aInterfaces) {
   this._interfaces = aInterfaces;
 }
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -447,17 +447,18 @@ NetworkManager.prototype = {
     this._overriddenActive = network;
     this.setAndConfigureActive();
   },
 
 #ifdef MOZ_B2G_RIL
   isNetworkTypeSecondaryMobile: function(type) {
     return (type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
             type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL ||
-            type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS);
+            type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS ||
+            type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN);
   },
 
   isNetworkTypeMobile: function(type) {
     return (type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
             this.isNetworkTypeSecondaryMobile(type));
   },
 
   setExtraHostRoute: function(network) {
--- a/dom/system/gonk/moz.build
+++ b/dom/system/gonk/moz.build
@@ -59,21 +59,21 @@ SOURCES += [
 
 if CONFIG['ENABLE_TESTS']:
     XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell.ini']
 
 EXTRA_COMPONENTS += [
     'NetworkInterfaceListService.js',
     'NetworkInterfaceListService.manifest',
     'NetworkManager.manifest',
+    'NetworkService.js',
     'NetworkService.manifest',
 ]
 EXTRA_PP_COMPONENTS += [
     'NetworkManager.js',
-    'NetworkService.js',
 ]
 EXTRA_JS_MODULES += [
     'systemlibs.js',
 ]
 
 if CONFIG['MOZ_B2G_RIL']:
     XPIDL_SOURCES += [
         'nsIRadioInterfaceLayer.idl',
--- a/dom/system/gonk/tests/marionette/test_data_connection.js
+++ b/dom/system/gonk/tests/marionette/test_data_connection.js
@@ -54,17 +54,17 @@ function getSetting(key) {
   return deferred.promise;
 }
 
 function setEmulatorAPN() {
   let apn = [
     [{"carrier":"T-Mobile US",
       "apn":"epc.tmobile.com",
       "mmsc":"http://mms.msg.eng.t-mobile.com/mms/wapenc",
-      "types":["default","supl","mms","ims"]}]
+      "types":["default","supl","mms","ims","dun"]}]
   ];
 
   return setSetting(APN_KEY, apn);
 }
 
 function waitNetworkConnected(networkType) {
   log("wait network " + networkType + " connected");
 
@@ -150,17 +150,18 @@ function testNonDefaultDataConnection() 
   log("= testNonDefaultDataConnection =");
 
   function doTestNonDefaultDataConnection(type) {
     log("doTestNonDefaultDataConnection: " + type);
 
     let typeMapping = {
       "mms": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS,
       "supl": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL,
-      "ims": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS
+      "ims": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS,
+      "dun": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN
     };
     let networkType = typeMapping[type];
 
     return Promise.resolve()
       .then(() => radioInterface.setupDataCallByType(type))
       .then(() => waitNetworkConnected(networkType))
       .then(() => radioInterface.deactivateDataCallByType(type))
       .then(() => waitNetworkDisconnected(networkType));
@@ -171,16 +172,17 @@ function testNonDefaultDataConnection() 
     .then(() => getSetting(APN_KEY))
     .then(value => {
       currentApn = value;
     })
     .then(setEmulatorAPN)
     .then(() => doTestNonDefaultDataConnection("mms"))
     .then(() => doTestNonDefaultDataConnection("supl"))
     .then(() => doTestNonDefaultDataConnection("ims"))
+    .then(() => doTestNonDefaultDataConnection("dun"))
     // Restore APN settings
     .then(() => setSetting(APN_KEY, currentApn))
     .then(null, () => {
       ok(false, "promise rejected during test");
     })
     .then(runNextTest);
 }
 
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -673,18 +673,26 @@ var interfaceNamesInGlobalScope =
     {name: "MozTimeManager", b2g: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozVoicemail", b2g: true, pref: "dom.voicemail.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozVoicemailEvent", b2g: true, pref: "dom.voicemail.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWakeLock", b2g: true, pref: "dom.wakelock.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "MozWifiConnection", b2g: true, permission: "wifi-manage"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "MozWifiConnectionInfo", b2g: true, permission: "wifi-manage"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWifiConnectionInfoEvent", b2g: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "MozWifiManager", b2g: true, permission: "wifi-manage"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "MozWifiNetwork", b2g: true, permission: "wifi-manage"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWifiStatusChangeEvent", b2g: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWifiP2pGroupOwner", b2g: true, permission: "wifi-manage"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWifiP2pManager", b2g: true, permission: "wifi-manage"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWifiP2pStatusChangeEvent", b2g: true, permission: "wifi-manage"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/webidl/MediaRecorder.webidl
+++ b/dom/webidl/MediaRecorder.webidl
@@ -7,17 +7,17 @@
  * https://dvcs.w3.org/hg/dap/raw-file/default/media-stream-capture/MediaRecorder.html
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 enum RecordingState { "inactive", "recording", "paused" };
 
-[Constructor(MediaStream stream)]
+[Constructor(MediaStream stream, optional MediaRecorderOptions options)]
 interface MediaRecorder : EventTarget {
 
   readonly attribute MediaStream stream;
 
   readonly attribute RecordingState state;
 
   readonly attribute DOMString mimeType;
 
@@ -40,8 +40,11 @@ interface MediaRecorder : EventTarget {
 
   [Throws]
   void resume();
 
   [Throws]
   void requestData();
 };
 
+dictionary MediaRecorderOptions {
+  DOMString mimeType = ""; // Default encoding mimeType.
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/MozWifiManager.webidl
@@ -0,0 +1,237 @@
+/* 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/. */
+
+enum WifiWPSMethod {
+  "pbc",
+  "pin",
+  "cancel"
+};
+
+enum ConnectionStatus {
+  "connecting",
+  "associated",
+  "connected",
+  "disconnected"
+};
+
+dictionary WifiWPSInfo {
+  WifiWPSMethod method;
+  DOMString? pin;
+  DOMString? bssid;
+};
+
+dictionary NetworkProperties {
+  DOMString ssid;
+  sequence<DOMString>? security;
+  sequence<DOMString>? capabilities;
+  boolean known;
+  boolean connected;
+  boolean hidden;
+};
+
+[Constructor(optional NetworkProperties properties),
+ JSImplementation="@mozilla.org/mozwifinetwork;1"]
+interface MozWifiNetwork {
+  readonly attribute DOMString ssid;
+  readonly attribute any security;
+  readonly attribute any capabilities;
+  readonly attribute boolean known;
+  readonly attribute boolean connected;
+  readonly attribute boolean hidden;
+
+           attribute DOMString? bssid;
+           attribute DOMString? signalStrength;
+           attribute long? relSignalStrength;
+           attribute DOMString? psk;
+           attribute DOMString? keyManagement;
+           attribute DOMString? identity;
+           attribute DOMString? password;
+           attribute DOMString? phase1;
+           attribute DOMString? phase2;
+           attribute DOMString? eap;
+           attribute DOMString? pin;
+};
+
+[JSImplementation="@mozilla.org/mozwificonnection;1"]
+interface MozWifiConnection {
+  readonly attribute ConnectionStatus status;
+  readonly attribute MozWifiNetwork? network;
+};
+
+[JSImplementation="@mozilla.org/mozwificonnectioninfo;1"]
+interface MozWifiConnectionInfo {
+  readonly attribute short signalStrength;
+  readonly attribute short relSignalStrength;
+  readonly attribute long linkSpeed;
+  readonly attribute DOMString? ipAddress;
+};
+
+dictionary IPConfiguration {
+  boolean enabled;
+  DOMString ipaddr;
+  DOMString proxy;
+  short maskLength;
+  DOMString gateway;
+  DOMString dns1;
+  DOMString dns2;
+};
+
+[JSImplementation="@mozilla.org/wifimanager;1",
+ NavigatorProperty="mozWifiManager",
+ Func="Navigator::HasWifiManagerSupport"]
+interface MozWifiManager : EventTarget {
+  /**
+   * Returns the list of currently available networks.
+   * onsuccess: We have obtained the current list of networks. request.value
+   *            is an object whose property names are SSIDs and values are
+   *            network objects.
+   * onerror: We were unable to obtain a list of property names.
+   */
+  DOMRequest getNetworks();
+
+  /**
+   * Returns the list of networks known to the system that will be
+   * automatically connected to if they're in range.
+   * onsuccess: request.value is an object whose property names are
+   *            SSIDs and values are network objects.
+   * onerror: We were unable to obtain a list of known networks.
+   */
+  DOMRequest getKnownNetworks();
+
+  /**
+   * Takes one of the networks returned from getNetworks and tries to
+   * connect to it.
+   * @param network A network object with information about the network,
+   *                such as the SSID, key management desired, etc.
+   * onsuccess: We have started attempting to associate with the network.
+   *            request.value is true.
+   * onerror: We were unable to select the network. This most likely means a
+   *          configuration error.
+   */
+  DOMRequest associate(MozWifiNetwork network);
+
+  /**
+   * Given a network, removes it from the list of networks that we'll
+   * automatically connect to. In order to re-connect to the network, it is
+   * necessary to call associate on it.
+   * @param network A network object with the SSID of the network to remove.
+   * onsuccess: We have removed this network. If we were previously
+   *            connected to it, we have started reconnecting to the next
+   *            network in the list.
+   * onerror: We were unable to remove the network.
+   */
+  DOMRequest forget(MozWifiNetwork network);
+
+  /**
+   * Wi-Fi Protected Setup functionality.
+   * @param detail WPS detail which has 'method' and 'pin' field.
+   *               The possible method field values are:
+   *                 - pbc: The Push Button Configuration.
+   *                 - pin: The PIN configuration.
+   *                 - cancel: Request to cancel WPS in progress.
+   *               If method field is 'pin', 'pin' field can exist and has
+   *               a PIN number.
+   *               If method field is 'pin', 'bssid' field can exist and has
+   *               a opposite BSSID.
+   * onsuccess: We have successfully started/canceled wps.
+   * onerror: We have failed to start/cancel wps.
+   */
+  DOMRequest wps(optional WifiWPSInfo detail);
+
+  /**
+   * Turn on/off wifi power saving mode.
+   * @param enabled true or false.
+   * onsuccess: We have successfully turn on/off wifi power saving mode.
+   * onerror: We have failed to turn on/off wifi power saving mode.
+   */
+  DOMRequest setPowerSavingMode(boolean enabled);
+
+  /**
+   * Given a network, configure using static IP instead of running DHCP
+   * @param network A network object with the SSID of the network to set static ip.
+   * @param info info should have following field:
+   *        - enabled True to enable static IP, false to use DHCP
+   *        - ipaddr configured static IP address
+   *        - proxy configured proxy server address
+   *        - maskLength configured mask length
+   *        - gateway configured gateway address
+   *        - dns1 configured first DNS server address
+   *        - dns2 configured seconf DNS server address
+   * onsuccess: We have successfully configure the static ip mode.
+   * onerror: We have failed to configure the static ip mode.
+   */
+  DOMRequest setStaticIpMode(MozWifiNetwork network, optional IPConfiguration info);
+
+  /**
+   * Given a network, configure http proxy when using wifi.
+   * @param network A network object with the SSID of the network to set http proxy.
+   * @param info info should have following field:
+   *        - httpProxyHost ip address of http proxy.
+   *        - httpProxyPort port of http proxy, set 0 to use default port 8080.
+   *        set info to null to clear http proxy.
+   * onsuccess: We have successfully configure http proxy.
+   * onerror: We have failed to configure http proxy.
+   */
+  DOMRequest setHttpProxy(MozWifiNetwork network, any info);
+
+  /**
+   * Returns whether or not wifi is currently enabled.
+   */
+  readonly attribute boolean enabled;
+
+  /**
+   * Returns the MAC address of the wifi adapter.
+   */
+  readonly attribute DOMString macAddress;
+
+  /**
+   * An non-null object containing the following information:
+   *  - status ("disconnected", "connecting", "associated", "connected")
+   *  - network
+   *
+   *  Note that the object returned is read only. Any changes required must
+   *  be done by calling other APIs.
+   */
+  readonly attribute MozWifiConnection? connection;
+
+  /**
+   * A connectionInformation object with the same information found in an
+   * nsIDOMMozWifiConnectionInfoEvent (but without the network).
+   * If we are not currently connected to a network, this will be null.
+   */
+  readonly attribute MozWifiConnectionInfo? connectionInformation;
+
+  /**
+   * State notification listeners. These all take an
+   * nsIDOMMozWifiStatusChangeEvent with the new status and a network (which
+   * may be null).
+   *
+   * The possible statuses are:
+   *   - connecting: Fires when we start the process of connecting to a
+   *                 network.
+   *   - associated: Fires when we have connected to an access point but do
+   *                 not yet have an IP address.
+   *   - connected: Fires once we are fully connected to an access point and
+   *                can access the internet.
+   *   - disconnected: Fires when we either fail to connect to an access
+   *                   point (transition: associated -> disconnected) or
+   *                   when we were connected to a network but have
+   *                   disconnected for any reason (transition: connected ->
+   *                   disconnected).
+   */
+  attribute EventHandler onstatuschange;
+
+  /**
+   * An event listener that is called with information about the signal
+   * strength and link speed every 5 seconds.
+   */
+  attribute EventHandler onconnectionInfoUpdate;
+
+  /**
+   * These two events fire when the wifi system is brought online or taken
+   * offline.
+   */
+  attribute EventHandler onenabled;
+  attribute EventHandler ondisabled;
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -548,16 +548,17 @@ if CONFIG['MOZ_NFC']:
          'MozNFCPeer.webidl',
          'MozNFCTag.webidl',
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     WEBIDL_FILES += [
         'MozSpeakerManager.webidl',
         'MozWifiConnectionInfoEvent.webidl',
+        'MozWifiManager.webidl',
         'MozWifiP2pManager.webidl',
         'MozWifiP2pStatusChangeEvent.webidl',
         'MozWifiStatusChangeEvent.webidl',
     ]
 
 if CONFIG['MOZ_WEBSPEECH']:
     WEBIDL_FILES += [
         'SpeechRecognitionError.webidl',
--- a/dom/wifi/DOMWifiManager.js
+++ b/dom/wifi/DOMWifiManager.js
@@ -10,77 +10,84 @@ const {classes: Cc, interfaces: Ci, util
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
 
 const DEBUG = false; // set to false to suppress debug messages
 
 const DOMWIFIMANAGER_CONTRACTID = "@mozilla.org/wifimanager;1";
-const DOMWIFIMANAGER_CID        = Components.ID("{2cf775a7-1837-410c-9e26-323c42e076da}");
+const DOMWIFIMANAGER_CID        = Components.ID("{c9b5f09e-25d2-40ca-aef4-c4d13d93c706}");
 
-function DOMWifiManager() {
-}
-
-function exposeCurrentNetwork(currentNetwork) {
-  currentNetwork.__exposedProps__ = exposeCurrentNetwork.currentNetworkApi;
+function MozWifiNetwork() {
 }
 
-exposeCurrentNetwork.currentNetworkApi = {
-  ssid: "r",
-  security: "r",
-  capabilities: "r",
-  known: "r"
+MozWifiNetwork.prototype = {
+
+  init: function(aWindow) {
+    this._window = aWindow;
+  },
+
+  __init: function(obj) {
+    this.ssid = obj.ssid;
+    this.security = obj.security;
+    this.capabilities = obj.capabilities;
+    this.known = obj.known;
+    this.connected = obj.connected;
+    this.hidden = obj.hidden;
+  },
+
+  classID: Components.ID("{c01fd751-43c0-460a-8b64-abf652ec7220}"),
+  contractID: "@mozilla.org/mozwifinetwork;1",
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
+                                         Ci.nsIDOMGlobalPropertyInitializer])
 };
 
-// For smaller, read-only APIs, we expose any property that doesn't begin with
-// an underscore.
-function exposeReadOnly(obj) {
-  var exposedProps = {};
-  for (let i in obj) {
-    if (i[0] === "_")
-      continue;
-    exposedProps[i] = "r";
-  }
+function MozWifiConnection(obj) {
+  this.status = obj.status;
+  this.network = obj.network;
+}
+
+MozWifiConnection.prototype = {
+  classID: Components.ID("{23579da4-201b-4319-bd42-9b7f337343ac}"),
+  contractID: "@mozilla.org/mozwificonnection;1",
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
+};
 
-  obj.__exposedProps__ = exposedProps;
-  return obj;
+function MozWifiConnectionInfo(obj) {
+  this.signalStrength = obj.signalStrength;
+  this.relSignalStrength = obj.relSignalStrength;
+  this.linkSpeed = obj.linkSpeed;
+  this.ipAddress = obj.ipAddress;
+}
+
+MozWifiConnectionInfo.prototype = {
+  classID: Components.ID("{83670352-6ed4-4c35-8de9-402296a1959c}"),
+  contractID: "@mozilla.org/mozwificonnectioninfo;1",
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
+}
+
+function DOMWifiManager() {
+  this.defineEventHandlerGetterSetter("onstatuschange");
+  this.defineEventHandlerGetterSetter("onconnectionInfoUpdate");
+  this.defineEventHandlerGetterSetter("onenabled");
+  this.defineEventHandlerGetterSetter("ondisabled");
 }
 
 DOMWifiManager.prototype = {
   __proto__: DOMRequestIpcHelper.prototype,
-
-  classID:   DOMWIFIMANAGER_CID,
-  classInfo: XPCOMUtils.generateCI({classID: DOMWIFIMANAGER_CID,
-                                    contractID: DOMWIFIMANAGER_CONTRACTID,
-                                    classDescription: "DOMWifiManager",
-                                    interfaces: [Ci.nsIDOMWifiManager],
-                                    flags: Ci.nsIClassInfo.DOM_OBJECT}),
-
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMWifiManager,
-                                         Ci.nsIDOMGlobalPropertyInitializer,
+  classDescription: "DOMWifiManager",
+  classID: DOMWIFIMANAGER_CID,
+  contractID: DOMWIFIMANAGER_CONTRACTID,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
                                          Ci.nsISupportsWeakReference,
                                          Ci.nsIObserver]),
 
   // nsIDOMGlobalPropertyInitializer implementation
   init: function(aWindow) {
-    let principal = aWindow.document.nodePrincipal;
-    let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
-
-    let perm = principal == secMan.getSystemPrincipal()
-                 ? Ci.nsIPermissionManager.ALLOW_ACTION
-                 : Services.perms.testExactPermissionFromPrincipal(principal, "wifi-manage");
-
-    // Only pages with perm set can use the wifi manager.
-    this._hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
-
-    if (!this._hasPrivileges) {
-      return null;
-    }
-
     // Maintain this state for synchronous APIs.
     this._currentNetwork = null;
     this._connectionStatus = "disconnected";
     this._enabled = false;
     this._lastConnectionInfo = null;
 
     const messages = ["WifiManager:getNetworks:Return:OK", "WifiManager:getNetworks:Return:NO",
                       "WifiManager:getKnownNetworks:Return:OK", "WifiManager:getKnownNetworks:Return:NO",
@@ -96,37 +103,64 @@ DOMWifiManager.prototype = {
                       "WifiManager:onwpstimeout", "WifiManager:onwpsfail",
                       "WifiManager:onwpsoverlap", "WifiManager:connectionInfoUpdate",
                       "WifiManager:onconnectingfailed"];
     this.initDOMRequestHelper(aWindow, messages);
     this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
 
     var state = this._mm.sendSyncMessage("WifiManager:getState")[0];
     if (state) {
-      this._currentNetwork = state.network;
-      if (this._currentNetwork)
-        exposeCurrentNetwork(this._currentNetwork);
-      this._lastConnectionInfo = state.connectionInfo;
+      this._currentNetwork = this._convertWifiNetwork(state.network);
+      this._lastConnectionInfo = this._convertConnectionInfo(state.connectionInfo);
       this._enabled = state.enabled;
       this._connectionStatus = state.status;
       this._macAddress = state.macAddress;
     } else {
       this._currentNetwork = null;
       this._lastConnectionInfo = null;
       this._enabled = false;
       this._connectionStatus = "disconnected";
       this._macAddress = "";
     }
   },
 
-  uninit: function() {
-    this._onStatusChange = null;
-    this._onConnectionInfoUpdate = null;
-    this._onEnabled = null;
-    this._onDisabled = null;
+  _convertWifiNetworkToJSON: function(aNetwork) {
+    let json = {};
+
+    for (let key in aNetwork) {
+      // In WifiWorker.js there are lots of check using "key in network".
+      // So if the value of any property of WifiNetwork is undefined, do not clone it.
+      if (aNetwork[key] != undefined) {
+        json[key] = aNetwork[key];
+      }
+    }
+    return json;
+  },
+
+  _convertWifiNetwork: function(aNetwork) {
+    let network = aNetwork ? new this._window.MozWifiNetwork(aNetwork) : null;
+    return network;
+  },
+
+  _convertWifiNetworks: function(aNetworks) {
+    let networks = [];
+    for (let i in aNetworks) {
+      networks.push(this._convertWifiNetwork(aNetworks[i]));
+    }
+    return networks;
+  },
+
+  _convertConnection: function(aConn) {
+    let conn = aConn ? new MozWifiConnection(aConn) : null;
+    return conn;
+  },
+
+  _convertConnectionInfo: function(aInfo) {
+    let info = aInfo ? new MozWifiConnectionInfo(aInfo) : null;
+    return info;
   },
 
   _sendMessageForRequest: function(name, data, request) {
     let id = this.getRequestId(request);
     this._mm.sendAsyncMessage(name, { data: data, rid: id, mid: this._id });
   },
 
   receiveMessage: function(aMessage) {
@@ -139,25 +173,25 @@ DOMWifiManager.prototype = {
       request = this.takeRequest(msg.rid);
       if (!request) {
         return;
       }
     }
 
     switch (aMessage.name) {
       case "WifiManager:getNetworks:Return:OK":
-        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        Services.DOMRequest.fireSuccess(request, this._convertWifiNetworks(msg.data));
         break;
 
       case "WifiManager:getNetworks:Return:NO":
         Services.DOMRequest.fireError(request, "Unable to scan for networks");
         break;
 
       case "WifiManager:getKnownNetworks:Return:OK":
-        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        Services.DOMRequest.fireSuccess(request, this._convertWifiNetworks(msg.data));
         break;
 
       case "WifiManager:getKnownNetworks:Return:NO":
         Services.DOMRequest.fireError(request, "Unable to get known networks");
         break;
 
       case "WifiManager:associate:Return:OK":
         Services.DOMRequest.fireSuccess(request, true);
@@ -171,41 +205,41 @@ DOMWifiManager.prototype = {
         Services.DOMRequest.fireSuccess(request, true);
         break;
 
       case "WifiManager:forget:Return:NO":
         Services.DOMRequest.fireError(request, msg.data);
         break;
 
       case "WifiManager:wps:Return:OK":
-        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        Services.DOMRequest.fireSuccess(request, msg.data);
         break;
 
       case "WifiManager:wps:Return:NO":
         Services.DOMRequest.fireError(request, msg.data);
         break;
 
       case "WifiManager:setPowerSavingMode:Return:OK":
-        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        Services.DOMRequest.fireSuccess(request, msg.data);
         break;
 
       case "WifiManager:setPowerSavingMode:Return:NO":
         Services.DOMRequest.fireError(request, msg.data);
         break;
 
       case "WifiManager:setHttpProxy:Return:OK":
-        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        Services.DOMRequest.fireSuccess(request, msg.data);
         break;
 
       case "WifiManager:setHttpProxy:Return:NO":
         Services.DOMRequest.fireError(request, msg.data);
         break;
 
       case "WifiManager:setStaticIpMode:Return:OK":
-        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        Services.DOMRequest.fireSuccess(request, msg.data);
         break;
 
       case "WifiManager:setStaticIpMode:Return:NO":
         Services.DOMRequest.fireError(request, msg.data);
         break;
 
       case "WifiManager:wifiDown":
         this._enabled = false;
@@ -215,32 +249,29 @@ DOMWifiManager.prototype = {
 
       case "WifiManager:wifiUp":
         this._enabled = true;
         this._macAddress = msg.macAddress;
         this._fireEnabledOrDisabled(true);
         break;
 
       case "WifiManager:onconnecting":
-        this._currentNetwork = msg.network;
-        exposeCurrentNetwork(this._currentNetwork);
+        this._currentNetwork = this._convertWifiNetwork(msg.network);
         this._connectionStatus = "connecting";
         this._fireStatusChangeEvent();
         break;
 
       case "WifiManager:onassociate":
-        this._currentNetwork = msg.network;
-        exposeCurrentNetwork(this._currentNetwork);
+        this._currentNetwork = this._convertWifiNetwork(msg.network);
         this._connectionStatus = "associated";
         this._fireStatusChangeEvent();
         break;
 
       case "WifiManager:onconnect":
-        this._currentNetwork = msg.network;
-        exposeCurrentNetwork(this._currentNetwork);
+        this._currentNetwork = this._convertWifiNetwork(msg.network);
         this._connectionStatus = "connected";
         this._fireStatusChangeEvent();
         break;
 
       case "WifiManager:ondisconnect":
         this._currentNetwork = null;
         this._connectionStatus = "disconnected";
         this._lastConnectionInfo = null;
@@ -264,179 +295,138 @@ DOMWifiManager.prototype = {
       case "WifiManager:onwpsoverlap":
         this._currentNetwork = null;
         this._connectionStatus = "wps-overlapped";
         this._lastConnectionInfo = null;
         this._fireStatusChangeEvent();
         break;
 
       case "WifiManager:connectionInfoUpdate":
-        this._lastConnectionInfo = msg;
+        this._lastConnectionInfo = this._convertConnectionInfo(msg);
         this._fireConnectionInfoUpdate(msg);
         break;
       case "WifiManager:onconnectingfailed":
         this._currentNetwork = null;
         this._connectionStatus = "connectingfailed";
         this._lastConnectionInfo = null;
         this._fireStatusChangeEvent();
         break;
     }
   },
 
   _fireStatusChangeEvent: function StatusChangeEvent() {
-    if (this._onStatusChange) {
-      debug("StatusChangeEvent");
-      var event = new this._window.MozWifiStatusChangeEvent("statusChangeEvent",
-                                                            { network: this._currentNetwork,
-                                                              status: this._connectionStatus
-                                                            });
-      this._onStatusChange.handleEvent(event);
-    }
+    var event = new this._window.MozWifiStatusChangeEvent("statuschange",
+                                                          { network: this._currentNetwork,
+                                                            status: this._connectionStatus
+                                                          });
+    this.__DOM_IMPL__.dispatchEvent(event);
   },
 
-  _fireConnectionInfoUpdate: function connectionInfoUpdate(info) {
-    if (this._onConnectionInfoUpdate) {
-      debug("ConnectionInfoEvent");
-      var evt = new this._window.MozWifiConnectionInfoEvent("connectionInfoEvent",
-                                                            { network: this._currentNetwork,
-                                                              signalStrength: info.signalStrength,
-                                                              relSignalStrength: info.relSignalStrength,
-                                                              linkSpeed: info.linkSpeed,
-                                                              ipAddress: info.ipAddress,
-                                                            });
-      this._onConnectionInfoUpdate.handleEvent(evt);
-    }
+  _fireConnectionInfoUpdate: function onConnectionInfoUpdate(info) {
+    var evt = new this._window.MozWifiConnectionInfoEvent("connectioninfoupdate",
+                                                          { network: this._currentNetwork,
+                                                            signalStrength: info.signalStrength,
+                                                            relSignalStrength: info.relSignalStrength,
+                                                            linkSpeed: info.linkSpeed,
+                                                            ipAddress: info.ipAddress,
+                                                          });
+    this.__DOM_IMPL__.dispatchEvent(evt);
   },
 
   _fireEnabledOrDisabled: function enabledDisabled(enabled) {
-    var handler = enabled ? this._onEnabled : this._onDisabled;
-    if (handler) {
-      var evt = new this._window.Event("WifiEnabled");
-      handler.handleEvent(evt);
-    }
+    var evt = new this._window.Event(enabled ? "enabled" : "disabled");
+    this.__DOM_IMPL__.dispatchEvent(evt);
   },
 
-  // nsIDOMWifiManager
-  getNetworks: function nsIDOMWifiManager_getNetworks() {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  getNetworks: function getNetworks() {
     var request = this.createRequest();
     this._sendMessageForRequest("WifiManager:getNetworks", null, request);
     return request;
   },
 
-  getKnownNetworks: function nsIDOMWifiManager_getKnownNetworks() {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  getKnownNetworks: function getKnownNetworks() {
     var request = this.createRequest();
     this._sendMessageForRequest("WifiManager:getKnownNetworks", null, request);
     return request;
   },
 
-  associate: function nsIDOMWifiManager_associate(network) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  associate: function associate(network) {
     var request = this.createRequest();
-    this._sendMessageForRequest("WifiManager:associate", network, request);
+    this._sendMessageForRequest("WifiManager:associate",
+                                this._convertWifiNetworkToJSON(network), request);
     return request;
   },
 
-  forget: function nsIDOMWifiManager_forget(network) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  forget: function forget(network) {
     var request = this.createRequest();
-    this._sendMessageForRequest("WifiManager:forget", network, request);
+    this._sendMessageForRequest("WifiManager:forget",
+                                this._convertWifiNetworkToJSON(network), request);
     return request;
   },
 
-  wps: function nsIDOMWifiManager_wps(detail) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  wps: function wps(detail) {
     var request = this.createRequest();
     this._sendMessageForRequest("WifiManager:wps", detail, request);
     return request;
   },
 
-  setPowerSavingMode: function nsIDOMWifiManager_setPowerSavingMode(enabled) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  setPowerSavingMode: function setPowerSavingMode(enabled) {
     var request = this.createRequest();
     this._sendMessageForRequest("WifiManager:setPowerSavingMode", enabled, request);
     return request;
   },
 
-  setHttpProxy: function nsIDOMWifiManager_setHttpProxy(network, info) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  setHttpProxy: function setHttpProxy(network, info) {
     var request = this.createRequest();
-    this._sendMessageForRequest("WifiManager:setHttpProxy", {network:network, info:info}, request);
+    this._sendMessageForRequest("WifiManager:setHttpProxy",
+                                { network: this._convertWifiNetworkToJSON(network), info:info}, request);
     return request;
   },
 
-  setStaticIpMode: function nsIDOMWifiManager_setStaticIpMode(network, info) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  setStaticIpMode: function setStaticIpMode(network, info) {
     var request = this.createRequest();
-    this._sendMessageForRequest("WifiManager:setStaticIpMode", {network: network,info: info}, request);
+    this._sendMessageForRequest("WifiManager:setStaticIpMode",
+                                { network: this._convertWifiNetworkToJSON(network), info: info}, request);
     return request;
   },
 
   get enabled() {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     return this._enabled;
   },
 
   get macAddress() {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     return this._macAddress;
   },
 
   get connection() {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
-    return exposeReadOnly({ status: this._connectionStatus,
-                            network: this._currentNetwork });
+    let _connection = this._convertConnection({ status: this._connectionStatus,
+                                                network: this._currentNetwork,
+                                              });
+    return _connection;
   },
 
   get connectionInformation() {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
-    return this._lastConnectionInfo
-           ? exposeReadOnly(this._lastConnectionInfo)
-           : null;
-  },
-
-  set onstatuschange(callback) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
-    this._onStatusChange = callback;
+    return this._lastConnectionInfo;
   },
 
-  set connectionInfoUpdate(callback) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
-    this._onConnectionInfoUpdate = callback;
+  defineEventHandlerGetterSetter: function(name) {
+    Object.defineProperty(this, name, {
+      get: function() {
+        return this.__DOM_IMPL__.getEventHandler(name);
+      },
+      set: function(handler) {
+        this.__DOM_IMPL__.setEventHandler(name, handler);
+      }
+    });
   },
-
-  set onenabled(callback) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
-    this._onEnabled = callback;
-  },
-
-  set ondisabled(callback) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
-    this._onDisabled = callback;
-  }
 };
 
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DOMWifiManager]);
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([
+  DOMWifiManager, MozWifiNetwork, MozWifiConnection, MozWifiConnectionInfo
+]);
 
 let debug;
 if (DEBUG) {
   debug = function (s) {
     dump("-*- DOMWifiManager component: " + s + "\n");
   };
 } else {
   debug = function (s) {};
--- a/dom/wifi/DOMWifiManager.manifest
+++ b/dom/wifi/DOMWifiManager.manifest
@@ -1,4 +1,12 @@
 # DOMWifiManager.js
-component {2cf775a7-1837-410c-9e26-323c42e076da} DOMWifiManager.js
-contract @mozilla.org/wifimanager;1 {2cf775a7-1837-410c-9e26-323c42e076da}
-category JavaScript-navigator-property mozWifiManager @mozilla.org/wifimanager;1
+component {c9b5f09e-25d2-40ca-aef4-c4d13d93c706} DOMWifiManager.js
+contract @mozilla.org/wifimanager;1 {c9b5f09e-25d2-40ca-aef4-c4d13d93c706}
+
+component {c01fd751-43c0-460a-8b64-abf652ec7220} DOMWifiManager.js
+contract @mozilla.org/mozwifinetwork;1 {c01fd751-43c0-460a-8b64-abf652ec7220}
+
+component {23579da4-201b-4319-bd42-9b7f337343ac} DOMWifiManager.js
+contract @mozilla.org/mozwificonnection;1 {23579da4-201b-4319-bd42-9b7f337343ac}
+
+component {83670352-6ed4-4c35-8de9-402296a1959c} DOMWifiManager.js
+contract @mozilla.org/mozwificonnectioninfo;1 {83670352-6ed4-4c35-8de9-402296a1959c}
--- a/dom/wifi/nsIWifi.idl
+++ b/dom/wifi/nsIWifi.idl
@@ -53,168 +53,8 @@ interface nsIWifi : nsISupports
      * Returns the list of currently available networks as well as the list of
      * currently configured networks.
      *
      * On success a callback is notified with the list of networks.
      * On failure after 3 scan retry attempts a callback is notified of failure.
      */
     void getWifiScanResults(in nsIWifiScanResultsReady callback);
 };
-
-[scriptable, uuid(e5a72295-1c5f-4848-9cbb-f1d3785c16c1)]
-interface nsIDOMWifiManager : nsISupports
-{
-    /**
-     * Returns the list of currently available networks.
-     * onsuccess: We have obtained the current list of networks. request.value
-     *            is an object whose property names are SSIDs and values are
-     *            network objects.
-     * onerror: We were unable to obtain a list of property names.
-     */
-    nsIDOMDOMRequest getNetworks();
-
-    /**
-     * Returns the list of networks known to the system that will be
-     * automatically connected to if they're in range.
-     * onsuccess: request.value is an object whose property names are
-     *            SSIDs and values are network objects.
-     * onerror: We were unable to obtain a list of known networks.
-     */
-    nsIDOMDOMRequest getKnownNetworks();
-
-    /**
-     * Takes one of the networks returned from getNetworks and tries to
-     * connect to it.
-     * @param network A network object with information about the network,
-     *                such as the SSID, key management desired, etc.
-     * onsuccess: We have started attempting to associate with the network.
-     *            request.value is true.
-     * onerror: We were unable to select the network. This most likely means a
-     *          configuration error.
-     */
-    nsIDOMDOMRequest associate(in jsval network);
-
-    /**
-     * Given a network, removes it from the list of networks that we'll
-     * automatically connect to. In order to re-connect to the network, it is
-     * necessary to call associate on it.
-     * @param network A network object with the SSID of the network to remove.
-     * onsuccess: We have removed this network. If we were previously
-     *            connected to it, we have started reconnecting to the next
-     *            network in the list.
-     * onerror: We were unable to remove the network.
-     */
-    nsIDOMDOMRequest forget(in jsval network);
-
-    /**
-     * Wi-Fi Protected Setup functionality.
-     * @param detail WPS detail which has 'method' and 'pin' field.
-     *               The possible method field values are:
-     *                 - pbc: The Push Button Configuration.
-     *                 - pin: The PIN configuration.
-     *                 - cancel: Request to cancel WPS in progress.
-     *               If method field is 'pin', 'pin' field can exist and has
-     *               a PIN number.
-     *               If method field is 'pin', 'bssid' field can exist and has
-     *               a opposite BSSID.
-     * onsuccess: We have successfully started/canceled wps.
-     * onerror: We have failed to start/cancel wps.
-     */
-    nsIDOMDOMRequest wps(in jsval detail);
-
-    /**
-     * Turn on/off wifi power saving mode.
-     * @param enabled true or false.
-     * onsuccess: We have successfully turn on/off wifi power saving mode.
-     * onerror: We have failed to turn on/off wifi power saving mode.
-     */
-    nsIDOMDOMRequest setPowerSavingMode(in boolean enabled);
-
-    /**
-     * Given a network, configure using static IP instead of running DHCP
-     * @param network A network object with the SSID of the network to set static ip.
-     * @param info info should have following field:
-     *        - enabled True to enable static IP, false to use DHCP
-     *        - ipaddr configured static IP address
-     *        - proxy configured proxy server address
-     *        - maskLength configured mask length
-     *        - gateway configured gateway address
-     *        - dns1 configured first DNS server address
-     *        - dns2 configured seconf DNS server address
-     * onsuccess: We have successfully configure the static ip mode.
-     * onerror: We have failed to configure the static ip mode.
-     */
-    nsIDOMDOMRequest setStaticIpMode(in jsval network,
-                                     in jsval info);
-
-    /**
-     * Given a network, configure http proxy when using wifi.
-     * @param network A network object with the SSID of the network to set http proxy.
-     * @param info info should have following field:
-     *        - httpProxyHost ip address of http proxy.
-     *        - httpProxyPort port of http proxy, set 0 to use default port 8080.
-     *        set info to null to clear http proxy.
-     * onsuccess: We have successfully configure http proxy.
-     * onerror: We have failed to configure http proxy.
-     */
-    nsIDOMDOMRequest setHttpProxy(in jsval network,
-                                  in jsval info);
-
-    /**
-     * Returns whether or not wifi is currently enabled.
-     */
-    readonly attribute boolean enabled;
-
-    /**
-     * Returns the MAC address of the wifi adapter.
-     */
-    readonly attribute DOMString macAddress;
-
-    /**
-     * An non-null object containing the following information:
-     *  - status ("disconnected", "connecting", "associated", "connected")
-     *  - network
-     *
-     *  Note that the object returned is read only. Any changes required must
-     *  be done by calling other APIs.
-     */
-    readonly attribute jsval connection;
-
-    /**
-     * A connectionInformation object with the same information found in an
-     * nsIDOMMozWifiConnectionInfoEvent (but without the network).
-     * If we are not currently connected to a network, this will be null.
-     */
-    readonly attribute jsval connectionInformation;
-
-    /**
-     * State notification listeners. These all take an
-     * nsIDOMMozWifiStatusChangeEvent with the new status and a network (which
-     * may be null).
-     *
-     * The possible statuses are:
-     *   - connecting: Fires when we start the process of connecting to a
-     *                 network.
-     *   - associated: Fires when we have connected to an access point but do
-     *                 not yet have an IP address.
-     *   - connected: Fires once we are fully connected to an access point and
-     *                can access the internet.
-     *   - disconnected: Fires when we either fail to connect to an access
-     *                   point (transition: associated -> disconnected) or
-     *                   when we were connected to a network but have
-     *                   disconnected for any reason (transition: connected ->
-     *                   disconnected).
-     */
-    attribute nsIDOMEventListener onstatuschange;
-
-    /**
-     * An event listener that is called with information about the signal
-     * strength and link speed every 5 seconds.
-     */
-    attribute nsIDOMEventListener connectionInfoUpdate;
-
-    /**
-     * These two events fire when the wifi system is brought online or taken
-     * offline.
-     */
-    attribute nsIDOMEventListener onenabled;
-    attribute nsIDOMEventListener ondisabled;
-};
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -873,16 +873,18 @@ SetProcessPriority(int aPid,
 
 // From HalTypes.h.
 const char*
 ProcessPriorityToString(ProcessPriority aPriority)
 {
   switch (aPriority) {
   case PROCESS_PRIORITY_MASTER:
     return "MASTER";
+  case PROCESS_PRIORITY_PREALLOC:
+    return "PREALLOC";
   case PROCESS_PRIORITY_FOREGROUND_HIGH:
     return "FOREGROUND_HIGH";
   case PROCESS_PRIORITY_FOREGROUND:
     return "FOREGROUND";
   case PROCESS_PRIORITY_FOREGROUND_KEYBOARD:
     return "FOREGROUND_KEYBOARD";
   case PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE:
     return "BACKGROUND_PERCEIVABLE";
@@ -911,16 +913,23 @@ ProcessPriorityToString(ProcessPriority 
   switch (aPriority) {
   case PROCESS_PRIORITY_MASTER:
     if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
       return "MASTER:CPU_NORMAL";
     }
     if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
       return "MASTER:CPU_LOW";
     }
+  case PROCESS_PRIORITY_PREALLOC:
+    if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
+      return "PREALLOC:CPU_NORMAL";
+    }
+    if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
+      return "PREALLOC:CPU_LOW";
+    }
   case PROCESS_PRIORITY_FOREGROUND_HIGH:
     if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
       return "FOREGROUND_HIGH:CPU_NORMAL";
     }
     if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
       return "FOREGROUND_HIGH:CPU_LOW";
     }
   case PROCESS_PRIORITY_FOREGROUND:
--- a/hal/HalTypes.h
+++ b/hal/HalTypes.h
@@ -79,16 +79,19 @@ typedef Observer<SwitchEvent> SwitchObse
 // Note that we rely on the order of this enum's entries.  Higher priorities
 // should have larger int values.
 enum ProcessPriority {
   PROCESS_PRIORITY_UNKNOWN = -1,
   PROCESS_PRIORITY_BACKGROUND,
   PROCESS_PRIORITY_BACKGROUND_HOMESCREEN,
   PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE,
   PROCESS_PRIORITY_FOREGROUND_KEYBOARD,
+  // The special class for the preallocated process, high memory priority but
+  // low CPU priority.
+  PROCESS_PRIORITY_PREALLOC,
   // Any priority greater than or equal to FOREGROUND is considered
   // "foreground" for the purposes of priority testing, for example
   // CurrentProcessIsForeground().
   PROCESS_PRIORITY_FOREGROUND,
   PROCESS_PRIORITY_FOREGROUND_HIGH,
   PROCESS_PRIORITY_MASTER,
   NUM_PROCESS_PRIORITY
 };
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -1251,16 +1251,19 @@ EnsureKernelLowMemKillerParamsSet()
       MOZ_CRASH();
     }
 
     int32_t killUnderKB;
     if (!NS_SUCCEEDED(Preferences::GetInt(
           nsPrintfCString("hal.processPriorityManager.gonk.%s.KillUnderKB",
                           ProcessPriorityToString(priority)).get(),
           &killUnderKB))) {
+      // ProcessPriority values like PROCESS_PRIORITY_FOREGROUND_KEYBOARD,
+      // which has only OomScoreAdjust but lacks KillUnderMB value, will not
+      // create new LMK parameters.
       continue;
     }
 
     // The LMK in kernel silently malfunctions if we assign the parameters
     // in non-increasing order, so we add this assertion here. See bug 887192.
     MOZ_ASSERT(oomScoreAdj > lowerBoundOfNextOomScoreAdj);
     MOZ_ASSERT(killUnderKB > lowerBoundOfNextKillUnderKB);
 
--- a/media/mtransport/gonk_addrs.cpp
+++ b/media/mtransport/gonk_addrs.cpp
@@ -36,17 +36,19 @@ GetInterfaces(std::vector<NetworkInterfa
   // Obtain network interfaces from network manager.
   nsresult rv;
   nsCOMPtr<nsINetworkInterfaceListService> listService =
     do_GetService("@mozilla.org/network/interface-list-service;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   int32_t flags =
     nsINetworkInterfaceListService::LIST_NOT_INCLUDE_SUPL_INTERFACES |
-    nsINetworkInterfaceListService::LIST_NOT_INCLUDE_MMS_INTERFACES;
+    nsINetworkInterfaceListService::LIST_NOT_INCLUDE_MMS_INTERFACES |
+    nsINetworkInterfaceListService::LIST_NOT_INCLUDE_IMS_INTERFACES |
+    nsINetworkInterfaceListService::LIST_NOT_INCLUDE_DUN_INTERFACES;
   nsCOMPtr<nsINetworkInterfaceList> networkList;
   NS_ENSURE_SUCCESS(listService->GetDataInterfaceList(flags,
                                                       getter_AddRefs(networkList)),
                     NS_ERROR_FAILURE);
 
   // Translate nsINetworkInterfaceList to NetworkInterface.
   int32_t listLength;
   NS_ENSURE_SUCCESS(networkList->GetNumberOfInterface(&listLength),
--- a/netwerk/mime/nsMimeTypes.h
+++ b/netwerk/mime/nsMimeTypes.h
@@ -74,16 +74,17 @@
 
 #define AUDIO_BASIC                         "audio/basic"
 #define AUDIO_OGG                           "audio/ogg"
 #define AUDIO_WAV                           "audio/x-wav"
 #define AUDIO_WEBM                          "audio/webm"
 #define AUDIO_MP3                           "audio/mpeg"
 #define AUDIO_MP4                           "audio/mp4"
 #define AUDIO_AMR                           "audio/amr"
+#define AUDIO_3GPP                          "audio/3gpp"
 #define AUDIO_MIDI                          "audio/x-midi"
 
 #define BINARY_OCTET_STREAM                 "binary/octet-stream"
 
 #define IMAGE_GIF                           "image/gif"
 #define IMAGE_JPEG                          "image/jpeg"
 #define IMAGE_JPG                           "image/jpg"
 #define IMAGE_PJPEG                         "image/pjpeg"
--- a/testing/marionette/client/marionette/emulator.py
+++ b/testing/marionette/client/marionette/emulator.py
@@ -220,16 +220,20 @@ class Emulator(object):
                 raise Exception('bad telnet response: %s' % line)
 
     def _run_telnet(self, command):
         if not self.telnet:
             self.telnet = Telnet('localhost', self.port)
             self._get_telnet_response()
         return self._get_telnet_response(command)
 
+    def _run_shell(self, args):
+        args.insert(0, 'shell')
+        return self._run_adb(args).split('\r\n')
+
     def close(self):
         if self.is_running and self._emulator_launched:
             self.proc.kill()
         if self._adb_started:
             self._run_adb(['kill-server'])
             self._adb_started = False
         if self.proc:
             retcode = self.proc.poll()
--- a/testing/marionette/client/marionette/marionette.py
+++ b/testing/marionette/client/marionette/marionette.py
@@ -603,34 +603,52 @@ class Marionette(object):
             self.session = None
             self.window = None
             self.client.close()
             raise TimeoutException(
                 "Connection timed out", status=ErrorCodes.TIMEOUT)
 
         # Process any emulator commands that are sent from a script
         # while it's executing.
-        while response.get("emulator_cmd"):
-            response = self._handle_emulator_cmd(response)
+        while True:
+            if response.get("emulator_cmd"):
+                response = self._handle_emulator_cmd(response)
+                continue;
+
+            if response.get("emulator_shell"):
+                response = self._handle_emulator_shell(response)
+                continue;
+
+            break;
 
         if response_key in response:
             return response[response_key]
         self._handle_error(response)
 
     def _handle_emulator_cmd(self, response):
         cmd = response.get("emulator_cmd")
         if not cmd or not self.emulator:
             raise MarionetteException(
                 "No emulator in this test to run command against")
         cmd = cmd.encode("ascii")
         result = self.emulator._run_telnet(cmd)
         return self.client.send({"name": "emulatorCmdResult",
                                  "id": response.get("id"),
                                  "result": result})
 
+    def _handle_emulator_shell(self, response):
+        args = response.get("emulator_shell")
+        if not isinstance(args, list) or not self.emulator:
+            raise MarionetteException(
+                "No emulator in this test to run shell command against")
+        result = self.emulator._run_shell(args)
+        return self.client.send({"name": "emulatorCmdResult",
+                                 "id": response.get("id"),
+                                 "result": result})
+
     def _handle_error(self, response):
         if 'error' in response and isinstance(response['error'], dict):
             status = response['error'].get('status', 500)
             message = response['error'].get('message')
             stacktrace = response['error'].get('stacktrace')
             # status numbers come from
             # http://code.google.com/p/selenium/wiki/JsonWireProtocol#Response_Status_Codes
             if status == ErrorCodes.NO_SUCH_ELEMENT:
--- a/testing/marionette/client/marionette/tests/unit/test_emulator.py
+++ b/testing/marionette/client/marionette/tests/unit/test_emulator.py
@@ -12,16 +12,24 @@ class TestEmulatorContent(MarionetteTest
         self.marionette.set_script_timeout(10000)
         expected = ["<build>",
                     "OK"]
         result = self.marionette.execute_async_script("""
         runEmulatorCmd("avd name", marionetteScriptFinished)
         """);
         self.assertEqual(result, expected)
 
+    def test_emulator_shell(self):
+        self.marionette.set_script_timeout(10000)
+        expected = ["Hello World!", ""]
+        result = self.marionette.execute_async_script("""
+        runEmulatorShell(["echo", "Hello World!"], marionetteScriptFinished)
+        """);
+        self.assertEqual(result, expected)
+
     def test_emulator_order(self):
         self.marionette.set_script_timeout(10000)
         self.assertRaises(MarionetteException,
                           self.marionette.execute_async_script,
         """runEmulatorCmd("gsm status", function(result) {});
            marionetteScriptFinished(true);
         """);
 
--- a/testing/marionette/marionette-frame-manager.js
+++ b/testing/marionette/marionette-frame-manager.js
@@ -158,16 +158,17 @@ FrameManager.prototype = {
   addMessageManagerListeners: function MDA_addMessageManagerListeners(messageManager) {
     messageManager.addWeakMessageListener("Marionette:ok", this.server);
     messageManager.addWeakMessageListener("Marionette:done", this.server);
     messageManager.addWeakMessageListener("Marionette:error", this.server);
     messageManager.addWeakMessageListener("Marionette:log", this.server);
     messageManager.addWeakMessageListener("Marionette:shareData", this.server);
     messageManager.addWeakMessageListener("Marionette:register", this.server);
     messageManager.addWeakMessageListener("Marionette:runEmulatorCmd", this.server);
+    messageManager.addWeakMessageListener("Marionette:runEmulatorShell", this.server);
     messageManager.addWeakMessageListener("Marionette:switchToModalOrigin", this.server);
     messageManager.addWeakMessageListener("Marionette:switchToFrame", this.server);
     messageManager.addWeakMessageListener("Marionette:switchedToFrame", this.server);
     messageManager.addWeakMessageListener("MarionetteFrame:handleModal", this);
     messageManager.addWeakMessageListener("MarionetteFrame:getInterruptedState", this);
   },
 
   /**
@@ -185,14 +186,15 @@ FrameManager.prototype = {
   removeMessageManagerListeners: function MDA_removeMessageManagerListeners(messageManager) {
     messageManager.removeWeakMessageListener("Marionette:ok", this.server);
     messageManager.removeWeakMessageListener("Marionette:done", this.server);
     messageManager.removeWeakMessageListener("Marionette:error", this.server);
     messageManager.removeWeakMessageListener("Marionette:log", this.server);
     messageManager.removeWeakMessageListener("Marionette:shareData", this.server);
     messageManager.removeWeakMessageListener("Marionette:register", this.server);
     messageManager.removeWeakMessageListener("Marionette:runEmulatorCmd", this.server);
+    messageManager.removeWeakMessageListener("Marionette:runEmulatorShell", this.server);
     messageManager.removeWeakMessageListener("Marionette:switchToFrame", this.server);
     messageManager.removeWeakMessageListener("Marionette:switchedToFrame", this.server);
     messageManager.removeWeakMessageListener("MarionetteFrame:handleModal", this);
   },
 
 };
--- a/testing/marionette/marionette-listener.js
+++ b/testing/marionette/marionette-listener.js
@@ -2014,16 +2014,24 @@ let _emu_cbs = {};
 function runEmulatorCmd(cmd, callback) {
   if (callback) {
     _emu_cbs[_emu_cb_id] = callback;
   }
   sendAsyncMessage("Marionette:runEmulatorCmd", {emulator_cmd: cmd, id: _emu_cb_id});
   _emu_cb_id += 1;
 }
 
+function runEmulatorShell(args, callback) {
+  if (callback) {
+    _emu_cbs[_emu_cb_id] = callback;
+  }
+  sendAsyncMessage("Marionette:runEmulatorShell", {emulator_shell: args, id: _emu_cb_id});
+  _emu_cb_id += 1;
+}
+
 function emulatorCmdResult(msg) {
   let message = msg.json;
   if (!sandbox) {
     return;
   }
   let cb = _emu_cbs[message.id];
   delete _emu_cbs[message.id];
   if (!cb) {
--- a/testing/marionette/marionette-server.js
+++ b/testing/marionette/marionette-server.js
@@ -2123,16 +2123,27 @@ MarionetteServerConnection.prototype = {
         this._emu_cbs = {};
       }
       this._emu_cbs[this._emu_cb_id] = callback;
     }
     this.sendToClient({emulator_cmd: cmd, id: this._emu_cb_id}, -1);
     this._emu_cb_id += 1;
   },
 
+  runEmulatorShell: function runEmulatorShell(args, callback) {
+    if (callback) {
+      if (!this._emu_cbs) {
+        this._emu_cbs = {};
+      }
+      this._emu_cbs[this._emu_cb_id] = callback;
+    }
+    this.sendToClient({emulator_shell: args, id: this._emu_cb_id}, -1);
+    this._emu_cb_id += 1;
+  },
+
   emulatorCmdResult: function emulatorCmdResult(message) {
     if (this.context != "chrome") {
       this.sendAsync("emulatorCmdResult", message, -1);
       return;
     }
 
     if (!this._emu_cbs) {
       return;
@@ -2320,16 +2331,17 @@ MarionetteServerConnection.prototype = {
         break;
       case "Marionette:shareData":
         //log messages from tests
         if (message.json.log) {
           this.marionetteLog.addLogs(message.json.log);
         }
         break;
       case "Marionette:runEmulatorCmd":
+      case "Marionette:runEmulatorShell":
         this.sendToClient(message.json, -1);
         break;
       case "Marionette:switchToFrame":
         this.curBrowser.frameManager.switchToFrame(message);
         this.messageManager = this.curBrowser.frameManager.currentRemoteFrame.messageManager.get();
         break;
       case "Marionette:switchToModalOrigin":
         this.curBrowser.frameManager.switchToModalOrigin(message);
--- a/testing/marionette/marionette-simpletest.js
+++ b/testing/marionette/marionette-simpletest.js
@@ -17,17 +17,17 @@ this.Marionette = function Marionette(sc
   this.testName = testName;
   this.TEST_UNEXPECTED_FAIL = "TEST-UNEXPECTED-FAIL";
   this.TEST_PASS = "TEST-PASS";
   this.TEST_KNOWN_FAIL = "TEST-KNOWN-FAIL";
 }
 
 Marionette.prototype = {
   exports: ['ok', 'is', 'isnot', 'log', 'getLogs', 'generate_results', 'waitFor',
-            'runEmulatorCmd', 'TEST_PASS', 'TEST_KNOWN_FAIL',
+            'runEmulatorCmd', 'runEmulatorShell', 'TEST_PASS', 'TEST_KNOWN_FAIL',
             'TEST_UNEXPECTED_FAIL'],
 
   ok: function Marionette__ok(condition, name, passString, failString, diag) {
     this.heartbeatCallback();
     if (typeof(diag) == "undefined") {
       diag = this.repr(condition) + " was " + !!condition + ", expected true";
     }
     let test = {'result': !!condition, 'name': name, 'diag': diag};
@@ -158,10 +158,15 @@ Marionette.prototype = {
       this.window.setTimeout(this.waitFor.bind(this), 100, callback, test, deadline - now);
   },
 
   runEmulatorCmd: function runEmulatorCmd(cmd, callback) {
     this.heartbeatCallback();
     this.scope.runEmulatorCmd(cmd, callback);
   },
 
+  runEmulatorShell: function runEmulatorShell(args, callback) {
+    this.heartbeatCallback();
+    this.scope.runEmulatorShell(args, callback);
+  },
+
 };
 
--- a/testing/mochitest/Makefile.in
+++ b/testing/mochitest/Makefile.in
@@ -39,19 +39,16 @@ SERV_FILES = 	\
 		browser-harness.xul \
 		redirect.html \
 		$(topsrcdir)/build/pgo/server-locations.txt \
 		$(topsrcdir)/netwerk/test/httpserver/httpd.js \
 		pywebsocket_wrapper.py \
 		android.json \
 		androidx86.json \
 		android23.json \
-		b2g.json \
-		b2g-desktop.json \
-		b2g-debug.json \
 		gl.json \
 		b2g_start_script.js \
 		$(NULL)	
 
 ifeq ($(MOZ_BUILD_APP),mobile/android)
 SERV_FILES += \
   $(topsrcdir)/mobile/android/base/tests/robocop.ini \
   $(topsrcdir)/mobile/android/base/tests/robocop_autophone.ini \
deleted file mode 100644
--- a/testing/mochitest/b2g-debug.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-"runtests": {
-  },
-"excludetests": {
-  }
-}
deleted file mode 100644
--- a/testing/mochitest/b2g-desktop.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-"runtests": {
-  },
-"excludetests": {
-  }
-}
deleted file mode 100644
--- a/testing/mochitest/b2g.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-"runtests": {
-  },
-"excludetests": {
-  }
-}
--- a/testing/mochitest/mach_commands.py
+++ b/testing/mochitest/mach_commands.py
@@ -138,23 +138,16 @@ class MochitestRunner(MozbuildObject):
             test_root_file = mozpack.path.join(self.mochitest_dir, 'tests', test_path)
             if not os.path.exists(test_root_file):
                 print('Specified test path does not exist: %s' % test_root_file)
                 return 1
             if os.path.isdir(test_root_file):
                 test_path_dir = True;
             options.testPath = test_path
 
-        # filter test directiories or all tests according to the manifest
-        if not test_path or test_path_dir:
-            if conditions.is_b2g_desktop(self):
-                options.testManifest = 'b2g-desktop.json'
-            else:
-                options.testManifest = 'b2g.json'
-
         for k, v in kwargs.iteritems():
             setattr(options, k, v)
         options.noWindow = no_window
         options.totalChunks = total_chunks
         options.thisChunk = this_chunk
 
         options.symbolsPath = os.path.join(self.distdir, 'crashreporter-symbols')
 
--- a/widget/gonk/HwcComposer2D.h
+++ b/widget/gonk/HwcComposer2D.h
@@ -42,16 +42,33 @@ typedef hwc_composer_device_1_t HwcDevic
 typedef hwc_display_contents_1_t HwcList;
 typedef hwc_layer_1_t HwcLayer;
 #else
 typedef hwc_composer_device_t HwcDevice;
 typedef hwc_layer_list_t HwcList;
 typedef hwc_layer_t HwcLayer;
 #endif
 
+/*
+ * HwcComposer2D provides a way for gecko to render frames
+ * using hwcomposer.h in the AOSP HAL.
+ *
+ * hwcomposer.h defines an interface for display composition
+ * using dedicated hardware. This hardware is usually faster
+ * or more power efficient than the GPU. However, in exchange
+ * for better performance, generality has to be sacrificed:
+ * no 3d transforms, no intermediate surfaces, no special shader effects,
+ * and loss of other goodies depending on the platform.
+ *
+ * In general, when hwc is enabled gecko tries to compose
+ * its frames using HwcComposer2D first. Then if HwcComposer2D is
+ * unable to compose a frame then it falls back to compose it
+ * using the GPU with OpenGL.
+ *
+ */
 class HwcComposer2D : public mozilla::layers::Composer2D {
 public:
     HwcComposer2D();
     virtual ~HwcComposer2D();
 
     int Init(hwc_display_t aDisplay, hwc_surface_t aSurface);
 
     bool Initialized() const { return mHwc; }