Merge mozilla-central to fx-team on a CLOSED TREE
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 25 Feb 2014 15:42:32 +0100
changeset 170474 5d020fa8466104695256e47f43ecd373812c3832
parent 170473 fd87c9bb872ca2d5c8b7c2baed698c2620c1ff42 (current diff)
parent 170359 1507f021ac93c1d27cfd00e389fba1c9421b3201 (diff)
child 170475 db3625395d32268f8b98d78429193c5680271c1b
push id26288
push userryanvm@gmail.com
push dateTue, 25 Feb 2014 20:20:43 +0000
treeherdermozilla-central@22650589a724 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone30.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 mozilla-central to fx-team on a CLOSED TREE
browser/app/profile/firefox.js
dom/bluetooth/bluedroid/BluetoothHfpManager.cpp
dom/bluetooth/bluedroid/BluetoothHfpManager.h
dom/bluetooth/bluedroid/gonk/BluetoothServiceBluedroid.cpp
dom/bluetooth/bluedroid/gonk/BluetoothServiceBluedroid.h
dom/bluetooth/bluez/linux/BluetoothDBusService.cpp
dom/bluetooth/bluez/linux/BluetoothDBusService.h
dom/file/DOMFileHandle.cpp
dom/file/DOMFileHandle.h
dom/file/nsIDOMFileHandle.idl
services/common/tests/unit/xpcshell.ini
toolkit/components/osfile/modules/osfile_win_front.jsm
xpcom/base/nsITraceRefcnt.idl
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,11 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-CLOBBER to test mozfile changes which previously broke mozbuild's ability to clobber (bug 949600).
-
-Safe to ignore - last clobber was 'Skia update from Bug 910754 needs a CLOBBER build' at Feb 18 15:19:59 2014 PST
+Update CLOBBER for bug 939672 moves file location and requires clobber build.
--- a/accessible/src/jsat/OutputGenerator.jsm
+++ b/accessible/src/jsat/OutputGenerator.jsm
@@ -9,16 +9,17 @@ const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 const INCLUDE_DESC = 0x01;
 const INCLUDE_NAME = 0x02;
 const INCLUDE_VALUE = 0x04;
 const INCLUDE_CUSTOM = 0x08;
 const NAME_FROM_SUBTREE_RULE = 0x10;
+const IGNORE_EXPLICIT_NAME = 0x20;
 
 const OUTPUT_DESC_FIRST = 0;
 const OUTPUT_DESC_LAST = 1;
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'PrefCache',
@@ -62,17 +63,18 @@ this.OutputGenerator = {
     };
     let ignoreSubtree = function ignoreSubtree(aAccessible) {
       let roleString = Utils.AccRetrieval.getStringRole(aAccessible.role);
       let nameRule = self.roleRuleMap[roleString] || 0;
       // Ignore subtree if the name is explicit and the role's name rule is the
       // NAME_FROM_SUBTREE_RULE.
       return (((nameRule & INCLUDE_VALUE) && aAccessible.value) ||
               ((nameRule & NAME_FROM_SUBTREE_RULE) &&
-               Utils.getAttributes(aAccessible)['explicit-name'] === 'true'));
+               (Utils.getAttributes(aAccessible)['explicit-name'] === 'true' &&
+               !(nameRule & IGNORE_EXPLICIT_NAME))));
     };
 
     let contextStart = this._getContextStart(aContext);
 
     if (this.outputOrder === OUTPUT_DESC_FIRST) {
       contextStart.forEach(addOutput);
       addOutput(aContext.accessible);
       [addOutput(node) for
@@ -152,18 +154,18 @@ this.OutputGenerator = {
    * @return {Array} The mode utterance
    */
   genForEditingMode: function genForEditingMode(aIsEditing) {},
 
   _getContextStart: function getContextStart(aContext) {},
 
   _addName: function _addName(aOutput, aAccessible, aFlags) {
     let name;
-    if (Utils.getAttributes(aAccessible)['explicit-name'] === 'true' ||
-      (aFlags & INCLUDE_NAME)) {
+    if ((Utils.getAttributes(aAccessible)['explicit-name'] === 'true' &&
+         !(aFlags & IGNORE_EXPLICIT_NAME)) || (aFlags & INCLUDE_NAME)) {
       name = aAccessible.name;
     }
 
     let description = aAccessible.description;
     if (description) {
       // Compare against the calculated name unconditionally, regardless of name rule,
       // so we can make sure we don't speak duplicated descriptions
       let tmpName = name || aAccessible.name;
@@ -314,17 +316,19 @@ this.OutputGenerator = {
     'check rich option': NAME_FROM_SUBTREE_RULE,
     'term': NAME_FROM_SUBTREE_RULE,
     'definition': NAME_FROM_SUBTREE_RULE,
     'key': NAME_FROM_SUBTREE_RULE,
     'image map': INCLUDE_DESC,
     'option': INCLUDE_DESC,
     'listbox': INCLUDE_DESC,
     'definitionlist': INCLUDE_DESC | INCLUDE_NAME,
-    'dialog': INCLUDE_DESC | INCLUDE_NAME },
+    'dialog': INCLUDE_DESC | INCLUDE_NAME,
+    'chrome window': IGNORE_EXPLICIT_NAME,
+    'app root': IGNORE_EXPLICIT_NAME },
 
   objectOutputFunctions: {
     _generateBaseOutput: function _generateBaseOutput(aAccessible, aRoleStr, aState, aFlags) {
       let output = [];
 
       if (aFlags & INCLUDE_DESC) {
         let desc = this._getLocalizedState(aState);
         let roleStr = this._getLocalizedRole(aRoleStr);
--- a/accessible/tests/mochitest/jsat/output.js
+++ b/accessible/tests/mochitest/jsat/output.js
@@ -13,23 +13,36 @@ Cu.import("resource://gre/modules/access
  *                         the |aAccOrElmOrID|.
  * @param aGenerator       the output generator to use when generating accessible
  *                         output
  *
  * Note: if |aOldAccOrElmOrID| is not provided, the |aAccOrElmOrID| must be
  * scoped to the "root" element in markup.
  */
 function testContextOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, aGenerator) {
-  aOldAccOrElmOrID = aOldAccOrElmOrID || "root";
   var accessible = getAccessible(aAccOrElmOrID);
-  var oldAccessible = getAccessible(aOldAccOrElmOrID);
+  var oldAccessible = aOldAccOrElmOrID !== null ?
+	getAccessible(aOldAccOrElmOrID || 'root') : null;
   var context = new PivotContext(accessible, oldAccessible);
   var output = aGenerator.genForContext(context).output;
 
-  isDeeply(output, expected,
+  // Create a version of the output that has null members where we have
+  // null members in the expected output. Those are indexes that are not testable
+  // because of the changing nature of the test (different window names), or strings
+  // that are inaccessible to us, like the title of parent documents.
+  var masked_output = [];
+  for (var i=0; i < output.length; i++) {
+    if (expected[i] === null) {
+      masked_output.push(null);
+    } else {
+      masked_output[i] = output[i];
+    }
+  }
+
+  isDeeply(masked_output, expected,
            "Context output is correct for " + aAccOrElmOrID +
            " (output: " + output.join(", ") + ") ==" +
            " (expected: " + expected.join(", ") + ")");
 }
 
 /**
  * Test object output generated array that includes names.
  * Note: test ignores outputs without the name.
--- a/accessible/tests/mochitest/jsat/test_explicit_names.html
+++ b/accessible/tests/mochitest/jsat/test_explicit_names.html
@@ -31,16 +31,21 @@
         expected: ["text area", "This is the text area text.", "Test Text Area"]
       }, {
         accOrElmOrID: "textarea2",
         expected: ["text area", "This is the text area text."]
       }, {
         accOrElmOrID: "heading1",
         expected: ["heading level 1", "Test heading", "This is the heading."]
       }, {
+        accOrElmOrID: "heading1",
+        oldAccOrElmOrID: null,
+        expected: [null /* parent doc title */, document.title,
+		   "heading level 1", "Test heading", "This is the heading."]
+      }, {
         accOrElmOrID: "heading2",
         expected: ["heading level 1", "This is the heading."]
       }, {
         accOrElmOrID: "list",
         expected: ["list 2 items", "Test List", "First item", "Top of the list",
           "Last item", "2.", "list two"]
       }, {
         accOrElmOrID: "dlist",
--- a/addon-sdk/source/test/test-content-script.js
+++ b/addon-sdk/source/test/test-content-script.js
@@ -585,17 +585,17 @@ exports["test valueOf"] = createProxyTes
 });
 
 exports["test XMLHttpRequest"] = createProxyTest("", function (helper) {
 
   helper.createWorker(
     'new ' + function ContentScriptScope() {
       // XMLHttpRequest doesn't support XMLHttpRequest.apply,
       // that may break our proxy code
-      assert(window.XMLHttpRequest(), "we are able to instantiate XMLHttpRequest object");
+      assert(new window.XMLHttpRequest(), "we are able to instantiate XMLHttpRequest object");
       done();
     }
   );
 
 });
 
 exports["test XPathResult"] = createProxyTest("", function (helper, assert) {
   const XPathResultTypes = ["ANY_TYPE",
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -867,16 +867,20 @@ pref("identity.fxaccounts.auth.uri", "ht
 
 // APZC preferences.
 //
 // Gaia relies heavily on scroll events for now, so lets fire them
 // more often than the default value (100).
 pref("apz.asyncscroll.throttle", 40);
 pref("apz.pan_repaint_interval", 40);
 
+// Maximum fling velocity in px/ms.  Slower devices may need to reduce this
+// to avoid checkerboarding.  Note, float value must be set as a string.
+pref("apz.max_velocity_pixels_per_ms", "6.0");
+
 // This preference allows FirefoxOS apps (and content, I think) to force
 // the use of software (instead of hardware accelerated) 2D canvases by
 // creating a context like this:
 //
 //   canvas.getContext('2d', { willReadFrequently: true })
 //
 // Using a software canvas can save memory when JS calls getImageData()
 // on the canvas frequently. See bug 884226.
--- a/b2g/components/ContentPermissionPrompt.js
+++ b/b2g/components/ContentPermissionPrompt.js
@@ -217,21 +217,30 @@ ContentPermissionPrompt.prototype = {
     let typesInfo = [];
     let perms = request.types.QueryInterface(Ci.nsIArray);
     for (let idx = 0; idx < perms.length; idx++) {
       let perm = perms.queryElementAt(idx, Ci.nsIContentPermissionType);
       let tmp = {
         permission: perm.type,
         access: (perm.access && perm.access !== "unused") ?
                   perm.type + "-" + perm.access : perm.type,
+        options: [],
         deny: true,
         action: Ci.nsIPermissionManager.UNKNOWN_ACTION
       };
+
+      // Append available options, if any.
+      let options = perm.options.QueryInterface(Ci.nsIArray);
+      for (let i = 0; i < options.length; i++) {
+        let option = options.queryElementAt(i, Ci.nsISupportsString).data;
+        tmp.options.push(option);
+      }
       typesInfo.push(tmp);
     }
+
     if (typesInfo.length == 0) {
       request.cancel();
       return;
     }
 
     if(!this.checkMultipleRequest(typesInfo)) {
       request.cancel();
       return;
@@ -304,23 +313,23 @@ ContentPermissionPrompt.prototype = {
   cancelPrompt: function(request, requestId, typesInfo) {
     this.sendToBrowserWindow("cancel-permission-prompt", request, requestId,
                              typesInfo);
   },
 
   delegatePrompt: function(request, requestId, typesInfo, callback) {
 
     this.sendToBrowserWindow("permission-prompt", request, requestId, typesInfo,
-                             function(type, remember) {
+                             function(type, remember, choices) {
       if (type == "permission-allow") {
         rememberPermission(typesInfo, request.principal, !remember);
         if (callback) {
           callback();
         }
-        request.allow();
+        request.allow(choices);
         return;
       }
 
       let addDenyPermission = function(type) {
         debug("add " + type.permission +
               " to permission manager with DENY_ACTION");
         if (remember) {
           Services.perms.addFromPrincipal(request.principal, type.access,
@@ -349,30 +358,30 @@ ContentPermissionPrompt.prototype = {
 
     if (callback) {
       content.addEventListener("mozContentEvent", function contentEvent(evt) {
         let detail = evt.detail;
         if (detail.id != requestId)
           return;
         evt.target.removeEventListener(evt.type, contentEvent);
 
-        callback(detail.type, detail.remember);
+        callback(detail.type, detail.remember, detail.choices);
       })
     }
 
     let principal = request.principal;
     let isApp = principal.appStatus != Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED;
     let remember = (principal.appStatus == Ci.nsIPrincipal.APP_STATUS_PRIVILEGED ||
                     principal.appStatus == Ci.nsIPrincipal.APP_STATUS_CERTIFIED)
                     ? true
                     : request.remember;
     let permissions = {};
     for (let i in typesInfo) {
       debug("prompt " + typesInfo[i].permission);
-      permissions[typesInfo[i].permission] = [];
+      permissions[typesInfo[i].permission] = typesInfo[i].options;
     }
 
     let details = {
       type: type,
       permissions: permissions,
       id: requestId,
       origin: principal.origin,
       isApp: isApp,
--- a/b2g/components/test/mochitest/SandboxPromptTest.html
+++ b/b2g/components/test/mochitest/SandboxPromptTest.html
@@ -1,16 +1,57 @@
 <html>
 <body>
 <script>
 
-// invoke audio-capture permission prompt
-navigator.mozGetUserMedia({audio: true}, function () {}, function () {});
+var actions = [
+  {
+    permissions: ["video-capture"],
+    action: function() {
+      // invoke video-capture permission prompt
+      navigator.mozGetUserMedia({video: true}, function () {}, function () {});
+    }
+  },
+  {
+    permissions: ["audio-capture", "video-capture"],
+    action: function() {
+      // invoke audio-capture + video-capture permission prompt
+      navigator.mozGetUserMedia({audio: true, video: true}, function () {}, function () {});
+    }
+  },
+  {
+    permissions: ["audio-capture"],
+    action: function() {
+      // invoke audio-capture permission prompt
+      navigator.mozGetUserMedia({audio: true}, function () {}, function () {});
+    }
+  },
+  {
+    permissions: ["geolocation"],
+    action: function() {
+      // invoke geolocation permission prompt
+      navigator.geolocation.getCurrentPosition(function (pos) {});
+    }
+  },
+  {
+    permissions: ["desktop-notification"],
+    action: function() {
+      // invoke desktop-notification prompt
+      Notification.requestPermission(function (perm) {});
+    }
+  },
+];
 
-// invoke geolocation permission prompt
-navigator.geolocation.getCurrentPosition(function (pos) {});
-
-// invoke desktop-notification prompt
-Notification.requestPermission(function (perm) {});
+// The requested permissions are specified in query string.
+var permissions = JSON.parse(decodeURIComponent(window.location.search.substring(1)));
+for (var i = 0; i < actions.length; i++) {
+  if(permissions.length === actions[i].permissions.length &&
+     permissions.every(function(permission) {
+                         return actions[i].permissions.indexOf(permission) >= 0;
+                       })) {
+    actions[i].action();
+    break;
+  }
+}
 
 </script>
 </body>
 </html>
--- a/b2g/components/test/mochitest/permission_handler_chrome.js
+++ b/b2g/components/test/mochitest/permission_handler_chrome.js
@@ -11,70 +11,40 @@ function debug(str) {
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 const { Services } = Cu.import("resource://gre/modules/Services.jsm");
 
 let browser = Services.wm.getMostRecentWindow("navigator:browser");
 let shell;
-let test_counts = 0;
 
 function loadShell() {
   if (!browser) {
     debug("no browser");
     return false;
   }
   shell = browser.shell;
   return true;
 }
 
 function getContentWindow() {
   return shell.contentBrowser.contentWindow;
 }
 
-function addChromeEventListener(type, listener) {
+if (loadShell()) {
   let content = getContentWindow();
-  content.addEventListener("mozChromeEvent", function chromeListener(evt) {
-    if (!evt.detail || evt.detail.type !== type) {
+  let eventHandler = function(evt) {
+    if (!evt.detail || evt.detail.type !== "permission-prompt") {
       return;
     }
 
-    let remove = listener(evt);
-    if (remove) {
-      content.removeEventListener("mozChromeEvent", chromeListener);
-    }
+    sendAsyncMessage("permission-request", evt.detail.permissions);
+  };
+
+  content.addEventListener("mozChromeEvent", eventHandler);
+
+  // need to remove ChromeEvent listener after test finished.
+  addMessageListener("teardown", function() {
+    content.removeEventListener("mozChromeEvent", eventHandler);
   });
 }
 
-function checkPromptEvent(prompt_evt) {
-  let detail = prompt_evt.detail;
-
-  if (detail.permissions) {
-    if ("audio-capture" in detail.permissions) {
-      sendAsyncMessage("permission.granted", "audio-capture");
-      test_counts--;
-    }
-    if ("desktop-notification" in detail.permissions) {
-      sendAsyncMessage("permission.granted", "desktop-notification");
-      test_counts--;
-    }
-    if ("geolocation" in detail.permissions) {
-      sendAsyncMessage("permission.granted", "geolocation");
-      test_counts--;
-    }
-  }
-
-  if (!test_counts) {
-    debug("remove prompt event listener.");
-    return true;
-  }
-
-  return false;
-}
-
-if (loadShell()) {
-  addMessageListener("test.counts", function (counts) {
-    test_counts = counts;
-  });
-
-  addChromeEventListener("permission-prompt", checkPromptEvent);
-}
--- a/b2g/components/test/mochitest/test_sandbox_permission.html
+++ b/b2g/components/test/mochitest/test_sandbox_permission.html
@@ -6,67 +6,92 @@ https://bugzilla.mozilla.org/show_bug.cg
 <head>
   <meta charset="utf-8">
   <title>Permission Prompt Test</title>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=951997">Permission prompt web content test</a>
-<script type="application/javascript">
+<script type="application/javascript;version=1.8">
 
 "use strict";
 
 const APP_URL = "SandboxPromptTest.html";
 
+var iframe;
 var gUrl = SimpleTest.getTestFileURL("permission_handler_chrome.js");
 var gScript = SpecialPowers.loadChromeScript(gUrl);
 var gResult = [
   {
-    type: "audio-capture",
-    prompt: false
+    "video-capture": ["back"],
+  },
+  {
+    "audio-capture": [""],
+    "video-capture": ["back"],
+  },
+  {
+    "audio-capture": [""],
+  },
+  {
+    "geolocation": [],
   },
   {
-    type: "geolocation",
-    prompt: false
-  },
-  {
-    type: "desktop-notification",
-    prompt: false
+    "desktop-notification": [],
   }
 ];
 
+function runNext() {
+  if (gResult.length > 0) {
+    // Put the requested permission in query string
+    let requestedPermission = JSON.stringify(Object.keys(gResult[0]));
+    info('request permissions for ' + requestedPermission);
+    iframe.src = APP_URL + '?' + encodeURIComponent(requestedPermission);
+  } else {
+    info('test finished, teardown');
+    gScript.sendAsyncMessage("teardown", "");
+    gScript.destroy();
+    SimpleTest.finish();
+  }
+}
+
 // Create a sanbox iframe.
 function loadBrowser() {
-  var iframe = document.createElement("iframe");
+  iframe = document.createElement("iframe");
   SpecialPowers.wrap(iframe).mozbrowser = true;
-  iframe.src = APP_URL;
+  iframe.src = 'about:blank';
   document.body.appendChild(iframe);
+
+  iframe.addEventListener("load", function onLoad() {
+    iframe.removeEventListener("load", onLoad);
+    runNext();
+  });
 }
 
-// send test counts to chrome script.
-gScript.sendAsyncMessage("test.counts", gResult.length);
+gScript.addMessageListener("permission-request", function (permissions) {
+  let expectedValue = gResult.shift();
+  let permissionTypes = Object.keys(permissions);
 
-gScript.addMessageListener("permission.granted", function (aName) {
-  gResult.forEach(function(aType, aIndex) {
-    if (aType.type == aName) {
-      aType.prompt = true;
+  is(permissionTypes.length, Object.keys(expectedValue).length, "expected number of permissions");
+
+  for (let type of permissionTypes) {
+    ok(expectedValue.hasOwnProperty(type), "expected permission type");
+    for (let i in permissions[type]) {
+      is(permissions[type][i], expectedValue[type][i], "expected permission option");
     }
-  });
-
-  if(gResult.every(function(aType) { return aType.prompt; })) {
-    ok(true, "Get all permission prompts");
-    gScript.destroy();
-    SimpleTest.finish();
-  }});
+  }
+  runNext();
+});
 
 // Add permissions to this app. We use ALLOW_ACTION here. The ContentPermissionPrompt
 // should prompt for permission, not allow it without prompt.
 SpecialPowers.pushPrefEnv({"set": [["media.navigator.permission.disabled", false]]},
   function() {
+    SpecialPowers.addPermission('video-capture',
+      SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION, document);
     SpecialPowers.addPermission('audio-capture',
       SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION, document);
     SpecialPowers.addPermission('geolocation',
       SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION, document);
     SpecialPowers.addPermission('desktop-notification',
       SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION, document);
     loadBrowser();
   });
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e0f39c7179c8b297326c0e2313950610be1f5c52"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="49312fb89b90eca48a8011b94a1a1a751daf32d2"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <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="022eadd5917615ff00c47eaaafa792b45e9c8a28"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
@@ -91,11 +91,11 @@
   <project name="platform/system/vold" path="system/vold" revision="919829940468066a32f403980b43f6ebfee5d314"/>
   <!-- Emulator specific things -->
   <project name="android-development" path="development" remote="b2g" revision="4e236e65a5d652a66ac32590f69f2123d17cb4ad"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="e7e8734fdd8bf41e48a56c1c85e0f7dac60aaa9f"/>
   <project name="platform/external/iproute2" path="external/iproute2" revision="c66c5716d5335e450f7a7b71ccc6a604fb2f41d2"/>
   <project name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="d2685281e2e54ca14d1df304867aa82c37b27162"/>
   <project name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="627f9b20fc518937b93747a7ff1ed4f5ed46e06f"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="c16df012d9649be75d6590f93aeacbdc24b29d53"/>
-  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="11663426672fcc46e2a0f29239afa736b90635ba"/>
+  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="431afac2ebfdd9c1c8402b413ff5914ed448e961"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="5701d3cb45c2e848cc57003cda2e1141288ecae4"/>
 </manifest>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e0f39c7179c8b297326c0e2313950610be1f5c52"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="49312fb89b90eca48a8011b94a1a1a751daf32d2"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
@@ -101,17 +101,17 @@
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="4f330e2d671e230c106a3c41ecddbced8ff5d826"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="bb653159145842bd86a3522073fcbf5d6450c598"/>
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="7044afe8fa0a992a2926370e7abe9d06cc9df67b"/>
   <project name="platform/libcore" path="libcore" revision="3552ed1686d04a65b85e56ccc24ff3fcf77725e6"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="4792069e90385889b0638e97ae62c67cdf274e22"/>
   <project name="platform/ndk" path="ndk" revision="7666b97bbaf1d645cdd6b4430a367b7a2bb53369"/>
   <project name="platform/prebuilts/misc" path="prebuilts/misc" revision="f6ab40b3257abc07741188fd173ac392575cc8d2"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="e52099755d0bd3a579130eefe8e58066cc6c0cb6"/>
-  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="11663426672fcc46e2a0f29239afa736b90635ba"/>
+  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="431afac2ebfdd9c1c8402b413ff5914ed448e961"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="842e33e43a55ea44833b9e23e4d180fa17c843af"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5db24726f0f42124304195a6bdea129039eeeaeb"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="930ae098543881f47eac054677726ee4b998b2f8"/>
   <project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
   <project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
   <project name="platform/system/media" path="system/media" revision="d90b836f66bf1d9627886c96f3a2d9c3007fbb80"/>
   <project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
   <project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e0f39c7179c8b297326c0e2313950610be1f5c52"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="49312fb89b90eca48a8011b94a1a1a751daf32d2"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <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="022eadd5917615ff00c47eaaafa792b45e9c8a28"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
@@ -91,11 +91,11 @@
   <project name="platform/system/vold" path="system/vold" revision="919829940468066a32f403980b43f6ebfee5d314"/>
   <!-- Emulator specific things -->
   <project name="android-development" path="development" remote="b2g" revision="4e236e65a5d652a66ac32590f69f2123d17cb4ad"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="e7e8734fdd8bf41e48a56c1c85e0f7dac60aaa9f"/>
   <project name="platform/external/iproute2" path="external/iproute2" revision="c66c5716d5335e450f7a7b71ccc6a604fb2f41d2"/>
   <project name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="d2685281e2e54ca14d1df304867aa82c37b27162"/>
   <project name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="627f9b20fc518937b93747a7ff1ed4f5ed46e06f"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="c16df012d9649be75d6590f93aeacbdc24b29d53"/>
-  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="11663426672fcc46e2a0f29239afa736b90635ba"/>
+  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="431afac2ebfdd9c1c8402b413ff5914ed448e961"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="5701d3cb45c2e848cc57003cda2e1141288ecae4"/>
 </manifest>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "7e08d1fefea803f39389bb009e146aaa692d126a", 
+    "revision": "e86b294efd18bfe96a58ba67f1b56fa48d70e753", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e0f39c7179c8b297326c0e2313950610be1f5c52"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="49312fb89b90eca48a8011b94a1a1a751daf32d2"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -5,17 +5,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e0f39c7179c8b297326c0e2313950610be1f5c52"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="49312fb89b90eca48a8011b94a1a1a751daf32d2"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e0f39c7179c8b297326c0e2313950610be1f5c52"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="49312fb89b90eca48a8011b94a1a1a751daf32d2"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e0f39c7179c8b297326c0e2313950610be1f5c52"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="49312fb89b90eca48a8011b94a1a1a751daf32d2"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e0f39c7179c8b297326c0e2313950610be1f5c52"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="49312fb89b90eca48a8011b94a1a1a751daf32d2"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
@@ -101,17 +101,17 @@
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="4f330e2d671e230c106a3c41ecddbced8ff5d826"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="bb653159145842bd86a3522073fcbf5d6450c598"/>
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="7044afe8fa0a992a2926370e7abe9d06cc9df67b"/>
   <project name="platform/libcore" path="libcore" revision="3552ed1686d04a65b85e56ccc24ff3fcf77725e6"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="4792069e90385889b0638e97ae62c67cdf274e22"/>
   <project name="platform/ndk" path="ndk" revision="7666b97bbaf1d645cdd6b4430a367b7a2bb53369"/>
   <project name="platform/prebuilts/misc" path="prebuilts/misc" revision="f6ab40b3257abc07741188fd173ac392575cc8d2"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="e52099755d0bd3a579130eefe8e58066cc6c0cb6"/>
-  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="11663426672fcc46e2a0f29239afa736b90635ba"/>
+  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="431afac2ebfdd9c1c8402b413ff5914ed448e961"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="842e33e43a55ea44833b9e23e4d180fa17c843af"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5db24726f0f42124304195a6bdea129039eeeaeb"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="930ae098543881f47eac054677726ee4b998b2f8"/>
   <project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
   <project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
   <project name="platform/system/media" path="system/media" revision="d90b836f66bf1d9627886c96f3a2d9c3007fbb80"/>
   <project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
   <project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e0f39c7179c8b297326c0e2313950610be1f5c52"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="49312fb89b90eca48a8011b94a1a1a751daf32d2"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1385,10 +1385,10 @@ pref("identity.fxaccounts.settings.uri",
 pref("identity.fxaccounts.auth.uri", "https://api.accounts.firefox.com/v1");
 
 // On GTK, we now default to showing the menubar only when alt is pressed:
 #ifdef MOZ_WIDGET_GTK
 pref("ui.key.menuAccessKeyFocuses", true);
 #endif
 
 
-// Temporarily turn the new http cache v2 on for Desktop Firefox only
-pref("browser.cache.use_new_backend_temp", true);
+// Delete HTTP cache v2 data of users that didn't opt-in manually
+pref("browser.cache.auto_delete_cache_version", 1);
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -51,17 +51,17 @@
       </menu>
       <menuitem id="context-copyemail"
                 label="&copyEmailCmd.label;"
                 accesskey="&copyEmailCmd.accesskey;"
                 oncommand="gContextMenu.copyEmail();"/>
       <menuitem id="context-copylink"
                 label="&copyLinkCmd.label;"
                 accesskey="&copyLinkCmd.accesskey;"
-                oncommand="goDoCommand('cmd_copyLink');"/>
+                oncommand="gContextMenu.copyLink();"/>
       <menuseparator id="context-sep-copylink"/>
       <menuitem id="context-media-play"
                 label="&mediaPlay.label;"
                 accesskey="&mediaPlay.accesskey;"
                 oncommand="gContextMenu.mediaCommand('play');"/>
       <menuitem id="context-media-pause"
                 label="&mediaPause.label;"
                 accesskey="&mediaPause.accesskey;"
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -844,17 +844,17 @@ nsContextMenu.prototype = {
     urlSecurityCheck(this.linkURL, this._unremotePrincipal(doc.nodePrincipal));
     var referrerURI = doc.documentURIObject;
 
     // if the mixedContentChannel is present and the referring URI passes
     // a same origin check with the target URI, we can preserve the users
     // decision of disabling MCB on a page for it's child tabs.
     var persistDisableMCBInChildTab = false;
 
-    if (this.browser.docShell.mixedContentChannel) {
+    if (this.browser.docShell && this.browser.docShell.mixedContentChannel) {
       const sm = Services.scriptSecurityManager;
       try {
         var targetURI = this.linkURI;
         sm.checkSameOriginURI(referrerURI, targetURI, false);
         persistDisableMCBInChildTab = true;
       }
       catch (e) { }
     }
@@ -1325,16 +1325,22 @@ nsContextMenu.prototype = {
       // Do nothing.
     }
 
     var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
                     getService(Ci.nsIClipboardHelper);
     clipboard.copyString(addresses, document);
   },
 
+  copyLink: function() {
+    var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
+                    getService(Ci.nsIClipboardHelper);
+    clipboard.copyString(this.linkURL, document);
+  },
+
   ///////////////
   // Utilities //
   ///////////////
 
   // Show/hide one item (specified via name or the item element itself).
   showItem: function(aItemOrId, aShow) {
     var item = aItemOrId.constructor == String ?
       document.getElementById(aItemOrId) : aItemOrId;
--- a/build/autoconf/hotfixes.m4
+++ b/build/autoconf/hotfixes.m4
@@ -14,11 +14,11 @@ dnl   #undef posix_memalign
 dnl This avoids double declaration of that function when the header normally
 dnl declares it, while the test itself is just expecting the function not to be
 dnl declared at all, and declares it differently (which doesn't matter for the
 dnl test itself).
 dnl More recent versions of autoconf are essentially doing this.
 define([ac_cv_func_], [ac_cv_func2_])dnl
 define([_AC_CHECK_FUNC],defn([AC_CHECK_FUNC]))dnl
 define([AC_CHECK_FUNC], [dnl
-patsubst(_AC_CHECK_FUNC($@), [#include.*], [#define $1 innocuous_$1
+patsubst(_AC_CHECK_FUNC($@), [#include.*$], [#define $1 innocuous_$1
 \&
 #undef $1])])dnl
--- a/build/autoconf/wrapper.m4
+++ b/build/autoconf/wrapper.m4
@@ -8,15 +8,26 @@ dnl ====================================
 AC_DEFUN([MOZ_CHECK_COMPILER_WRAPPER],
 [
 MOZ_ARG_WITH_STRING(compiler_wrapper,
 [  --with-compiler-wrapper[=path/to/wrapper]
     Enable compiling with wrappers such as distcc and ccache],
     COMPILER_WRAPPER=$withval, COMPILER_WRAPPER="no")
 
 if test "$COMPILER_WRAPPER" != "no"; then
-    CC="$COMPILER_WRAPPER $CC"
-    CXX="$COMPILER_WRAPPER $CXX"
-    MOZ_USING_COMPILER_WRAPPER=1
+    case "$CC" in
+    $COMPILER_WRAPPER\ *)
+        :
+        ;;
+    *)
+        CC="$COMPILER_WRAPPER $CC"
+        CXX="$COMPILER_WRAPPER $CXX"
+        _SUBDIR_CC="$CC"
+        _SUBDIR_CXX="$CXX"
+        ac_cv_prog_CC="$CC"
+        ac_cv_prog_CXX="$CXX"
+        MOZ_USING_COMPILER_WRAPPER=1
+        ;;
+    esac
 fi
 
 AC_SUBST(MOZ_USING_COMPILER_WRAPPER)
 ])
--- a/build/mozconfig.cache
+++ b/build/mozconfig.cache
@@ -16,11 +16,10 @@ if test -f "$topsrcdir/sccache/sccache.p
     esac
 fi
 
 if test -z "$bucket"; then
     ac_add_options --with-ccache
 else
     mk_add_options "export SCCACHE_BUCKET=$bucket"
     mk_add_options "export SCCACHE_NAMESERVER=169.254.169.253"
-    export CC="python2.7 $topsrcdir/sccache/sccache.py $CC"
-    export CXX="python2.7 $topsrcdir/sccache/sccache.py $CXX"
+    ac_add_options "--with-compiler-wrapper=python2.7 $topsrcdir/sccache/sccache.py"
 fi
--- a/configure.in
+++ b/configure.in
@@ -361,16 +361,18 @@ else
 fi
 
 if test -n "$MOZ_WINCONSOLE"; then
     AC_DEFINE(MOZ_WINCONSOLE)
 fi
 
 MOZ_TOOL_VARIABLES
 
+MOZ_CHECK_COMPILER_WRAPPER
+
 if test -n "$GNU_CC" -a -z "$CLANG_CC" ; then
     if test "$GCC_MAJOR_VERSION" -eq 4 -a "$GCC_MINOR_VERSION" -lt 4 ||
        test "$GCC_MAJOR_VERSION" -lt 4; then
         AC_MSG_ERROR([Only GCC 4.4 or newer supported])
     fi
 fi
 
 dnl ========================================================
@@ -7075,17 +7077,16 @@ MOZ_ARG_ENABLE_BOOL(root-analysis,
 [  --enable-root-analysis  Enable moving GC stack root analysis],
     JSGC_ROOT_ANALYSIS=1,
     JSGC_ROOT_ANALYSIS= )
 if test -n "$JSGC_ROOT_ANALYSIS"; then
     AC_DEFINE(JSGC_ROOT_ANALYSIS)
 fi
 
 MOZ_CHECK_CCACHE
-MOZ_CHECK_COMPILER_WRAPPER
 
 dnl ========================================================
 dnl = Enable static checking using gcc-dehydra
 dnl ========================================================
 
 MOZ_ARG_WITH_STRING(static-checking,
 [  --with-static-checking=path/to/gcc_dehydra.so
                           Enable static checking of code using GCC-dehydra],
--- a/content/base/public/nsViewportInfo.h
+++ b/content/base/public/nsViewportInfo.h
@@ -21,53 +21,59 @@ static const int32_t  kViewportDefaultSc
 /**
  * Information retrieved from the <meta name="viewport"> tag. See
  * nsContentUtils::GetViewportInfo for more information on this functionality.
  */
 class MOZ_STACK_CLASS nsViewportInfo
 {
   public:
     nsViewportInfo(const mozilla::ScreenIntSize& aDisplaySize,
-                   bool aAllowZoom = true) :
+                   bool aAllowZoom = true, bool aAllowDoubleTapZoom = true) :
       mDefaultZoom(1.0),
       mAutoSize(true),
-      mAllowZoom(aAllowZoom)
+      mAllowZoom(aAllowZoom),
+      mAllowDoubleTapZoom(aAllowDoubleTapZoom)
     {
         mSize = mozilla::gfx::RoundedToInt(mozilla::ScreenSize(aDisplaySize) / mDefaultZoom);
         mozilla::CSSToLayoutDeviceScale pixelRatio(1.0f);
         mMinZoom = pixelRatio * kViewportMinScale;
         mMaxZoom = pixelRatio * kViewportMaxScale;
         ConstrainViewportValues();
     }
 
     nsViewportInfo(const mozilla::CSSToScreenScale& aDefaultZoom,
                    const mozilla::CSSToScreenScale& aMinZoom,
                    const mozilla::CSSToScreenScale& aMaxZoom,
                    const mozilla::CSSIntSize& aSize,
                    bool aAutoSize,
-                   bool aAllowZoom) :
+                   bool aAllowZoom,
+                   bool aAllowDoubleTapZoom) :
                      mDefaultZoom(aDefaultZoom),
                      mMinZoom(aMinZoom),
                      mMaxZoom(aMaxZoom),
                      mSize(aSize),
                      mAutoSize(aAutoSize),
-                     mAllowZoom(aAllowZoom)
+                     mAllowZoom(aAllowZoom),
+                     mAllowDoubleTapZoom(aAllowDoubleTapZoom)
     {
       ConstrainViewportValues();
     }
 
     mozilla::CSSToScreenScale GetDefaultZoom() { return mDefaultZoom; }
     void SetDefaultZoom(const mozilla::CSSToScreenScale& aDefaultZoom);
     mozilla::CSSToScreenScale GetMinZoom() { return mMinZoom; }
     mozilla::CSSToScreenScale GetMaxZoom() { return mMaxZoom; }
 
     mozilla::CSSIntSize GetSize() { return mSize; }
 
     bool IsAutoSizeEnabled() { return mAutoSize; }
     bool IsZoomAllowed() { return mAllowZoom; }
+    bool IsDoubleTapZoomAllowed() { return mAllowDoubleTapZoom; }
+
+    void SetAllowDoubleTapZoom(bool aAllowDoubleTapZoom) { mAllowDoubleTapZoom = aAllowDoubleTapZoom; }
 
   private:
 
     /**
      * Constrain the viewport calculations from the
      * nsContentUtils::GetViewportInfo() function in order to always return
      * sane minimum/maximum values.
      */
@@ -89,12 +95,17 @@ class MOZ_STACK_CLASS nsViewportInfo
     // Whether or not we should automatically size the viewport to the device's
     // width. This is true if the document has been optimized for mobile, and
     // the width property of a specified <meta name="viewport"> tag is either
     // not specified, or is set to the special value 'device-width'.
     bool mAutoSize;
 
     // Whether or not the user can zoom in and out on the page. Default is true.
     bool mAllowZoom;
+
+    // Whether or not the user can double-tap to zoom in. When this is disabled
+    // we can dispatch click events faster on a single tap because we don't have
+    // to wait to detect the double-tap
+    bool mAllowDoubleTapZoom;
 };
 
 #endif
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -7448,21 +7448,25 @@ nsIDocument::AdoptNode(nsINode& aAdopted
                "Should still be in the document we just got adopted into");
 
   return adoptedNode;
 }
 
 nsViewportInfo
 nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
 {
+  // In cases where the width of the CSS viewport is less than or equal to the width
+  // of the display (i.e. width <= device-width) then we disable double-tap-to-zoom
+  // behaviour. See bug 941995 for details.
+
   switch (mViewportType) {
   case DisplayWidthHeight:
     return nsViewportInfo(aDisplaySize);
   case DisplayWidthHeightNoZoom:
-    return nsViewportInfo(aDisplaySize, /* allowZoom */ false);
+    return nsViewportInfo(aDisplaySize, /*allowZoom*/ false, /*allowDoubleTapZoom*/ false);
   case Unknown:
   {
     nsAutoString viewport;
     GetHeaderData(nsGkAtoms::viewport, viewport);
     if (viewport.IsEmpty()) {
       // If the docType specifies that we are on a site optimized for mobile,
       // then we want to return specially crafted defaults for the viewport info.
       nsCOMPtr<nsIDOMDocumentType> docType;
@@ -7472,26 +7476,26 @@ nsDocument::GetViewportInfo(const Screen
         rv = docType->GetPublicId(docId);
         if (NS_SUCCEEDED(rv)) {
           if ((docId.Find("WAP") != -1) ||
               (docId.Find("Mobile") != -1) ||
               (docId.Find("WML") != -1))
           {
             // We're making an assumption that the docType can't change here
             mViewportType = DisplayWidthHeight;
-            return nsViewportInfo(aDisplaySize);
+            return nsViewportInfo(aDisplaySize, /*allowZoom*/true, /*allowDoubleTapZoom*/false);
           }
         }
       }
 
       nsAutoString handheldFriendly;
       GetHeaderData(nsGkAtoms::handheldFriendly, handheldFriendly);
       if (handheldFriendly.EqualsLiteral("true")) {
         mViewportType = DisplayWidthHeight;
-        return nsViewportInfo(aDisplaySize);
+        return nsViewportInfo(aDisplaySize, /*allowZoom*/true, /*allowDoubleTapZoom*/false);
       }
 
       // Bug 940036. This is bad. When FirefoxOS was built, apps installed
       // where not using the AsyncPanZoom code. As a result a lot of apps
       // in the marketplace does not use it yet and instead are built to
       // render correctly in FirefoxOS only. For a smooth transition the above
       // code force installed apps to render as if they have a viewport with
       // content="width=device-width, height=device-height, user-scalable=no".
@@ -7504,17 +7508,17 @@ nsDocument::GetViewportInfo(const Screen
         GetDocumentURI(uri);
         if (!uri.EqualsLiteral("about:blank")) {
           nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                           NS_LITERAL_CSTRING("DOM"), this,
                                           nsContentUtils::eDOM_PROPERTIES,
                                           "ImplicitMetaViewportTagFallback");
         }
         mViewportType = DisplayWidthHeightNoZoom;
-        return nsViewportInfo(aDisplaySize, /* allowZoom */ false);
+        return nsViewportInfo(aDisplaySize, /*allowZoom*/false, /*allowDoubleTapZoom*/false);
       }
     }
 
     nsAutoString minScaleStr;
     GetHeaderData(nsGkAtoms::viewport_minimum_scale, minScaleStr);
 
     nsresult errorCode;
     mScaleMinFloat = LayoutDeviceToScreenScale(minScaleStr.ToFloat(&errorCode));
@@ -7578,16 +7582,17 @@ nsDocument::GetViewportInfo(const Screen
     nsAutoString userScalable;
     GetHeaderData(nsGkAtoms::viewport_user_scalable, userScalable);
 
     if ((userScalable.EqualsLiteral("0")) ||
         (userScalable.EqualsLiteral("no")) ||
         (userScalable.EqualsLiteral("false"))) {
       mAllowZoom = false;
     }
+    mAllowDoubleTapZoom = mAllowZoom;
 
     mScaleStrEmpty = scaleStr.IsEmpty();
     mWidthStrEmpty = widthStr.IsEmpty();
     mValidScaleFloat = !scaleStr.IsEmpty() && NS_SUCCEEDED(scaleErrorCode);
     mValidMaxScale = !maxScaleStr.IsEmpty() && NS_SUCCEEDED(scaleMaxErrorCode);
 
     mViewportType = Specified;
   }
@@ -7644,17 +7649,17 @@ nsDocument::GetViewportInfo(const Screen
       size.height = std::max(size.height, displaySize.height);
     } else if (mValidMaxScale) {
       CSSIntSize displaySize = RoundedToInt(ScreenSize(aDisplaySize) / scaleMaxFloat);
       size.width = std::max(size.width, displaySize.width);
       size.height = std::max(size.height, displaySize.height);
     }
 
     return nsViewportInfo(scaleFloat, scaleMinFloat, scaleMaxFloat, size,
-                          mAutoSize, mAllowZoom);
+                          mAutoSize, mAllowZoom, mAllowDoubleTapZoom);
   }
 }
 
 nsEventListenerManager*
 nsDocument::GetOrCreateListenerManager()
 {
   if (!mListenerManager) {
     mListenerManager =
@@ -11313,17 +11318,17 @@ public:
     nsDocument* doc = static_cast<nsDocument*>(d.get());
     if (doc->mAsyncFullscreenPending ||
         (doc->mHasFullscreenApprovedObserver && !doc->mIsApprovedForFullscreen)) {
       // We're still waiting for approval.
       return NS_OK;
     }
 
     if (doc->mIsApprovedForFullscreen || doc->mAllowRelocking) {
-      Allow();
+      Allow(JS::UndefinedHandleValue);
       return NS_OK;
     }
 
     // In non-fullscreen mode user input (or chrome caller) is required!
     // Also, don't let the page to try to get the permission too many times.
     if (!mUserInputOrChromeCaller ||
         doc->mCancelledPointerLockRequests > 2) {
       Handled();
@@ -11358,18 +11363,20 @@ public:
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsPointerLockPermissionRequest,
                              nsRunnable,
                              nsIContentPermissionRequest)
 
 NS_IMETHODIMP
 nsPointerLockPermissionRequest::GetTypes(nsIArray** aTypes)
 {
+  nsTArray<nsString> emptyOptions;
   return CreatePermissionArray(NS_LITERAL_CSTRING("pointerLock"),
                                NS_LITERAL_CSTRING("unused"),
+                               emptyOptions,
                                aTypes);
 }
 
 NS_IMETHODIMP
 nsPointerLockPermissionRequest::GetPrincipal(nsIPrincipal** aPrincipal)
 {
   nsCOMPtr<nsIDocument> d = do_QueryReferent(mDocument);
   if (d) {
@@ -11404,18 +11411,20 @@ nsPointerLockPermissionRequest::Cancel()
   if (d) {
     static_cast<nsDocument*>(d.get())->mCancelledPointerLockRequests++;
     DispatchPointerLockError(d);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPointerLockPermissionRequest::Allow()
-{
+nsPointerLockPermissionRequest::Allow(JS::HandleValue aChoices)
+{
+  MOZ_ASSERT(aChoices.isUndefined());
+
   nsCOMPtr<Element> e = do_QueryReferent(mElement);
   nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
   nsDocument* d = static_cast<nsDocument*>(doc.get());
   if (!e || !d || gPendingPointerLockRequest != this ||
       e->GetCurrentDoc() != d ||
       (!mUserInputOrChromeCaller && !d->mIsApprovedForFullscreen)) {
     Handled();
     DispatchPointerLockError(d);
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1627,17 +1627,17 @@ private:
 
   // These member variables cache information about the viewport so we don't have to
   // recalculate it each time.
   bool mValidWidth, mValidHeight;
   mozilla::LayoutDeviceToScreenScale mScaleMinFloat;
   mozilla::LayoutDeviceToScreenScale mScaleMaxFloat;
   mozilla::LayoutDeviceToScreenScale mScaleFloat;
   mozilla::CSSToLayoutDeviceScale mPixelRatio;
-  bool mAutoSize, mAllowZoom, mValidScaleFloat, mValidMaxScale, mScaleStrEmpty, mWidthStrEmpty;
+  bool mAutoSize, mAllowZoom, mAllowDoubleTapZoom, mValidScaleFloat, mValidMaxScale, mScaleStrEmpty, mWidthStrEmpty;
   mozilla::CSSIntSize mViewportSize;
 
   nsrefcnt mStackRefCnt;
   bool mNeedsReleaseAfterStackRefCntRelease;
 
   CSPErrorQueue mCSPWebConsoleErrorQueue;
 
 #ifdef DEBUG
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -1738,21 +1738,21 @@ public:
     if (!BuildClonedMessageDataForChild(cc, aData, data)) {
       return false;
     }
     InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
     if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
       return false;
     }
     if (aIsSync) {
-      return cc->SendSyncMessage(nsString(aMessage), data, cpows, aPrincipal,
-                                 aJSONRetVal);
+      return cc->SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
+                                 aPrincipal, aJSONRetVal);
     }
-    return cc->CallRpcMessage(nsString(aMessage), data, cpows, aPrincipal,
-                              aJSONRetVal);
+    return cc->CallRpcMessage(PromiseFlatString(aMessage), data, cpows,
+                              aPrincipal, aJSONRetVal);
   }
 
   virtual bool DoSendAsyncMessage(JSContext* aCx,
                                   const nsAString& aMessage,
                                   const mozilla::dom::StructuredCloneData& aData,
                                   JS::Handle<JSObject *> aCpows,
                                   nsIPrincipal* aPrincipal) MOZ_OVERRIDE
   {
@@ -1764,17 +1764,18 @@ public:
     ClonedMessageData data;
     if (!BuildClonedMessageDataForChild(cc, aData, data)) {
       return false;
     }
     InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
     if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
       return false;
     }
-    return cc->SendAsyncMessage(nsString(aMessage), data, cpows, aPrincipal);
+    return cc->SendAsyncMessage(PromiseFlatString(aMessage), data, cpows,
+                                aPrincipal);
   }
 
 };
 
 
 class nsAsyncMessageToSameProcessParent : public nsRunnable
 {
 public:
--- a/content/media/MediaDecoderReader.cpp
+++ b/content/media/MediaDecoderReader.cpp
@@ -76,32 +76,38 @@ VideoData* MediaDecoderReader::DecodeToF
       ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
       if (mDecoder->IsShutdown()) {
         return nullptr;
       }
     }
     bool keyframeSkip = false;
     eof = !DecodeVideoFrame(keyframeSkip, 0);
   }
+  if (eof) {
+    VideoQueue().Finish();
+  }
   VideoData* d = nullptr;
   return (d = VideoQueue().PeekFront()) ? d : nullptr;
 }
 
 AudioData* MediaDecoderReader::DecodeToFirstAudioData()
 {
   bool eof = false;
   while (!eof && AudioQueue().GetSize() == 0) {
     {
       ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
       if (mDecoder->IsShutdown()) {
         return nullptr;
       }
     }
     eof = !DecodeAudioData();
   }
+  if (eof) {
+    AudioQueue().Finish();
+  }
   AudioData* d = nullptr;
   return (d = AudioQueue().PeekFront()) ? d : nullptr;
 }
 
 VideoData* MediaDecoderReader::FindStartTime(int64_t& aOutStartTime)
 {
   NS_ASSERTION(mDecoder->OnStateMachineThread() || mDecoder->OnDecodeThread(),
                "Should be on state machine or decode thread.");
@@ -150,21 +156,22 @@ nsresult MediaDecoderReader::DecodeToTar
         eof = !DecodeVideoFrame(skip, 0);
         {
           ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
           if (mDecoder->IsShutdown()) {
             return NS_ERROR_FAILURE;
           }
         }
       }
-      if (VideoQueue().GetSize() == 0) {
+      if (eof) {
         // Hit end of file, we want to display the last frame of the video.
         if (video) {
           VideoQueue().PushFront(video.forget());
         }
+        VideoQueue().Finish();
         break;
       }
       video = VideoQueue().PeekFront();
       // If the frame end time is less than the seek target, we won't want
       // to display this frame after the seek, so discard it.
       if (video && video->GetEndTime() <= aTarget) {
         if (startTime == -1) {
           startTime = video->mTime;
@@ -193,18 +200,20 @@ nsresult MediaDecoderReader::DecodeToTar
         {
           ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
           if (mDecoder->IsShutdown()) {
             return NS_ERROR_FAILURE;
           }
         }
       }
       const AudioData* audio = AudioQueue().PeekFront();
-      if (!audio)
+      if (!audio || eof) {
+        AudioQueue().Finish();
         break;
+      }
       CheckedInt64 startFrame = UsecsToFrames(audio->mTime, mInfo.mAudio.mRate);
       CheckedInt64 targetFrame = UsecsToFrames(aTarget, mInfo.mAudio.mRate);
       if (!startFrame.isValid() || !targetFrame.isValid()) {
         return NS_ERROR_FAILURE;
       }
       if (startFrame.value() + audio->mFrames <= targetFrame.value()) {
         // Our seek target lies after the frames in this AudioData. Pop it
         // off the queue, and keep decoding forwards.
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -1794,27 +1794,29 @@ void MediaDecoderStateMachine::DecodeSee
       // while we seek, since the seek reads, which could block on I/O.
       res = mReader->Seek(seekTime,
                           mStartTime,
                           mEndTime,
                           mediaTime);
     }
     if (NS_SUCCEEDED(res)) {
       AudioData* audio = HasAudio() ? mReader->AudioQueue().PeekFront() : nullptr;
-      NS_ASSERTION(!audio || (audio->mTime <= seekTime &&
-                              seekTime <= audio->mTime + audio->mDuration),
-                    "Seek target should lie inside the first audio block after seek");
+      MOZ_ASSERT(!audio ||
+                 (audio->mTime <= seekTime &&
+                  seekTime <= audio->mTime + audio->mDuration) ||
+                 mReader->AudioQueue().IsFinished(),
+                 "Seek target should lie inside the first audio block after seek");
       int64_t startTime = (audio && audio->mTime < seekTime) ? audio->mTime : seekTime;
       mAudioStartTime = startTime;
       mPlayDuration = startTime - mStartTime;
       if (HasVideo()) {
         VideoData* video = mReader->VideoQueue().PeekFront();
         if (video) {
-          NS_ASSERTION((video->mTime <= seekTime && seekTime <= video->GetEndTime()) ||
-                        mReader->VideoQueue().IsFinished(),
+          MOZ_ASSERT((video->mTime <= seekTime && seekTime <= video->GetEndTime()) ||
+                     mReader->VideoQueue().IsFinished(),
             "Seek target should lie inside the first frame after seek, unless it's the last frame.");
           {
             ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
             RenderVideoFrame(video, TimeStamp::Now());
           }
           nsCOMPtr<nsIRunnable> event =
             NS_NewRunnableMethod(mDecoder, &MediaDecoder::Invalidate);
           NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -10,16 +10,19 @@
 #include <cutils/properties.h>
 #include <stagefright/foundation/ADebug.h>
 #include <stagefright/foundation/AMessage.h>
 #include <stagefright/MediaExtractor.h>
 #include <stagefright/MetaData.h>
 #include <stagefright/OMXClient.h>
 #include <stagefright/OMXCodec.h>
 #include <OMX.h>
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#include <ui/Fence.h>
+#endif
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Types.h"
 #include "mozilla/Monitor.h"
 #include "nsMimeTypes.h"
 #include "MPAPI.h"
 #include "prlog.h"
 
@@ -208,17 +211,17 @@ void
 VideoGraphicBuffer::Unlock()
 {
   android::sp<android::OmxDecoder> omxDecoder = mOmxDecoder.promote();
   if (omxDecoder.get()) {
     // Post kNotifyPostReleaseVideoBuffer message to OmxDecoder via ALooper.
     // The message is delivered to OmxDecoder on ALooper thread.
     // MediaBuffer::release() could take a very long time.
     // PostReleaseVideoBuffer() prevents long time locking.
-    omxDecoder->PostReleaseVideoBuffer(mMediaBuffer);
+    omxDecoder->PostReleaseVideoBuffer(mMediaBuffer, mReleaseFenceHandle);
   } else {
     NS_WARNING("OmxDecoder is not present");
     if (mMediaBuffer) {
       mMediaBuffer->release();
     }
   }
   mMediaBuffer = nullptr;
 }
@@ -789,17 +792,17 @@ bool OmxDecoder::ReadVideo(VideoFrame *a
       mIsVideoSeeking = true;
     }
     MediaSource::ReadOptions options;
     options.setSeekTo(aTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
     err = mVideoSource->read(&mVideoBuffer, &options);
     {
       Mutex::Autolock autoLock(mSeekLock);
       mIsVideoSeeking = false;
-      ReleaseAllPendingVideoBuffersLocked();
+      PostReleaseVideoBuffer(nullptr, FenceHandle());
     }
 
     aDoSeek = false;
   } else {
     err = mVideoSource->read(&mVideoBuffer);
   }
 
   aFrame->mSize = 0;
@@ -836,16 +839,19 @@ bool OmxDecoder::ReadVideo(VideoFrame *a
 
       mozilla::layers::SurfaceDescriptor descWrapper(newDescriptor);
       aFrame->mGraphicBuffer = new mozilla::layers::VideoGraphicBuffer(this, mVideoBuffer, descWrapper);
       aFrame->mRotation = mVideoRotation;
       aFrame->mTimeUs = timeUs;
       aFrame->mKeyFrame = keyFrame;
       aFrame->Y.mWidth = mVideoWidth;
       aFrame->Y.mHeight = mVideoHeight;
+      // Release to hold video buffer in OmxDecoder more.
+      // MediaBuffer's ref count is changed from 2 to 1.
+      ReleaseVideoBuffer();
     } else if (mVideoBuffer->range_length() > 0) {
       char *data = static_cast<char *>(mVideoBuffer->data()) + mVideoBuffer->range_offset();
       size_t length = mVideoBuffer->range_length();
 
       if (unreadable) {
         LOG(PR_LOG_DEBUG, "video frame is unreadable");
       }
 
@@ -1017,47 +1023,69 @@ void OmxDecoder::onMessageReceived(const
     }
 
     default:
       TRESPASS();
       break;
   }
 }
 
-void OmxDecoder::PostReleaseVideoBuffer(MediaBuffer *aBuffer)
+void OmxDecoder::PostReleaseVideoBuffer(MediaBuffer *aBuffer, const FenceHandle& aReleaseFenceHandle)
 {
   {
     Mutex::Autolock autoLock(mPendingVideoBuffersLock);
-    mPendingVideoBuffers.push(aBuffer);
+    if (aBuffer) {
+      mPendingVideoBuffers.push(BufferItem(aBuffer, aReleaseFenceHandle));
+    }
   }
 
   sp<AMessage> notify =
             new AMessage(kNotifyPostReleaseVideoBuffer, mReflector->id());
   // post AMessage to OmxDecoder via ALooper.
   notify->post();
 }
 
 void OmxDecoder::ReleaseAllPendingVideoBuffersLocked()
 {
-  Vector<MediaBuffer *> releasingVideoBuffers;
+  Vector<BufferItem> releasingVideoBuffers;
   {
     Mutex::Autolock autoLock(mPendingVideoBuffersLock);
 
     int size = mPendingVideoBuffers.size();
     for (int i = 0; i < size; i++) {
-      MediaBuffer *buffer = mPendingVideoBuffers[i];
-      releasingVideoBuffers.push(buffer);
+      releasingVideoBuffers.push(mPendingVideoBuffers[i]);
     }
     mPendingVideoBuffers.clear();
   }
   // Free all pending video buffers without holding mPendingVideoBuffersLock.
   int size = releasingVideoBuffers.size();
   for (int i = 0; i < size; i++) {
     MediaBuffer *buffer;
-    buffer = releasingVideoBuffers[i];
+    buffer = releasingVideoBuffers[i].mMediaBuffer;
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+    android::sp<Fence> fence;
+    int fenceFd = -1;
+    fence = releasingVideoBuffers[i].mReleaseFenceHandle.mFence;
+    if (fence.get() && fence->isValid()) {
+      fenceFd = fence->dup();
+    }
+    MOZ_ASSERT(buffer->refcount() == 1);
+    // This code expect MediaBuffer's ref count is 1.
+    // Return gralloc buffer to ANativeWindow
+    ANativeWindow* window = static_cast<ANativeWindow*>(mNativeWindowClient.get());
+    window->cancelBuffer(window,
+                         buffer->graphicBuffer().get(),
+                         fenceFd);
+    // Mark MediaBuffer as rendered.
+    // When gralloc buffer is directly returned to ANativeWindow,
+    // this mark is necesary.
+    sp<MetaData> metaData = buffer->meta_data();
+    metaData->setInt32(kKeyRendered, 1);
+#endif
+    // Return MediaBuffer to OMXCodec.
     buffer->release();
   }
   releasingVideoBuffers.clear();
 }
 
 int64_t OmxDecoder::ProcessCachedData(int64_t aOffset, bool aWaitForCompletion)
 {
   // We read data in chunks of 32 KiB. We can reduce this
--- a/content/media/omx/OmxDecoder.h
+++ b/content/media/omx/OmxDecoder.h
@@ -5,16 +5,17 @@
 #include <stagefright/DataSource.h>
 #include <stagefright/MediaSource.h>
 #include <utils/RefBase.h>
 #include <stagefright/MediaExtractor.h>
 
 #include "GonkNativeWindow.h"
 #include "GonkNativeWindowClient.h"
 #include "GrallocImages.h"
+#include "mozilla/layers/FenceUtils.h"
 #include "MP3FrameParser.h"
 #include "MPAPI.h"
 #include "MediaResource.h"
 #include "AbstractMediaDecoder.h"
 #include "OMXCodecProxy.h"
 
 namespace android {
 class OmxDecoder;
@@ -78,16 +79,17 @@ private:
 };
 
 class OmxDecoder : public OMXCodecProxy::EventListener {
   typedef MPAPI::AudioFrame AudioFrame;
   typedef MPAPI::VideoFrame VideoFrame;
   typedef mozilla::MP3FrameParser MP3FrameParser;
   typedef mozilla::MediaResource MediaResource;
   typedef mozilla::AbstractMediaDecoder AbstractMediaDecoder;
+  typedef mozilla::layers::FenceHandle FenceHandle;
 
   enum {
     kPreferSoftwareCodecs = 1,
     kSoftwareCodecsOnly = 8,
     kHardwareCodecsOnly = 16,
   };
 
   enum {
@@ -117,21 +119,36 @@ class OmxDecoder : public OMXCodecProxy:
   MP3FrameParser mMP3FrameParser;
   bool mIsMp3;
 
   // Lifetime of these should be handled by OMXCodec, as long as we release
   //   them after use: see ReleaseVideoBuffer(), ReleaseAudioBuffer()
   MediaBuffer *mVideoBuffer;
   MediaBuffer *mAudioBuffer;
 
+  struct BufferItem {
+    BufferItem()
+     : mMediaBuffer(nullptr)
+    {
+    }
+    BufferItem(MediaBuffer* aMediaBuffer, const FenceHandle& aReleaseFenceHandle)
+     : mMediaBuffer(aMediaBuffer)
+     , mReleaseFenceHandle(aReleaseFenceHandle) {
+    }
+
+    MediaBuffer* mMediaBuffer;
+    // a fence will signal when the current buffer is no longer being read.
+    FenceHandle mReleaseFenceHandle;
+  };
+
   // Hold video's MediaBuffers that are released during video seeking.
   // The holded MediaBuffers are released soon after seek completion.
   // OMXCodec does not accept MediaBuffer during seeking. If MediaBuffer is
   //  returned to OMXCodec during seeking, OMXCodec calls assert.
-  Vector<MediaBuffer *> mPendingVideoBuffers;
+  Vector<BufferItem> mPendingVideoBuffers;
   // The lock protects mPendingVideoBuffers.
   Mutex mPendingVideoBuffersLock;
 
   // Show if OMXCodec is seeking.
   bool mIsVideoSeeking;
   // The lock protects video MediaBuffer release()'s pending operations called
   //  from multiple threads. The pending operations happen only during video
   //  seeking. Holding mSeekLock long time could affect to video rendering.
@@ -230,17 +247,17 @@ public:
 
   //Change decoder into a playing state
   nsresult Play();
 
   //Change decoder into a paused state
   void Pause();
 
   // Post kNotifyPostReleaseVideoBuffer message to OmxDecoder via ALooper.
-  void PostReleaseVideoBuffer(MediaBuffer *aBuffer);
+  void PostReleaseVideoBuffer(MediaBuffer *aBuffer, const FenceHandle& aReleaseFenceHandle);
   // Receive a message from AHandlerReflector.
   // Called on ALooper thread.
   void onMessageReceived(const sp<AMessage> &msg);
 
   int64_t ProcessCachedData(int64_t aOffset, bool aWaitForCompletion);
 };
 
 }
--- a/content/media/plugins/MediaPluginHost.cpp
+++ b/content/media/plugins/MediaPluginHost.cpp
@@ -167,17 +167,17 @@ static const char* GetOmxLibraryName()
     ALOG("Android Hardware is: %s", NS_LossyConvertUTF16toASCII(hardware).get());
   }
 #endif
 
   if (!IsOmxSupported())
     return nullptr;
 
 #if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
-  if (version >= 19) {
+  if (version >= 17) {
     return "libomxpluginkk.so";
   }
   else if (version == 13 || version == 12 || version == 11) {
     return "libomxpluginhc.so";
   }
   else if (version == 10 && release_version >= NS_LITERAL_STRING("2.3.6")) {
     // Gingerbread versions from 2.3.6 and above have a different DataSource
     // layout to those on 2.3.5 and below.
--- a/content/media/test/test_bug495300.html
+++ b/content/media/test/test_bug495300.html
@@ -10,21 +10,16 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script type="text/javascript" src="manifest.js"></script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=495300">Mozilla Bug 495300</a>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
-if (!navigator.platform.startsWith("Mac")) {
-  // not Mac
-  SimpleTest.expectAssertions(0, 2);
-}
-
 var manager = new MediaTestManager;
 
 function filename(uri) {
   return uri.substr(uri.lastIndexOf("/")+1);
 }
 
 function mediaEnded(event) {
   ok(true, "Got expected 'ended' event: " + filename(event.target.currentSrc));
--- a/content/media/webaudio/test/test_bug827541.html
+++ b/content/media/webaudio/test/test_bug827541.html
@@ -6,17 +6,17 @@
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
   var iframe = document.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
   document.body.appendChild(iframe);
   var frameWin = iframe.contentWindow;
-  frameWin.AudioContext();
+  new frameWin.AudioContext();
   document.body.removeChild(iframe);
-  frameWin.AudioContext();
+  new frameWin.AudioContext();
 
   ok(true, "This test should not leak");
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/webaudio/test/test_bug839753.html
+++ b/content/media/webaudio/test/test_bug839753.html
@@ -4,15 +4,15 @@
   <title>Crashtest for bug 839753</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
-AudioContext().destination.expando = null;
+(new AudioContext()).destination.expando = null;
 ok(true, "The test should not trigger wrapper cache assertions");
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/webaudio/test/test_bug866570.html
+++ b/content/media/webaudio/test/test_bug866570.html
@@ -4,15 +4,15 @@
   <title>Crashtest for bug 859600</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
-AudioContext().foo = null;
+(new AudioContext()).foo = null;
 ok(true, "The test should not fatally assert");
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/webaudio/test/test_bug894150.html
+++ b/content/media/webaudio/test/test_bug894150.html
@@ -3,17 +3,17 @@
 <head>
   <title>Test whether we can create an AudioContext interface</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script>
 
-var ac = AudioContext();
+var ac = new AudioContext();
 ac.createPanner();
 var listener = ac.listener;
 SpecialPowers.forceGC();
 SpecialPowers.forceCC();
 listener.setOrientation(0, 0, -1, 0, 0, 0);
 
 ok(true, "No crashes should happen!");
 
--- a/content/media/webrtc/MediaEngineWebRTC.h
+++ b/content/media/webrtc/MediaEngineWebRTC.h
@@ -46,16 +46,17 @@
 #include "webrtc/video_engine/include/vie_render.h"
 #include "webrtc/video_engine/include/vie_capture.h"
 #ifdef MOZ_B2G_CAMERA
 #include "CameraControlListener.h"
 #include "ICameraControl.h"
 #include "ImageContainer.h"
 #include "nsGlobalWindow.h"
 #include "prprf.h"
+#include "mozilla/Hal.h"
 #endif
 
 #include "NullTransport.h"
 
 namespace mozilla {
 
 #ifdef MOZ_B2G_CAMERA
 class CameraAllocateRunnable;
@@ -78,26 +79,28 @@ class GetCameraNameRunnable;
  * Where mWidth, mHeight, mImage are protected by mMonitor
  *       mState, mLastCapture is protected by mCallbackMonitor
  * Other variable is accessed only from single thread
  */
 class MediaEngineWebRTCVideoSource : public MediaEngineVideoSource
                                    , public nsRunnable
 #ifdef MOZ_B2G_CAMERA
                                    , public CameraControlListener
+                                   , public mozilla::hal::ScreenConfigurationObserver
 #else
                                    , public webrtc::ExternalRenderer
 #endif
 {
 public:
 #ifdef MOZ_B2G_CAMERA
   MediaEngineWebRTCVideoSource(int aIndex)
     : mCameraControl(nullptr)
     , mCallbackMonitor("WebRTCCamera.CallbackMonitor")
-    , mSensorAngle(0)
+    , mRotation(0)
+    , mBackCamera(false)
     , mCaptureIndex(aIndex)
     , mMonitor("WebRTCCamera.Monitor")
     , mWidth(0)
     , mHeight(0)
     , mInitDone(false)
     , mInSnapshotMode(false)
     , mSnapshotPath(nullptr)
   {
@@ -167,17 +170,18 @@ public:
   void OnError(CameraErrorContext aContext, CameraError aError);
   void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType);
 
   void AllocImpl();
   void DeallocImpl();
   void StartImpl(webrtc::CaptureCapability aCapability);
   void StopImpl();
   void SnapshotImpl();
-  void RotateImage(layers::Image* aImage);
+  void RotateImage(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight);
+  void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration);
 #endif
 
   // This runnable is for creating a temporary file on the main thread.
   NS_IMETHODIMP
   Run()
   {
     nsCOMPtr<nsIFile> tmp;
     nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmp));
@@ -202,17 +206,19 @@ private:
   void Init();
   void Shutdown();
 
   // Engine variables.
 #ifdef MOZ_B2G_CAMERA
   nsRefPtr<ICameraControl> mCameraControl;
   mozilla::ReentrantMonitor mCallbackMonitor; // Monitor for camera callback handling
   nsRefPtr<nsIDOMFile> mLastCapture;
-  int mSensorAngle;
+  int mRotation;
+  int mCameraAngle; // See dom/base/ScreenOrientation.h
+  bool mBackCamera;
 #else
   webrtc::VideoEngine* mVideoEngine; // Weak reference, don't free.
   webrtc::ViEBase* mViEBase;
   webrtc::ViECapture* mViECapture;
   webrtc::ViERender* mViERender;
 #endif
   webrtc::CaptureCapability mCapability; // Doesn't work on OS X.
 
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -7,16 +7,19 @@
 #include "ImageTypes.h"
 #include "ImageContainer.h"
 #include "nsMemory.h"
 #include "mtransport/runnable_utils.h"
 
 #ifdef MOZ_B2G_CAMERA
 #include "GrallocImages.h"
 #include "libyuv.h"
+#include "mozilla/Hal.h"
+#include "ScreenOrientation.h"
+using namespace mozilla::dom;
 #endif
 namespace mozilla {
 
 using namespace mozilla::gfx;
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetMediaManagerLog();
 #define LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
@@ -132,17 +135,17 @@ MediaEngineWebRTCVideoSource::NotifyPull
   MonitorAutoLock lock(mMonitor);
   if (mState != kStarted)
     return;
 
   // Note: we're not giving up mImage here
   nsRefPtr<layers::Image> image = mImage;
   TrackTicks target = TimeToTicksRoundUp(USECS_PER_S, aDesiredTime);
   TrackTicks delta = target - aLastEndTime;
-  LOGFRAME(("NotifyPull, desired = %ld, target = %ld, delta = %ld %s", (int64_t) aDesiredTime, 
+  LOGFRAME(("NotifyPull, desired = %ld, target = %ld, delta = %ld %s", (int64_t) aDesiredTime,
             (int64_t) target, (int64_t) delta, image ? "" : "<null>"));
 
   // Bug 846188 We may want to limit incoming frames to the requested frame rate
   // mFps - if you want 30FPS, and the camera gives you 60FPS, this could
   // cause issues.
   // We may want to signal if the actual frame rate is below mMinFPS -
   // cameras often don't return the requested frame rate especially in low
   // light; we should consider surfacing this so that we can switch to a
@@ -507,44 +510,94 @@ MediaEngineWebRTCVideoSource::AllocImpl(
   mCameraControl = ICameraControl::Create(mCaptureIndex);
   if (mCameraControl) {
     mState = kAllocated;
     // Add this as a listener for CameraControl events. We don't need
     // to explicitly remove this--destroying the CameraControl object
     // in DeallocImpl() will do that for us.
     mCameraControl->AddListener(this);
   }
+
   mCallbackMonitor.Notify();
 }
 
 void
 MediaEngineWebRTCVideoSource::DeallocImpl() {
   MOZ_ASSERT(NS_IsMainThread());
 
   mCameraControl = nullptr;
 }
 
+// The same algorithm from bug 840244
+static int
+GetRotateAmount(ScreenOrientation aScreen, int aCameraMountAngle, bool aBackCamera) {
+  int screenAngle = 0;
+  switch (aScreen) {
+    case eScreenOrientation_PortraitPrimary:
+      screenAngle = 0;
+      break;
+    case eScreenOrientation_PortraitSecondary:
+      screenAngle = 180;
+      break;
+   case eScreenOrientation_LandscapePrimary:
+      screenAngle = 90;
+      break;
+   case eScreenOrientation_LandscapeSecondary:
+      screenAngle = 270;
+      break;
+   default:
+      MOZ_ASSERT(false);
+      break;
+  }
+
+  int result;
+
+  if (aBackCamera) {
+    //back camera
+    result = (aCameraMountAngle - screenAngle + 360) % 360;
+  } else {
+    //front camera
+    result = (aCameraMountAngle + screenAngle) % 360;
+  }
+  return result;
+}
+
+// undefine to remove on-the-fly rotation support
+// #define DYNAMIC_GUM_ROTATION
+
+void
+MediaEngineWebRTCVideoSource::Notify(const hal::ScreenConfiguration& aConfiguration) {
+#ifdef DYNAMIC_GUM_ROTATION
+  MonitorAutoLock enter(mMonitor);
+  mRotation = GetRotateAmount(aConfiguration.orientation(), mCameraAngle, mBackCamera);
+
+  LOG(("*** New orientation: %d (Camera %d Back %d MountAngle: %d)",
+       mRotation, mCaptureIndex, mBackCamera, mCameraAngle));
+#endif
+}
+
 void
 MediaEngineWebRTCVideoSource::StartImpl(webrtc::CaptureCapability aCapability) {
   MOZ_ASSERT(NS_IsMainThread());
 
   ICameraControl::Configuration config;
   config.mMode = ICameraControl::kPictureMode;
   config.mPreviewSize.width = aCapability.width;
   config.mPreviewSize.height = aCapability.height;
   mCameraControl->Start(&config);
   mCameraControl->Set(CAMERA_PARAM_PICTURESIZE, config.mPreviewSize);
-  mCameraControl->Get(CAMERA_PARAM_SENSORANGLE, mSensorAngle);
-  MOZ_ASSERT(mSensorAngle >= 0 && mSensorAngle < 360);
+
+  hal::RegisterScreenConfigurationObserver(this);
 }
 
 void
 MediaEngineWebRTCVideoSource::StopImpl() {
   MOZ_ASSERT(NS_IsMainThread());
 
+  hal::UnregisterScreenConfigurationObserver(this);
   mCameraControl->Stop();
 }
 
 void
 MediaEngineWebRTCVideoSource::SnapshotImpl() {
   MOZ_ASSERT(NS_IsMainThread());
   mCameraControl->TakePicture();
 }
@@ -558,16 +611,31 @@ MediaEngineWebRTCVideoSource::OnHardware
     // the current state of the camera--normally 'closed'. We only
     // pay attention to that state if we've progressed out of the
     // allocated state.
     if (mState != kAllocated) {
       mState = kReleased;
       mCallbackMonitor.Notify();
     }
   } else {
+    mCameraControl->Get(CAMERA_PARAM_SENSORANGLE, mCameraAngle);
+    MOZ_ASSERT(mCameraAngle == 0 || mCameraAngle == 90 || mCameraAngle == 180 ||
+               mCameraAngle == 270);
+    hal::ScreenConfiguration aConfig;
+    hal::GetCurrentScreenConfiguration(&aConfig);
+
+    nsCString deviceName;
+    ICameraControl::GetCameraName(mCaptureIndex, deviceName);
+    if (deviceName.EqualsASCII("back")) {
+      mBackCamera = true;
+    }
+
+    mRotation = GetRotateAmount(aConfig.orientation(), mCameraAngle, mBackCamera);
+    LOG(("*** Initial orientation: %d (Camera %d Back %d MountAngle: %d)",
+         mRotation, mCaptureIndex, mBackCamera, mCameraAngle));
     mState = kStarted;
     mCallbackMonitor.Notify();
   }
 }
 
 void
 MediaEngineWebRTCVideoSource::OnError(CameraErrorContext aContext, CameraError aError)
 {
@@ -582,49 +650,52 @@ MediaEngineWebRTCVideoSource::OnTakePict
   mLastCapture =
     static_cast<nsIDOMFile*>(new nsDOMMemoryFile(static_cast<void*>(aData),
                                                  static_cast<uint64_t>(aLength),
                                                  aMimeType));
   mCallbackMonitor.Notify();
 }
 
 void
-MediaEngineWebRTCVideoSource::RotateImage(layers::Image* aImage) {
+MediaEngineWebRTCVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) {
   layers::GrallocImage *nativeImage = static_cast<layers::GrallocImage*>(aImage);
   layers::SurfaceDescriptor handle = nativeImage->GetSurfaceDescriptor();
   layers::SurfaceDescriptorGralloc grallocHandle = handle.get_SurfaceDescriptorGralloc();
   android::sp<android::GraphicBuffer> graphicBuffer = layers::GrallocBufferActor::GetFrom(grallocHandle);
   void *pMem = nullptr;
-  uint32_t size = mWidth * mHeight * 3 / 2;
+  uint32_t size = aWidth * aHeight * 3 / 2;
 
   graphicBuffer->lock(android::GraphicBuffer::USAGE_SW_READ_MASK, &pMem);
 
   uint8_t* srcPtr = static_cast<uint8_t*>(pMem);
   // Create a video frame and append it to the track.
   nsRefPtr<layers::Image> image = mImageContainer->CreateImage(ImageFormat::PLANAR_YCBCR);
   layers::PlanarYCbCrImage* videoImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
 
-  uint32_t dstWidth = mWidth;
-  uint32_t dstHeight = mHeight;
+  uint32_t dstWidth;
+  uint32_t dstHeight;
 
-  if (mSensorAngle == 90 || mSensorAngle == 270) {
-    dstWidth = mHeight;
-    dstHeight = mWidth;
+  if (mRotation == 90 || mRotation == 270) {
+    dstWidth = aHeight;
+    dstHeight = aWidth;
+  } else {
+    dstWidth = aWidth;
+    dstHeight = aHeight;
   }
 
   uint32_t half_width = dstWidth / 2;
   uint8_t* dstPtr = videoImage->AllocateAndGetNewBuffer(size);
   libyuv::ConvertToI420(srcPtr, size,
                         dstPtr, dstWidth,
                         dstPtr + (dstWidth * dstHeight), half_width,
                         dstPtr + (dstWidth * dstHeight * 5 / 4), half_width,
                         0, 0,
-                        mWidth, mHeight,
-                        mWidth, mHeight,
-                        static_cast<libyuv::RotationMode>(mSensorAngle),
+                        aWidth, aHeight,
+                        aWidth, aHeight,
+                        static_cast<libyuv::RotationMode>(mRotation),
                         libyuv::FOURCC_NV21);
   graphicBuffer->unlock();
 
   const uint8_t lumaBpp = 8;
   const uint8_t chromaBpp = 4;
 
   layers::PlanarYCbCrData data;
   data.mYChannel = dstPtr;
@@ -646,24 +717,26 @@ MediaEngineWebRTCVideoSource::RotateImag
 }
 
 bool
 MediaEngineWebRTCVideoSource::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) {
   MonitorAutoLock enter(mMonitor);
   if (mState == kStopped) {
     return false;
   }
+  // Bug XXX we'd prefer to avoid converting if mRotation == 0, but that causes problems in UpdateImage()
+  RotateImage(aImage, aWidth, aHeight);
+  if (mRotation != 0 && mRotation != 180) {
+    uint32_t temp = aWidth;
+    aWidth = aHeight;
+    aHeight = temp;
+  }
   if (mWidth != static_cast<int>(aWidth) || mHeight != static_cast<int>(aHeight)) {
     mWidth = aWidth;
     mHeight = aHeight;
     LOG(("Video FrameSizeChange: %ux%u", mWidth, mHeight));
   }
 
-  if (mSensorAngle == 0) {
-    mImage = aImage;
-  } else {
-    RotateImage(aImage);
-  }
   return true; // return true because we're accepting the frame
 }
 #endif
 
 }
--- a/dom/base/nsContentPermissionHelper.cpp
+++ b/dom/base/nsContentPermissionHelper.cpp
@@ -14,16 +14,19 @@
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/PContentPermissionRequestParent.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/unused.h"
 #include "nsComponentManagerUtils.h"
 #include "nsArrayUtils.h"
 #include "nsIMutableArray.h"
 #include "nsContentPermissionHelper.h"
+#include "nsCxPusher.h"
+#include "nsJSUtils.h"
+#include "nsISupportsPrimitives.h"
 
 using mozilla::unused;          // <snicker>
 using namespace mozilla::dom;
 using namespace mozilla;
 
 namespace mozilla {
 namespace dom {
 
@@ -89,20 +92,22 @@ ContentPermissionRequestParent::IsBeingD
   // to send out any message now.
   TabParent* tabParent = static_cast<TabParent*>(Manager());
   return tabParent->IsDestroyed();
 }
 
 NS_IMPL_ISUPPORTS1(ContentPermissionType, nsIContentPermissionType)
 
 ContentPermissionType::ContentPermissionType(const nsACString& aType,
-                                             const nsACString& aAccess)
+                                             const nsACString& aAccess,
+                                             const nsTArray<nsString>& aOptions)
 {
   mType = aType;
   mAccess = aAccess;
+  mOptions = aOptions;
 }
 
 ContentPermissionType::~ContentPermissionType()
 {
 }
 
 NS_IMETHODIMP
 ContentPermissionType::GetType(nsACString& aType)
@@ -113,37 +118,70 @@ ContentPermissionType::GetType(nsACStrin
 
 NS_IMETHODIMP
 ContentPermissionType::GetAccess(nsACString& aAccess)
 {
   aAccess = mAccess;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+ContentPermissionType::GetOptions(nsIArray** aOptions)
+{
+  NS_ENSURE_ARG_POINTER(aOptions);
+
+  *aOptions = nullptr;
+
+  nsresult rv;
+  nsCOMPtr<nsIMutableArray> options =
+    do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // copy options into JS array
+  for (uint32_t i = 0; i < mOptions.Length(); ++i) {
+    nsCOMPtr<nsISupportsString> isupportsString =
+      do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = isupportsString->SetData(mOptions[i]);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = options->AppendElement(isupportsString, false);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  NS_ADDREF(*aOptions = options);
+  return NS_OK;
+}
+
 uint32_t
 ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
                                 nsIMutableArray* aDesArray)
 {
   uint32_t len = aSrcArray.Length();
   for (uint32_t i = 0; i < len; i++) {
     nsRefPtr<ContentPermissionType> cpt =
-      new ContentPermissionType(aSrcArray[i].type(), aSrcArray[i].access());
+      new ContentPermissionType(aSrcArray[i].type(),
+                                aSrcArray[i].access(),
+                                aSrcArray[i].options());
     aDesArray->AppendElement(cpt, false);
   }
   return len;
 }
 
 nsresult
 CreatePermissionArray(const nsACString& aType,
                       const nsACString& aAccess,
+                      const nsTArray<nsString>& aOptions,
                       nsIArray** aTypesArray)
 {
   nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
   nsRefPtr<ContentPermissionType> permType = new ContentPermissionType(aType,
-                                                                       aAccess);
+                                                                       aAccess,
+                                                                       aOptions);
   types->AppendElement(permType, false);
   types.forget(aTypesArray);
 
   return NS_OK;
 }
 
 PContentPermissionRequestParent*
 CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
@@ -243,23 +281,25 @@ nsContentPermissionRequestProxy::Cancel(
   }
 
   // Don't send out the delete message when the managing protocol (PBrowser) is
   // being destroyed and PContentPermissionRequest will soon be.
   if (mParent->IsBeingDestroyed()) {
     return NS_ERROR_FAILURE;
   }
 
-  unused << ContentPermissionRequestParent::Send__delete__(mParent, false);
+  nsTArray<PermissionChoice> emptyChoices;
+
+  unused << ContentPermissionRequestParent::Send__delete__(mParent, false, emptyChoices);
   mParent = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsContentPermissionRequestProxy::Allow()
+nsContentPermissionRequestProxy::Allow(JS::HandleValue aChoices)
 {
   if (mParent == nullptr) {
     return NS_ERROR_FAILURE;
   }
 
   // Don't send out the delete message when the managing protocol (PBrowser) is
   // being destroyed and PContentPermissionRequest will soon be.
   if (mParent->IsBeingDestroyed()) {
@@ -277,12 +317,42 @@ nsContentPermissionRequestProxy::Allow()
     if (mPermissionRequests[i].type().Equals("video-capture")) {
       GonkPermissionService::GetInstance()->addGrantInfo(
         "android.permission.CAMERA",
         static_cast<TabParent*>(mParent->Manager())->Manager()->Pid());
     }
   }
 #endif
 
-  unused << ContentPermissionRequestParent::Send__delete__(mParent, true);
+  nsTArray<PermissionChoice> choices;
+  if (aChoices.isNullOrUndefined()) {
+    // No choice is specified.
+  } else if (aChoices.isObject()) {
+    // Iterate through all permission types.
+    for (uint32_t i = 0; i < mPermissionRequests.Length(); ++i) {
+      nsCString type = mPermissionRequests[i].type();
+
+      mozilla::AutoSafeJSContext cx;
+      JS::Rooted<JSObject*> obj(cx, &aChoices.toObject());
+      JSAutoCompartment ac(cx, obj);
+
+      JS::Rooted<JS::Value> val(cx);
+
+      if (!JS_GetProperty(cx, obj, type.BeginReading(), &val) ||
+          !val.isString()) {
+        // no setting for the permission type, skip it
+      } else {
+        nsDependentJSString choice;
+        if (!choice.init(cx, val)) {
+          return NS_ERROR_FAILURE;
+        }
+        choices.AppendElement(PermissionChoice(type, choice));
+      }
+    }
+  } else {
+    MOZ_ASSERT(false, "SelectedChoices should be undefined or an JS object");
+    return NS_ERROR_FAILURE;
+  }
+
+  unused << ContentPermissionRequestParent::Send__delete__(mParent, true, choices);
   mParent = nullptr;
   return NS_OK;
 }
--- a/dom/base/nsContentPermissionHelper.h
+++ b/dom/base/nsContentPermissionHelper.h
@@ -30,29 +30,33 @@ class ContentPermissionRequestParent;
 class PContentPermissionRequestParent;
 
 class ContentPermissionType : public nsIContentPermissionType
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTPERMISSIONTYPE
 
-  ContentPermissionType(const nsACString& aType, const nsACString& aAccess);
+  ContentPermissionType(const nsACString& aType,
+                        const nsACString& aAccess,
+                        const nsTArray<nsString>& aOptions);
   virtual ~ContentPermissionType();
 
 protected:
   nsCString mType;
   nsCString mAccess;
+  nsTArray<nsString> mOptions;
 };
 
 uint32_t ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
                                          nsIMutableArray* aDesArray);
 
 nsresult CreatePermissionArray(const nsACString& aType,
                                const nsACString& aAccess,
+                               const nsTArray<nsString>& aOptions,
                                nsIArray** aTypesArray);
 
 PContentPermissionRequestParent*
 CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
                                      Element* element,
                                      const IPC::Principal& principal);
 
 } // namespace dom
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -60,22 +60,23 @@
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 #endif
 
 #include "Layers.h"
 #include "mozilla/layers/ShadowLayers.h"
 
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/file/FileHandle.h"
+#include "mozilla/dom/FileHandleBinding.h"
 #include "mozilla/dom/IDBFactoryBinding.h"
 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
 #include "mozilla/dom/quota/PersistenceType.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "nsDOMBlobBuilder.h"
-#include "nsIDOMFileHandle.h"
 #include "nsPrintfCString.h"
 #include "nsViewportInfo.h"
 #include "nsIFormControl.h"
 #include "nsIScriptError.h"
 #include "nsIAppShell.h"
 #include "nsWidgetsCID.h"
 #include "FrameLayerBuilder.h"
 #include "nsDisplayList.h"
@@ -3018,30 +3019,30 @@ nsDOMWindowUtils::GetFileId(JS::Handle<J
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   if (!JSVAL_IS_PRIMITIVE(aFile)) {
     JSObject* obj = JSVAL_TO_OBJECT(aFile);
 
+    file::FileHandle* fileHandle;
+    if (NS_SUCCEEDED(UNWRAP_OBJECT(FileHandle, obj, fileHandle))) {
+      *aResult = fileHandle->GetFileId();
+      return NS_OK;
+    }
+
     nsISupports* nativeObj =
       nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj);
 
     nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(nativeObj);
     if (blob) {
       *aResult = blob->GetFileId();
       return NS_OK;
     }
-
-    nsCOMPtr<nsIDOMFileHandle> fileHandle = do_QueryInterface(nativeObj);
-    if (fileHandle) {
-      *aResult = fileHandle->GetFileId();
-      return NS_OK;
-    }
   }
 
   *aResult = -1;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName, int64_t aId,
--- a/dom/base/nsIScriptGlobalObject.h
+++ b/dom/base/nsIScriptGlobalObject.h
@@ -10,30 +10,36 @@
 #include "nsISupports.h"
 #include "nsIGlobalObject.h"
 #include "js/TypeDecls.h"
 #include "mozilla/EventForwards.h"
 
 class nsIScriptContext;
 class nsIScriptGlobalObject;
 
+namespace mozilla {
+namespace dom {
+struct ErrorEventInit;
+} // namespace dom
+} // namespace mozilla
+
 // A helper function for nsIScriptGlobalObject implementations to use
 // when handling a script error.  Generally called by the global when a context
 // notifies it of an error via nsIScriptGlobalObject::HandleScriptError.
 // Returns true if HandleDOMEvent was actually called, in which case
 // aStatus will be filled in with the status.
 bool
 NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
-                     mozilla::InternalScriptErrorEvent *aErrorEvent,
+                     const mozilla::dom::ErrorEventInit &aErrorEvent,
                      nsEventStatus *aStatus);
 
 
 #define NS_ISCRIPTGLOBALOBJECT_IID \
-{ 0x30c64680, 0x909a, 0x4435, \
-  { 0x90, 0x3b, 0x29, 0x3e, 0xb5, 0x5d, 0xc7, 0xa0 } }
+{ 0x6995e1ff, 0x9fc5, 0x44a7, \
+ { 0xbd, 0x7c, 0xe7, 0xcd, 0x44, 0x47, 0x22, 0x87 } }
 
 /**
  * The global object which keeps a script context for each supported script
  * language. This often used to store per-window global state.
  * This is a heavyweight interface implemented only by DOM globals, and
  * it might go away some time in the future.
  */
 
@@ -69,19 +75,19 @@ public:
    * same object the global is using for a global for that language.
    */
   virtual void OnFinalize(JSObject* aObject) = 0;
 
   /**
    * Handle a script error.  Generally called by a script context.
    */
   virtual nsresult HandleScriptError(
-                     mozilla::InternalScriptErrorEvent *aErrorEvent,
+                     const mozilla::dom::ErrorEventInit &aErrorEventInit,
                      nsEventStatus *aEventStatus) {
-    NS_ENSURE_STATE(NS_HandleScriptError(this, aErrorEvent, aEventStatus));
+    NS_ENSURE_STATE(NS_HandleScriptError(this, aErrorEventInit, aEventStatus));
     return NS_OK;
   }
 
   virtual bool IsBlackForCC(bool aTracingNeeded = true) { return false; }
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptGlobalObject,
                               NS_ISCRIPTGLOBALOBJECT_IID)
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -47,16 +47,18 @@
 #include "nsIArray.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "prmem.h"
 #include "WrapperFactory.h"
 #include "nsGlobalWindow.h"
 #include "nsScriptNameSpaceManager.h"
 #include "StructuredCloneTags.h"
+#include "mozilla/AutoRestore.h"
+#include "mozilla/dom/ErrorEvent.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/ImageDataBinding.h"
 #include "nsAXPCNativeCallContext.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 
 #include "nsJSPrincipals.h"
 
 #ifdef XP_MACOSX
@@ -307,34 +309,40 @@ private:
 };
 
 // A utility function for script languages to call.  Although it looks small,
 // the use of nsIDocShell and nsPresContext triggers a huge number of
 // dependencies that most languages would not otherwise need.
 // XXXmarkh - This function is mis-placed!
 bool
 NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
-                     InternalScriptErrorEvent *aErrorEvent,
+                     const ErrorEventInit &aErrorEventInit,
                      nsEventStatus *aStatus)
 {
   bool called = false;
   nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aScriptGlobal));
   nsIDocShell *docShell = win ? win->GetDocShell() : nullptr;
   if (docShell) {
     nsRefPtr<nsPresContext> presContext;
     docShell->GetPresContext(getter_AddRefs(presContext));
 
     static int32_t errorDepth; // Recursion prevention
     ++errorDepth;
 
-    if (presContext && errorDepth < 2) {
+    if (errorDepth < 2) {
       // Dispatch() must be synchronous for the recursion block
       // (errorDepth) to work.
-      nsEventDispatcher::Dispatch(win, presContext, aErrorEvent, nullptr,
-                                  aStatus);
+      nsRefPtr<ErrorEvent> event =
+        ErrorEvent::Constructor(static_cast<nsGlobalWindow*>(win.get()),
+                                NS_LITERAL_STRING("error"),
+                                aErrorEventInit);
+      event->SetTrusted(true);
+
+      nsEventDispatcher::DispatchDOMEvent(win, nullptr, event, presContext,
+                                          aStatus);
       called = true;
     }
     --errorDepth;
   }
   return called;
 }
 
 namespace mozilla {
@@ -439,54 +447,57 @@ public:
     nsEventStatus status = nsEventStatus_eIgnore;
     // First, notify the DOM that we have a script error.
     if (mDispatchEvent) {
       nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(mScriptGlobal));
       nsIDocShell* docShell = win ? win->GetDocShell() : nullptr;
       if (docShell &&
           !JSREPORT_IS_WARNING(mFlags) &&
           !sHandlingScriptError) {
-        sHandlingScriptError = true; // Recursion prevention
+        AutoRestore<bool> recursionGuard(sHandlingScriptError);
+        sHandlingScriptError = true;
 
         nsRefPtr<nsPresContext> presContext;
         docShell->GetPresContext(getter_AddRefs(presContext));
 
-        if (presContext) {
-          InternalScriptErrorEvent errorevent(true, NS_LOAD_ERROR);
-
-          errorevent.fileName = mFileName.get();
-
-          nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
-          NS_ENSURE_STATE(sop);
-          nsIPrincipal* p = sop->GetPrincipal();
-          NS_ENSURE_STATE(p);
-
-          bool sameOrigin = !mOriginPrincipal;
-
-          if (p && !sameOrigin) {
-            if (NS_FAILED(p->Subsumes(mOriginPrincipal, &sameOrigin))) {
-              sameOrigin = false;
-            }
+        ErrorEventInit init;
+        init.mCancelable = true;
+        init.mFilename = mFileName;
+        init.mBubbles = true;
+
+        nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
+        NS_ENSURE_STATE(sop);
+        nsIPrincipal* p = sop->GetPrincipal();
+        NS_ENSURE_STATE(p);
+
+        bool sameOrigin = !mOriginPrincipal;
+
+        if (p && !sameOrigin) {
+          if (NS_FAILED(p->Subsumes(mOriginPrincipal, &sameOrigin))) {
+            sameOrigin = false;
           }
-
-          NS_NAMED_LITERAL_STRING(xoriginMsg, "Script error.");
-          if (sameOrigin) {
-            errorevent.errorMsg = mErrorMsg.get();
-            errorevent.lineNr = mLineNumber;
-          } else {
-            NS_WARNING("Not same origin error!");
-            errorevent.errorMsg = xoriginMsg.get();
-            errorevent.lineNr = 0;
-          }
-
-          nsEventDispatcher::Dispatch(win, presContext, &errorevent, nullptr,
-                                      &status);
         }
 
-        sHandlingScriptError = false;
+        NS_NAMED_LITERAL_STRING(xoriginMsg, "Script error.");
+        if (sameOrigin) {
+          init.mMessage = mErrorMsg;
+          init.mLineno = mLineNumber;
+        } else {
+          NS_WARNING("Not same origin error!");
+          init.mMessage = xoriginMsg;
+          init.mLineno = 0;
+        }
+
+        nsRefPtr<ErrorEvent> event =
+          ErrorEvent::Constructor(static_cast<nsGlobalWindow*>(win.get()),
+                                  NS_LITERAL_STRING("error"), init);
+        event->SetTrusted(true);
+
+        nsEventDispatcher::DispatchDOMEvent(win, nullptr, event, presContext,
+                                            &status);
       }
     }
 
     if (status != nsEventStatus_eConsumeNoDefault) {
       AsyncErrorReporter::ReportError();
     }
 
     return NS_OK;
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -11987,19 +11987,27 @@ class CGEventClass(CGBindingImplClass):
             "  ${nativeType}(mozilla::dom::EventTarget* aOwner);\n\n")
 
         baseDeclarations = string.Template(baseDeclarations).substitute(
             {
               "nativeType": self.descriptor.nativeType.split('::')[-1],
               "parentType": self.parentType
             })
 
-        CGClass.__init__(self, descriptor.nativeType.split('::')[-1],
+        className = descriptor.nativeType.split('::')[-1]
+        asConcreteTypeMethod = ClassMethod("As%s" % className,
+                                           "%s*" % className,
+                                           [],
+                                           virtual=True,
+                                           body="return this;",
+                                           breakAfterReturnDecl=" ")
+
+        CGClass.__init__(self, className,
                          bases=[ClassBase(self.parentType)],
-                         methods=self.methodDecls,
+                         methods=[asConcreteTypeMethod]+self.methodDecls,
                          members=members,
                          extradeclarations=baseDeclarations)
 
     def getWrapObjectBody(self):
         return "return %sBinding::Wrap(aCx, aScope, this);" % self.descriptor.name
 
     def implTraverse(self):
         retVal = ""
--- a/dom/bluetooth/BluetoothHidManager.h
+++ b/dom/bluetooth/BluetoothHidManager.h
@@ -11,18 +11,16 @@
 #include "BluetoothProfileController.h"
 #include "BluetoothProfileManagerBase.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothHidManager : public BluetoothProfileManagerBase
 {
 public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
   BT_DECL_PROFILE_MGR_BASE
   virtual void GetName(nsACString& aName)
   {
     aName.AssignLiteral("HID");
   }
 
   static BluetoothHidManager* Get();
   virtual ~BluetoothHidManager();
--- a/dom/bluetooth/BluetoothProfileManagerBase.h
+++ b/dom/bluetooth/BluetoothProfileManagerBase.h
@@ -67,16 +67,18 @@ public:
   /**
    * Returns string of profile name
    */
   virtual void GetName(nsACString& aName) = 0;
 };
 
 #define BT_DECL_PROFILE_MGR_BASE                                                 \
 public:                                                                          \
+  NS_DECL_ISUPPORTS                                                              \
+  NS_DECL_NSIOBSERVER                                                            \
   virtual void OnGetServiceChannel(const nsAString& aDeviceAddress,              \
                                    const nsAString& aServiceUuid,                \
                                    int aChannel) MOZ_OVERRIDE;                   \
   virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) MOZ_OVERRIDE; \
   virtual void GetAddress(nsAString& aDeviceAddress) MOZ_OVERRIDE;               \
   virtual bool IsConnected() MOZ_OVERRIDE;                                       \
   virtual void Connect(const nsAString& aDeviceAddress,                          \
                        BluetoothProfileController* aController) MOZ_OVERRIDE;    \
--- a/dom/bluetooth/BluetoothService.cpp
+++ b/dom/bluetooth/BluetoothService.cpp
@@ -542,17 +542,17 @@ BluetoothService::SetEnabled(bool aEnabl
       RemoveObserversExceptBluetoothManager, nullptr);
   }
 
   /**
    * mEnabled: real status of bluetooth
    * aEnabled: expected status of bluetooth
    */
   if (mEnabled == aEnabled) {
-    BT_WARNING("Bluetooth has already been enabled/disabled before"
+    BT_WARNING("Bluetooth has already been enabled/disabled before "
                "or the toggling is failed.");
   }
 
   mEnabled = aEnabled;
 }
 
 nsresult
 BluetoothService::HandleStartup()
--- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.h
+++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.h
@@ -10,18 +10,16 @@
 #include "BluetoothCommon.h"
 #include "BluetoothProfileController.h"
 #include "BluetoothProfileManagerBase.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 class BluetoothA2dpManager : public BluetoothProfileManagerBase
 {
 public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
   BT_DECL_PROFILE_MGR_BASE
   virtual void GetName(nsACString& aName)
   {
     aName.AssignLiteral("A2DP");
   }
 
   enum SinkState {
     SINK_UNKNOWN,
--- a/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
@@ -1459,17 +1459,17 @@ BluetoothOppManager::OnSocketConnectErro
 void
 BluetoothOppManager::OnSocketDisconnect(BluetoothSocket* aSocket)
 {
   MOZ_ASSERT(aSocket);
   if (aSocket != mSocket) {
     // Do nothing when a listening server socket is closed.
     return;
   }
-  BT_LOGR("[%s]", (mIsServer) ? "client" : "server");
+  BT_LOGR("[%s]", (mIsServer) ? "server" : "client");
 
   /**
    * It is valid for a bluetooth device which is transfering file via OPP
    * closing socket without sending OBEX disconnect request first. So we
    * delete the broken file when we failed to receive a file from the remote,
    * and notify the transfer has been completed (but failed). We also call
    * AfterOppDisconnected here to ensure all variables will be cleaned.
    */
--- a/dom/bluetooth/bluedroid/BluetoothOppManager.h
+++ b/dom/bluetooth/bluedroid/BluetoothOppManager.h
@@ -24,18 +24,16 @@ BEGIN_BLUETOOTH_NAMESPACE
 class BluetoothSocket;
 class ObexHeaderSet;
 class SendFileBatch;
 
 class BluetoothOppManager : public BluetoothSocketObserver
                           , public BluetoothProfileManagerBase
 {
 public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
   BT_DECL_PROFILE_MGR_BASE
   virtual void GetName(nsACString& aName)
   {
     aName.AssignLiteral("OPP");
   }
 
   static const int MAX_PACKET_LENGTH = 0xFFFE;
 
rename from dom/bluetooth/bluedroid/gonk/BluetoothServiceBluedroid.cpp
rename to dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
rename from dom/bluetooth/bluedroid/gonk/BluetoothServiceBluedroid.h
rename to dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/bluedroid/hfp-fallback/BluetoothHfpManager.cpp
@@ -0,0 +1,183 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "base/basictypes.h"
+#include "BluetoothHfpManager.h"
+#include "BluetoothProfileController.h"
+#include "mozilla/Services.h"
+#include "mozilla/StaticPtr.h"
+#include "nsIObserverService.h"
+#include "nsThreadUtils.h"
+
+using namespace mozilla;
+USING_BLUETOOTH_NAMESPACE
+
+namespace {
+  StaticRefPtr<BluetoothHfpManager> sBluetoothHfpManager;
+  bool sInShutdown = false;
+} // anonymous namespace
+
+/**
+ * nsIObserver function
+ */
+NS_IMETHODIMP
+BluetoothHfpManager::Observe(nsISupports* aSubject,
+                             const char* aTopic,
+                             const char16_t* aData)
+{
+  if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
+    HandleShutdown();
+  } else {
+    MOZ_ASSERT(false, "BluetoothHfpManager got unexpected topic!");
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  return NS_OK;
+}
+
+/**
+ * BluetoothProfileManagerBase functions
+ */
+void
+BluetoothHfpManager::Connect(const nsAString& aDeviceAddress,
+                             BluetoothProfileController* aController)
+{
+  MOZ_ASSERT(aController);
+
+  aController->OnConnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
+}
+
+void
+BluetoothHfpManager::Disconnect(BluetoothProfileController* aController)
+{
+  MOZ_ASSERT(aController);
+
+  aController->OnDisconnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
+}
+
+bool
+BluetoothHfpManager::IsConnected()
+{
+  return false;
+}
+
+void
+BluetoothHfpManager::OnConnect(const nsAString& aErrorStr)
+{
+  MOZ_ASSERT(false);
+}
+
+void
+BluetoothHfpManager::OnDisconnect(const nsAString& aErrorStr)
+{
+  MOZ_ASSERT(false);
+}
+
+void
+BluetoothHfpManager::GetAddress(nsAString& aDeviceAddress)
+{
+  aDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
+}
+
+void
+BluetoothHfpManager::OnGetServiceChannel(const nsAString& aDeviceAddress,
+                                         const nsAString& aServiceUuid,
+                                         int aChannel)
+{
+  MOZ_ASSERT(false);
+}
+
+void
+BluetoothHfpManager::OnUpdateSdpRecords(const nsAString& aDeviceAddress)
+{
+  MOZ_ASSERT(false);
+}
+
+/**
+ * BluetoothHfpManagerBase function
+ */
+bool
+BluetoothHfpManager::IsScoConnected()
+{
+  return false;
+}
+
+/**
+ * Non-inherited functions
+ */
+// static
+BluetoothHfpManager*
+BluetoothHfpManager::Get()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // If sBluetoothHfpManager already exists, exit early
+  if (sBluetoothHfpManager) {
+    return sBluetoothHfpManager;
+  }
+
+  // If we're in shutdown, don't create a new instance
+  NS_ENSURE_FALSE(sInShutdown, nullptr);
+
+  // Create a new instance and return
+  BluetoothHfpManager* manager = new BluetoothHfpManager();
+  NS_ENSURE_TRUE(manager->Init(), nullptr);
+
+  sBluetoothHfpManager = manager;
+  return sBluetoothHfpManager;
+}
+
+bool
+BluetoothHfpManager::Init()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  NS_ENSURE_TRUE(obs, false);
+
+  if (NS_FAILED(obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false))) {
+    BT_WARNING("Failed to add observers!");
+    return false;
+  }
+
+  return true;
+}
+
+void
+BluetoothHfpManager::HandleShutdown()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  sInShutdown = true;
+  sBluetoothHfpManager = nullptr;
+}
+
+bool
+BluetoothHfpManager::ConnectSco()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  /**
+   * TODO:
+   *   Implement ConnectSco() for applications that want to create SCO link
+   *   without a HFP connection (e.g., VoIP).
+   */
+  return false;
+}
+
+bool
+BluetoothHfpManager::DisconnectSco()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  /**
+   * TODO:
+   *   Implement DisconnectSco() for applications that want to destroy SCO link
+   *   without a HFP connection (e.g., VoIP).
+   */
+  return false;
+}
+
+NS_IMPL_ISUPPORTS1(BluetoothHfpManager, nsIObserver)
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/bluedroid/hfp-fallback/BluetoothHfpManager.h
@@ -0,0 +1,45 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_bluetooth_bluetoothhfpmanager_h__
+#define mozilla_dom_bluetooth_bluetoothhfpmanager_h__
+
+#include "BluetoothHfpManagerBase.h"
+
+/**
+ * Fallback BluetoothHfpManager is built for non-phone devices (e.g., tablets).
+ * These devices has no radio interface and the build flag MOZ_B2G_RIL is
+ * disabled. To prevent build breaks of accessing radio interface, we implement
+ * fallback BluetoothHfpManager with empty functions to keep original
+ * BluetoothHfpManager away from numerous #ifdef/#endif statements.
+ */
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothHfpManager : public BluetoothHfpManagerBase
+{
+public:
+  BT_DECL_HFP_MGR_BASE
+  virtual void GetName(nsACString& aName)
+  {
+    aName.AssignLiteral("Fallback HFP/HSP");
+  }
+
+  static BluetoothHfpManager* Get();
+  virtual ~BluetoothHfpManager() { }
+
+  bool ConnectSco();
+  bool DisconnectSco();
+
+private:
+  BluetoothHfpManager() { }
+  bool Init();
+  void HandleShutdown();
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
rename from dom/bluetooth/bluedroid/BluetoothHfpManager.cpp
rename to dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
rename from dom/bluetooth/bluedroid/BluetoothHfpManager.h
rename to dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
--- a/dom/bluetooth/bluedroid/BluetoothHfpManager.h
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
@@ -70,18 +70,16 @@ public:
   bthf_call_direction_t mDirection; // 0: outgoing call; 1: incoming call
   bthf_call_addrtype_t mType;
 };
 
 class BluetoothHfpManager : public BluetoothHfpManagerBase
                           , public BatteryObserver
 {
 public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
   BT_DECL_HFP_MGR_BASE
   virtual void GetName(nsACString& aName)
   {
     aName.AssignLiteral("HFP/HSP");
   }
 
   static BluetoothHfpManager* Get();
   virtual ~BluetoothHfpManager();
--- a/dom/bluetooth/bluez/BluetoothA2dpManager.h
+++ b/dom/bluetooth/bluez/BluetoothA2dpManager.h
@@ -11,18 +11,16 @@
 #include "BluetoothProfileController.h"
 #include "BluetoothProfileManagerBase.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothA2dpManager : public BluetoothProfileManagerBase
 {
 public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
   BT_DECL_PROFILE_MGR_BASE
   virtual void GetName(nsACString& aName)
   {
     aName.AssignLiteral("A2DP");
   }
 
   enum SinkState {
     SINK_UNKNOWN,
rename from dom/bluetooth/bluez/linux/BluetoothDBusService.cpp
rename to dom/bluetooth/bluez/BluetoothDBusService.cpp
rename from dom/bluetooth/bluez/linux/BluetoothDBusService.h
rename to dom/bluetooth/bluez/BluetoothDBusService.h
--- a/dom/bluetooth/bluez/BluetoothHfpManager.h
+++ b/dom/bluetooth/bluez/BluetoothHfpManager.h
@@ -74,18 +74,16 @@ public:
 };
 #endif // MOZ_B2G_RIL
 
 class BluetoothHfpManager : public BluetoothSocketObserver
                           , public BluetoothHfpManagerBase
                           , public BatteryObserver
 {
 public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
   BT_DECL_HFP_MGR_BASE
   virtual void GetName(nsACString& aName)
   {
     aName.AssignLiteral("HFP/HSP");
   }
 
   static BluetoothHfpManager* Get();
   ~BluetoothHfpManager();
--- a/dom/bluetooth/bluez/BluetoothOppManager.h
+++ b/dom/bluetooth/bluez/BluetoothOppManager.h
@@ -24,18 +24,16 @@ BEGIN_BLUETOOTH_NAMESPACE
 class BluetoothSocket;
 class ObexHeaderSet;
 class SendFileBatch;
 
 class BluetoothOppManager : public BluetoothSocketObserver
                           , public BluetoothProfileManagerBase
 {
 public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
   BT_DECL_PROFILE_MGR_BASE
   virtual void GetName(nsACString& aName)
   {
     aName.AssignLiteral("OPP");
   }
 
   static const int MAX_PACKET_LENGTH = 0xFFFE;
 
--- a/dom/bluetooth/moz.build
+++ b/dom/bluetooth/moz.build
@@ -25,50 +25,62 @@ if CONFIG['MOZ_B2G_BT']:
         SOURCES += [
             'BluetoothRilListener.cpp',
         ]
 
     if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
         if CONFIG['MOZ_B2G_BT_BLUEZ']:
             SOURCES += [
                 'bluez/BluetoothA2dpManager.cpp',
+                'bluez/BluetoothDBusService.cpp',
                 'bluez/BluetoothHfpManager.cpp',
                 'bluez/BluetoothOppManager.cpp',
                 'bluez/BluetoothSocket.cpp',
                 'bluez/BluetoothUnixSocketConnector.cpp',
                 'bluez/BluetoothUtils.cpp',
-                'bluez/linux/BluetoothDBusService.cpp',
             ]
             LOCAL_INCLUDES += [
                 'bluez',
-                'bluez/linux',
             ]
             DEFINES['MOZ_B2G_BT_BLUEZ'] = True
         elif CONFIG['MOZ_B2G_BT_BLUEDROID']:
             SOURCES += [
                 'bluedroid/BluetoothA2dpManager.cpp',
-                'bluedroid/BluetoothHfpManager.cpp',
                 'bluedroid/BluetoothOppManager.cpp',
+                'bluedroid/BluetoothServiceBluedroid.cpp',
                 'bluedroid/BluetoothSocket.cpp',
                 'bluedroid/BluetoothUtils.cpp',
-                'bluedroid/gonk/BluetoothServiceBluedroid.cpp',
             ]
             LOCAL_INCLUDES += [
                 'bluedroid',
-                'bluedroid/gonk',
             ]
+
+            if CONFIG['MOZ_B2G_RIL']:
+                SOURCES += [
+                    'bluedroid/hfp/BluetoothHfpManager.cpp',
+                ]
+                LOCAL_INCLUDES += [
+                    'bluedroid/hfp',
+                ]
+            else:
+                SOURCES += [
+                    'bluedroid/hfp-fallback/BluetoothHfpManager.cpp',
+                ]
+                LOCAL_INCLUDES += [
+                    'bluedroid/hfp-fallback',
+                ]
+
             DEFINES['MOZ_B2G_BT_BLUEDROID'] = True
     elif CONFIG['MOZ_ENABLE_DBUS']:
         SOURCES += [
+            'bluez/BluetoothDBusService.cpp',
             'bluez/BluetoothHfpManager.cpp',
-            'bluez/linux/BluetoothDBusService.cpp',
         ]
         LOCAL_INCLUDES += [
             'bluez',
-            'bluez/linux',
         ]
         DEFINES['MOZ_BLUETOOTH_DBUS'] = True
         DEFINES['HAVE_PTHREADS'] = True
 
     FINAL_LIBRARY = 'gklayout'
 
     LOCAL_INCLUDES += [
         'ipc',
--- a/dom/browser-element/mochitest/browserElement_OpenMixedProcess.js
+++ b/dom/browser-element/mochitest/browserElement_OpenMixedProcess.js
@@ -50,17 +50,17 @@ function runTest() {
     }
     else if (e.detail.message.startsWith('fail')) {
       ok(false, e.detail.message);
     }
     else if (e.detail.message == 'finish') {
       // We assume here that iframe is completely blank, and spin until popup's
       // screenshot is not the same as iframe.
       iframe.getScreenshot(1000, 1000).onsuccess = function(e) {
-        var fr = FileReader();
+        var fr = new FileReader();
         fr.onloadend = function() { test2(popup, fr.result); };
         fr.readAsArrayBuffer(e.target.result);
       };
     }
     else {
       ok(false, e.detail.message, "Unexpected message!");
     }
   });
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -591,19 +591,22 @@ nsGonkCameraControl::SetThumbnailSizeImp
          supportedSizes[i].height == mLastPictureSize.width
     ) {
       smallestDelta = delta;
       smallestDeltaIndex = i;
     }
   }
 
   if (smallestDeltaIndex == UINT32_MAX) {
-    DOM_CAMERA_LOGW("Unable to find a thumbnail size close to %ux%u\n",
+    DOM_CAMERA_LOGW("Unable to find a thumbnail size close to %ux%u, disabling thumbnail\n",
       aSize.width, aSize.height);
-    return NS_ERROR_INVALID_ARG;
+    // If we are unable to find a thumbnail size with a suitable aspect ratio,
+    // just disable the thumbnail altogether.
+    Size size = { 0, 0 };
+    return SetAndPush(CAMERA_PARAM_THUMBNAILSIZE, size);
   }
 
   Size size = supportedSizes[smallestDeltaIndex];
   DOM_CAMERA_LOGI("camera-param set thumbnail-size = %ux%u (requested %ux%u)\n",
     size.width, size.height, aSize.width, aSize.height);
   if (size.width > INT32_MAX || size.height > INT32_MAX) {
     DOM_CAMERA_LOGE("Supported thumbnail size is too big, no change\n");
     return NS_ERROR_FAILURE;
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -1569,20 +1569,22 @@ public:
 
   NS_FORWARD_NSICONTENTPERMISSIONREQUEST(mCursor->);
 
   DeviceStorageCursorRequest(nsDOMDeviceStorageCursor* aCursor)
     : mCursor(aCursor) { }
 
   ~DeviceStorageCursorRequest() {}
 
-  bool Recv__delete__(const bool& allow)
+  bool Recv__delete__(const bool& allow,
+                      const InfallibleTArray<PermissionChoice>& choices)
   {
+    MOZ_ASSERT(choices.IsEmpty(), "DeviceStorageCursor doesn't support permission choice");
     if (allow) {
-      Allow();
+      Allow(JS::UndefinedHandleValue);
     }
     else {
       Cancel();
     }
     return true;
   }
 
   void IPDLRelease()
@@ -1808,17 +1810,21 @@ nsDOMDeviceStorageCursor::GetStorageType
 NS_IMETHODIMP
 nsDOMDeviceStorageCursor::GetTypes(nsIArray** aTypes)
 {
   nsCString type;
   nsresult rv =
     DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return CreatePermissionArray(type, NS_LITERAL_CSTRING("read"), aTypes);
+  nsTArray<nsString> emptyOptions;
+  return CreatePermissionArray(type,
+                               NS_LITERAL_CSTRING("read"),
+                               emptyOptions,
+                               aTypes);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorageCursor::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
 {
   NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
   return NS_OK;
 }
@@ -1841,18 +1847,20 @@ NS_IMETHODIMP
 nsDOMDeviceStorageCursor::Cancel()
 {
   nsCOMPtr<PostErrorEvent> event
     = new PostErrorEvent(this, POST_ERROR_EVENT_PERMISSION_DENIED);
   return NS_DispatchToMainThread(event);
 }
 
 NS_IMETHODIMP
-nsDOMDeviceStorageCursor::Allow()
+nsDOMDeviceStorageCursor::Allow(JS::HandleValue aChoices)
 {
+  MOZ_ASSERT(aChoices.isUndefined());
+
   if (!mFile->IsSafePath()) {
     nsCOMPtr<nsIRunnable> r
       = new PostErrorEvent(this, POST_ERROR_EVENT_PERMISSION_DENIED);
     return NS_DispatchToMainThread(r);
   }
 
   if (XRE_GetProcessType() != GeckoProcessType_Default) {
     PDeviceStorageRequestChild* child
@@ -1892,20 +1900,23 @@ nsDOMDeviceStorageCursor::Continue(Error
 
   nsCOMPtr<ContinueCursorEvent> event = new ContinueCursorEvent(this);
   event->Continue();
 
   mOkToCallContinue = false;
 }
 
 bool
-nsDOMDeviceStorageCursor::Recv__delete__(const bool& allow)
+nsDOMDeviceStorageCursor::Recv__delete__(const bool& allow,
+                                         const InfallibleTArray<PermissionChoice>& choices)
 {
+  MOZ_ASSERT(choices.IsEmpty(), "DeviceStorageCursor doesn't support permission choice");
+
   if (allow) {
-    Allow();
+    Allow(JS::UndefinedHandleValue);
   }
   else {
     Cancel();
   }
   return true;
 }
 
 void
@@ -2417,17 +2428,17 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DeviceStorageRequest,
                                            nsIContentPermissionRequest)
 
   NS_IMETHOD Run() {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) {
-      Allow();
+      Allow(JS::UndefinedHandleValue);
       return NS_OK;
     }
 
     if (XRE_GetProcessType() == GeckoProcessType_Content) {
 
       // because owner implements nsITabChild, we can assume that it is
       // the one and only TabChild.
       TabChild* child = TabChild::GetFrom(mWindow->GetDocShell());
@@ -2448,17 +2459,18 @@ public:
       }
       nsCString access;
       rv = DeviceStorageTypeChecker::GetAccessForRequest(
         DeviceStorageRequestType(mRequestType), access);
       if (NS_FAILED(rv)) {
         return rv;
       }
       nsTArray<PermissionRequest> permArray;
-      permArray.AppendElement(PermissionRequest(type, access));
+      nsTArray<nsString> emptyOptions;
+      permArray.AppendElement(PermissionRequest(type, access, emptyOptions));
       child->SendPContentPermissionRequestConstructor(
         this, permArray, IPC::Principal(mPrincipal));
 
       Sendprompt();
       return NS_OK;
     }
 
     nsCOMPtr<nsIContentPermissionPrompt> prompt
@@ -2480,17 +2492,18 @@ public:
 
     nsCString access;
     rv = DeviceStorageTypeChecker::GetAccessForRequest(
       DeviceStorageRequestType(mRequestType), access);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
-    return CreatePermissionArray(type, access, aTypes);
+    nsTArray<nsString> emptyOptions;
+    return CreatePermissionArray(type, access, emptyOptions, aTypes);
   }
 
   NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
   {
     NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
     return NS_OK;
   }
 
@@ -2509,19 +2522,20 @@ public:
   NS_IMETHOD Cancel()
   {
     nsCOMPtr<PostErrorEvent> event
       = new PostErrorEvent(mRequest.forget(),
                            POST_ERROR_EVENT_PERMISSION_DENIED);
     return NS_DispatchToMainThread(event);
   }
 
-  NS_IMETHOD Allow()
+  NS_IMETHOD Allow(JS::HandleValue aChoices)
   {
     MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(aChoices.isUndefined());
 
     if (!mRequest) {
       return NS_ERROR_FAILURE;
     }
 
     nsCOMPtr<nsIRunnable> r;
 
     switch(mRequestType) {
@@ -2767,20 +2781,23 @@ public:
         = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
       MOZ_ASSERT(target);
       target->Dispatch(r, NS_DISPATCH_NORMAL);
     }
 
     return NS_OK;
   }
 
-  bool Recv__delete__(const bool& allow)
+  bool Recv__delete__(const bool& allow,
+                      const InfallibleTArray<PermissionChoice>& choices)
   {
+    MOZ_ASSERT(choices.IsEmpty(), "DeviceStorage doesn't support permission choice");
+
     if (allow) {
-      Allow();
+      Allow(JS::UndefinedHandleValue);
     }
     else {
       Cancel();
     }
     return true;
   }
 
   void IPDLRelease()
@@ -3636,17 +3653,17 @@ nsDOMDeviceStorage::EnumerateInternal(co
   dsf->SetEditable(aEditable);
 
   nsRefPtr<nsDOMDeviceStorageCursor> cursor
     = new nsDOMDeviceStorageCursor(win, mPrincipal, dsf, since);
   nsRefPtr<DeviceStorageCursorRequest> r
     = new DeviceStorageCursorRequest(cursor);
 
   if (mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) {
-    r->Allow();
+    r->Allow(JS::UndefinedHandleValue);
     return cursor.forget();
   }
 
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     // because owner implements nsITabChild, we can assume that it is
     // the one and only TabChild.
     TabChild* child = TabChild::GetFrom(win->GetDocShell());
     if (!child) {
@@ -3658,17 +3675,20 @@ nsDOMDeviceStorage::EnumerateInternal(co
     r->AddRef();
 
     nsCString type;
     aRv = DeviceStorageTypeChecker::GetPermissionForType(mStorageType, type);
     if (aRv.Failed()) {
       return nullptr;
     }
     nsTArray<PermissionRequest> permArray;
-    permArray.AppendElement(PermissionRequest(type, NS_LITERAL_CSTRING("read")));
+    nsTArray<nsString> emptyOptions;
+    permArray.AppendElement(PermissionRequest(type,
+                                              NS_LITERAL_CSTRING("read"),
+                                              emptyOptions));
     child->SendPContentPermissionRequestConstructor(r,
                                                     permArray,
                                                     IPC::Principal(mPrincipal));
 
     r->Sendprompt();
 
     return cursor.forget();
   }
--- a/dom/devicestorage/nsDeviceStorage.h
+++ b/dom/devicestorage/nsDeviceStorage.h
@@ -199,17 +199,18 @@ public:
                            DeviceStorageFile* aFile,
                            PRTime aSince);
 
 
   nsTArray<nsRefPtr<DeviceStorageFile> > mFiles;
   bool mOkToCallContinue;
   PRTime mSince;
 
-  virtual bool Recv__delete__(const bool& allow) MOZ_OVERRIDE;
+  virtual bool Recv__delete__(const bool& allow,
+                              const InfallibleTArray<PermissionChoice>& choices) MOZ_OVERRIDE;
   virtual void IPDLRelease() MOZ_OVERRIDE;
 
   void GetStorageType(nsAString & aType);
 
   void RequestComplete() MOZ_OVERRIDE;
 
 private:
   ~nsDOMDeviceStorageCursor();
--- a/dom/encoding/test/test_BOMEncoding.js
+++ b/dom/encoding/test/test_BOMEncoding.js
@@ -111,18 +111,18 @@ function testMoreBOMEncoding() {
                   msg: "test decoder encoding provided with invalid BOM encoding for greek."});
 }
 
 function testBOMCharset(test)
 {
   var outText;
   try {
     var decoder = 'fatal' in test ?
-      TextDecoder(test.encoding, {fatal: test.fatal}) :
-      TextDecoder(test.encoding);
+      new TextDecoder(test.encoding, {fatal: test.fatal}) :
+      new TextDecoder(test.encoding);
     outText = decoder.decode(new Uint8Array(test.data));
   } catch (e) {
     assert_equals(e.name, test.error, test.msg);
     return;
   }
   assert_true(!test.error, test.msg);
 
   if (outText !== test.expected) {
--- a/dom/encoding/test/test_TextDecoder.js
+++ b/dom/encoding/test/test_TextDecoder.js
@@ -353,33 +353,33 @@ function testDecoderGetEncoding()
     {encoding: "utf-16be", labels: ["utf-16be"]},
     {encoding: "x-user-defined", labels: ["x-user-defined"]},
     {error: "TypeError", labels: ["x-windows-949", "\u0130SO-8859-1", "csiso2022kr", "iso-2022-kr", "iso-2022-cn", "iso-2022-cn-ext", "replacement"]},
   ];
 
   for (var le of labelEncodings) {
     for (var label of le.labels) {
       try {
-        var decoder = TextDecoder(label);
+        var decoder = new TextDecoder(label);
       } catch (e) {
         assert_true(!!le.error, label + " shoud not throw " + e.name);
         assert_equals(e.name, le.error, label + " label encoding unsupported test.");
         continue;
       }
       assert_true(!le.error, label + " shoud throw " + le.error);
       assert_equals(decoder.encoding, le.encoding, label + " label encoding test.");
     }
   }
 }
 
 function testCharset(test)
 {
   try {
     var fatal = test.fatal ? {fatal: test.fatal} : null;
-    var decoder = TextDecoder(test.encoding, fatal);
+    var decoder = new TextDecoder(test.encoding, fatal);
   } catch (e) {
     assert_equals(e.name, test.error, test.msg + " error thrown from the constructor.");
     return;
   }
 
   var array = test.array || [test];
   var num_strings = array.length;
   for (var i = 0; i < num_strings; i++) {
@@ -433,17 +433,17 @@ function testInvalid2022JP()
     [0x1b, 0x2e, 0x41, 0x1b, 0x4e, 0x80],
     [0x1b, 0x2e, 0x41, 0x1b, 0x4e, 0xFF],
   ];
 
   var failureCount = 0;
   inputs.forEach(function(input) {
     try {
       // decode() should never throw unless {fatal: true} is specified
-      new TextDecoder("iso-2022-jp").decode(new Uint8Array(input));
+      (new TextDecoder("iso-2022-jp")).decode(new Uint8Array(input));
     } catch (e) {
       if (e.name !== "EncodingError") {
         throw e;
       }
       failureCount++;
     }
   });
   assert_equals(failureCount, 0, failureCount + " of " + inputs.length + " tests failed");
--- a/dom/encoding/test/test_TextEncoder.js
+++ b/dom/encoding/test/test_TextEncoder.js
@@ -129,17 +129,17 @@ function testInputString(aData, aExpecte
     msg: "spaces as input string."});
 }
 
 function testSingleString(test)
 {
   var outText;
   try {
     var stream = test.stream ? {stream: true} : null;
-    outText = TextEncoder(test.encoding).encode(test.input, stream);
+    outText = (new TextEncoder(test.encoding)).encode(test.input, stream);
   } catch (e) {
     assert_equals(e.name, test.error, test.msg);
     return;
   }
   assert_true(!test.error, test.msg);
 
   if (outText.length !== test.expected.length) {
     assert_equals(outText.length, test.expected.length, test.msg + " length mismatch");
@@ -232,17 +232,17 @@ function testStreamingOptions()
 function arrayFromString(s) {
   return s.split('').map(function(c){return String.charCodeAt(c)});
 }
 
 function testArrayOfStrings(test)
 {
   var encoder;
   try {
-    encoder = TextEncoder(test.encoding);
+    encoder = new TextEncoder(test.encoding);
   } catch (e) {
     assert_equals(e.name, test.error, test.msg);
     return;
   }
   assert_true(!test.error, test.msg);
 
   var array = test.array;
   for (var i = 0; i < array.length; i += 1) {
@@ -265,13 +265,13 @@ function testEncoderGetEncoding()
   var labelEncodings = [
     {encoding: "utf-8", labels: ["unicode-1-1-utf-8", "utf-8", "utf8"]},
     {encoding: "utf-16le", labels: ["utf-16", "utf-16"]},
     {encoding: "utf-16be", labels: ["utf-16be"]},
   ];
 
   for (var le of labelEncodings) {
     for (var label of le.labels) {
-      var encoder = TextEncoder(label);
+      var encoder = new TextEncoder(label);
       assert_equals(encoder.encoding, le.encoding, label + " label encoding test.");
     }
   }
 }
--- a/dom/events/TextComposition.cpp
+++ b/dom/events/TextComposition.cpp
@@ -30,16 +30,25 @@ TextComposition::TextComposition(nsPresC
   mPresContext(aPresContext), mNode(aNode),
   mNativeContext(aEvent->widget->GetInputContext().mNativeIMEContext),
   mCompositionStartOffset(0), mCompositionTargetOffset(0),
   mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests),
   mIsComposing(false)
 {
 }
 
+void
+TextComposition::Destroy()
+{
+  mPresContext = nullptr;
+  mNode = nullptr;
+  // TODO: If the editor is still alive and this is held by it, we should tell
+  //       this being destroyed for cleaning up the stuff.
+}
+
 bool
 TextComposition::MatchesNativeContext(nsIWidget* aWidget) const
 {
   return mNativeContext == aWidget->GetInputContext().mNativeIMEContext;
 }
 
 void
 TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
@@ -48,16 +57,20 @@ TextComposition::DispatchEvent(WidgetGUI
 {
   if (aEvent->message == NS_COMPOSITION_UPDATE) {
     mLastData = aEvent->AsCompositionEvent()->data;
   }
 
   nsEventDispatcher::Dispatch(mNode, mPresContext,
                               aEvent, nullptr, aStatus, aCallBack);
 
+  if (!mPresContext) {
+    return;
+  }
+
   // Emulate editor behavior of text event handler if no editor handles
   // composition/text events.
   if (aEvent->message == NS_TEXT_TEXT && !HasEditor()) {
     EditorWillHandleTextEvent(aEvent->AsTextEvent());
     EditorDidHandleTextEvent();
   }
 
 #ifdef DEBUG
--- a/dom/events/TextComposition.h
+++ b/dom/events/TextComposition.h
@@ -40,16 +40,17 @@ public:
                   nsINode* aNode,
                   WidgetGUIEvent* aEvent);
 
   ~TextComposition()
   {
     // WARNING: mPresContext may be destroying, so, be careful if you touch it.
   }
 
+  bool Destroyed() const { return !mPresContext; }
   nsPresContext* GetPresContext() const { return mPresContext; }
   nsINode* GetEventTargetNode() const { return mNode; }
   // The latest CompositionEvent.data value except compositionstart event.
   // This value is modified at dispatching compositionupdate.
   const nsString& LastData() const { return mLastData; }
   // The composition string which is already handled by the focused editor.
   // I.e., this value must be same as the composition string on the focused
   // editor.  This value is modified at a call of EditorDidHandleTextEvent().
@@ -58,16 +59,21 @@ public:
   const nsString& String() const { return mString; }
   // Returns true if the composition is started with synthesized event which
   // came from nsDOMWindowUtils.
   bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }
 
   bool MatchesNativeContext(nsIWidget* aWidget) const;
 
   /**
+   * This is called when nsIMEStateManager stops managing the instance.
+   */
+  void Destroy();
+
+  /**
    * SynthesizeCommit() dispatches compositionupdate, text and compositionend
    * events for emulating commit on the content.
    *
    * @param aDiscard true when committing with empty string.  Otherwise, false.
    */
   void SynthesizeCommit(bool aDiscard);
 
   /**
--- a/dom/events/moz.build
+++ b/dom/events/moz.build
@@ -53,47 +53,58 @@ UNIFIED_SOURCES += [
     'nsDOMBeforeUnloadEvent.cpp',
     'nsDOMClipboardEvent.cpp',
     'nsDOMCommandEvent.cpp',
     'nsDOMCompositionEvent.cpp',
     'nsDOMDataContainerEvent.cpp',
     'nsDOMDataTransfer.cpp',
     'nsDOMDeviceMotionEvent.cpp',
     'nsDOMDragEvent.cpp',
-    'nsDOMEvent.cpp',
     'nsDOMEventTargetHelper.cpp',
     'nsDOMFocusEvent.cpp',
     'nsDOMKeyboardEvent.cpp',
     'nsDOMMessageEvent.cpp',
     'nsDOMMouseEvent.cpp',
     'nsDOMMouseScrollEvent.cpp',
     'nsDOMMutationEvent.cpp',
     'nsDOMNotifyAudioAvailableEvent.cpp',
-    'nsDOMNotifyPaintEvent.cpp',
-    'nsDOMScrollAreaEvent.cpp',
     'nsDOMSimpleGestureEvent.cpp',
     'nsDOMTextEvent.cpp',
     'nsDOMTouchEvent.cpp',
     'nsDOMTransitionEvent.cpp',
-    'nsDOMUIEvent.cpp',
     'nsDOMXULCommandEvent.cpp',
     'nsEventDispatcher.cpp',
-    'nsEventListenerManager.cpp',
     'nsEventListenerService.cpp',
     'nsIMEStateManager.cpp',
     'nsJSEventListener.cpp',
     'nsPaintRequest.cpp',
     'nsPrivateTextRange.cpp',
     'PointerEvent.cpp',
     'TextComposition.cpp',
     'Touch.cpp',
 ]
 
-# nsEventStateManager.cpp should be built separately because of Mac OS X headers.
 SOURCES += [
+    # nsDOMEvent.cpp should be built separately because it includes
+    # ipc/IPCMessageUtils.h, which on Windows includes windows.h.
+    'nsDOMEvent.cpp',
+    # nsDOMEvent.cpp should be built separately because it includes
+    # ipc/IPCMessageUtils.h, which on Windows includes windows.h.
+    'nsDOMNotifyPaintEvent.cpp',
+    # nsDOMEvent.cpp should be built separately because it includes
+    # ipc/IPCMessageUtils.h, which on Windows includes windows.h.
+    'nsDOMScrollAreaEvent.cpp',
+    # nsDOMEvent.cpp should be built separately because it includes
+    # ipc/IPCMessageUtils.h, which on Windows includes windows.h.
+    'nsDOMUIEvent.cpp',
+    # nsDOMEvent.cpp should be built separately because it includes
+    # mozilla/HalSensor.h, which includes ipc/IPCMessageUtils.h, which
+    # on Windows includes windows.h.
+    'nsEventListenerManager.cpp',
+    # nsEventStateManager.cpp should be built separately because of Mac OS X headers.
     'nsEventStateManager.cpp',
 ]
 
 if CONFIG['MOZ_WEBSPEECH']:
     UNIFIED_SOURCES += ['SpeechRecognitionError.cpp']
 
 FAIL_ON_WARNINGS = True
 
--- a/dom/events/nsDOMEvent.cpp
+++ b/dom/events/nsDOMEvent.cpp
@@ -759,25 +759,16 @@ nsDOMEvent::GetEventPopupControlState(Wi
         break;
       case NS_MOUSE_DOUBLECLICK :
         if (::PopupAllowedForEvent("dblclick"))
           abuse = openControlled;
         break;
       }
     }
     break;
-  case NS_SCRIPT_ERROR_EVENT :
-    switch(aEvent->message) {
-    case NS_LOAD_ERROR :
-      // Any error event will allow popups, if enabled in the pref.
-      if (::PopupAllowedForEvent("error"))
-        abuse = openControlled;
-      break;
-    }
-    break;
   case NS_FORM_EVENT :
     // For these following events only allow popups if they're
     // triggered while handling user input. See
     // nsPresShell::HandleEventInternal() for details.
     if (nsEventStateManager::IsHandlingUserInput()) {
       switch(aEvent->message) {
       case NS_FORM_SUBMIT :
         if (::PopupAllowedForEvent("submit"))
--- a/dom/events/nsDOMEvent.h
+++ b/dom/events/nsDOMEvent.h
@@ -22,16 +22,17 @@
 
 class nsIContent;
 class nsIDOMEventTarget;
 class nsPresContext;
 
 namespace mozilla {
 namespace dom {
 class EventTarget;
+class ErrorEvent;
 }
 }
 
 // Dummy class so we can cast through it to get from nsISupports to
 // nsDOMEvent subclasses with only two non-ambiguous static casts.
 class nsDOMEventBase : public nsIDOMEvent
 {
 };
@@ -85,16 +86,21 @@ public:
   }
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
   {
     return mozilla::dom::EventBinding::Wrap(aCx, aScope, this);
   }
 
+  virtual mozilla::dom::ErrorEvent* AsErrorEvent()
+  {
+    return nullptr;
+  }
+
   // nsIDOMEvent Interface
   NS_DECL_NSIDOMEVENT
 
   void InitPresContextData(nsPresContext* aPresContext);
 
   // Returns true if the event should be trusted.
   bool Init(mozilla::dom::EventTarget* aGlobal);
 
--- a/dom/events/nsEventListenerManager.cpp
+++ b/dom/events/nsEventListenerManager.cpp
@@ -864,17 +864,18 @@ nsEventListenerManager::CompileEventHand
     uint32_t argCount;
     const char **argNames;
     nsContentUtils::GetEventArgNames(aElement->GetNameSpaceID(),
                                      aListenerStruct->mTypeAtom,
                                      &argCount, &argNames);
 
     JSAutoCompartment ac(cx, context->GetWindowProxy());
     JS::CompileOptions options(cx);
-    options.setFileAndLine(url.get(), lineNo)
+    options.setIntroductionType("eventHandler")
+           .setFileAndLine(url.get(), lineNo)
            .setVersion(SCRIPTVERSION_DEFAULT);
 
     JS::Rooted<JS::Value> targetVal(cx);
     // Go ahead and wrap into the current compartment of cx directly.
     JS::Rooted<JSObject*> wrapScope(cx, JS::CurrentGlobalOrNull(cx));
     if (WrapNewBindingObject(cx, wrapScope, aElement, &targetVal)) {
       MOZ_ASSERT(targetVal.isObject());
 
--- a/dom/events/nsIMEStateManager.cpp
+++ b/dom/events/nsIMEStateManager.cpp
@@ -112,16 +112,17 @@ nsIMEStateManager::OnDestroyPresContext(
   NS_ENSURE_ARG_POINTER(aPresContext);
 
   // First, if there is a composition in the aPresContext, clean up it.
   if (sTextCompositions) {
     TextCompositionArray::index_type i =
       sTextCompositions->IndexOf(aPresContext);
     if (i != TextCompositionArray::NoIndex) {
       // there should be only one composition per presContext object.
+      sTextCompositions->ElementAt(i)->Destroy();
       sTextCompositions->RemoveElementAt(i);
       MOZ_ASSERT(sTextCompositions->IndexOf(aPresContext) ==
                    TextCompositionArray::NoIndex);
     }
   }
 
   if (aPresContext != sPresContext)
     return NS_OK;
@@ -574,16 +575,17 @@ nsIMEStateManager::DispatchCompositionEv
 
   // WARNING: the |composition| might have been destroyed already.
 
   // Remove the ended composition from the array.
   if (aEvent->message == NS_COMPOSITION_END) {
     TextCompositionArray::index_type i =
       sTextCompositions->IndexOf(GUIEvent->widget);
     if (i != TextCompositionArray::NoIndex) {
+      sTextCompositions->ElementAt(i)->Destroy();
       sTextCompositions->RemoveElementAt(i);
     }
   }
 }
 
 // static
 nsresult
 nsIMEStateManager::NotifyIME(IMEMessage aMessage,
--- a/dom/events/nsJSEventListener.cpp
+++ b/dom/events/nsJSEventListener.cpp
@@ -14,16 +14,17 @@
 #include "nsVariant.h"
 #include "nsIDOMBeforeUnloadEvent.h"
 #include "nsGkAtoms.h"
 #include "xpcpublic.h"
 #include "nsJSEnvironment.h"
 #include "nsDOMJSUtils.h"
 #include "mozilla/ContentEvents.h"
 #include "mozilla/Likely.h"
+#include "mozilla/dom/ErrorEvent.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "nsDOMEvent.h"
 
 #ifdef DEBUG
 
 #include "nspr.h" // PR_fprintf
 
 class EventListenerCounter
@@ -162,29 +163,26 @@ nsJSEventListener::HandleEvent(nsIDOMEve
 
     nsString errorMsg, file;
     EventOrString msgOrEvent;
     Optional<nsAString> fileName;
     Optional<uint32_t> lineNumber;
     Optional<uint32_t> columnNumber;
 
     NS_ENSURE_TRUE(aEvent, NS_ERROR_UNEXPECTED);
-    InternalScriptErrorEvent* scriptEvent =
-      aEvent->GetInternalNSEvent()->AsScriptErrorEvent();
-    if (scriptEvent &&
-        (scriptEvent->message == NS_LOAD_ERROR ||
-         scriptEvent->typeString.EqualsLiteral("error"))) {
-      errorMsg = scriptEvent->errorMsg;
+    ErrorEvent* scriptEvent = aEvent->InternalDOMEvent()->AsErrorEvent();
+    if (scriptEvent) {
+      scriptEvent->GetMessage(errorMsg);
       msgOrEvent.SetAsString().SetData(errorMsg.Data(), errorMsg.Length());
 
-      file = scriptEvent->fileName;
+      scriptEvent->GetFilename(file);
       fileName = &file;
 
       lineNumber.Construct();
-      lineNumber.Value() = scriptEvent->lineNr;
+      lineNumber.Value() = scriptEvent->Lineno();
     } else {
       msgOrEvent.SetAsEvent() = aEvent->InternalDOMEvent();
     }
 
     nsRefPtr<OnErrorEventHandlerNonNull> handler =
       mHandler.OnErrorEventHandler();
     ErrorResult rv;
     bool handled = handler->Call(mTarget, msgOrEvent, fileName, lineNumber,
new file mode 100644
--- /dev/null
+++ b/dom/events/test/error_event_worker.js
@@ -0,0 +1,15 @@
+ addEventListener("error", function(e) {
+     var obj = {};
+     for (var prop of ["message", "filename", "lineno"]) {
+       obj[prop] = e[prop]
+     }
+     obj.type = "event";
+     postMessage(obj);
+});
+onerror = function(message, filename, lineno) {
+  var obj = { message: message, filename: filename, lineno: lineno,
+	      type: "callback" }
+  postMessage(obj);
+  return false;
+}
+throw new Error("workerhello");
--- a/dom/events/test/mochitest.ini
+++ b/dom/events/test/mochitest.ini
@@ -1,16 +1,17 @@
 [DEFAULT]
 support-files =
   bug226361_iframe.xhtml
   bug299673.js
   bug322588-popup.html
   bug426082.html
   bug457672.html
   bug656379-1.html
+  error_event_worker.js
   empty.js
   window_bug493251.html
   window_bug659071.html
   window_wheel_default_action.html
 
 [test_addEventListenerExtraArg.html]
 [test_all_synthetic_events.html]
 [test_bug226361.xhtml]
@@ -125,15 +126,16 @@ skip-if = toolkit == 'android' #CRASH_DU
 [test_dom_keyboard_event.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dom_mouse_event.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dom_wheel_event.html]
 [test_draggableprop.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dragstart.html]
+[test_error_events.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_eventctors.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_focus_disabled.html]
 [test_messageEvent.html]
 [test_moz_mouse_pixel_scroll_event.html]
 [test_wheel_default_action.html]
new file mode 100644
--- /dev/null
+++ b/dom/events/test/test_error_events.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test for error events being ErrorEvent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+  var errorEvent;
+  var file;
+  var line;
+  var msg;
+  window.addEventListener("error", function errorListener(e) {
+    window.removeEventListener("error", errorListener);
+    errorEvent = e;
+  });
+  var oldOnerror = window.onerror;
+  window.onerror = function(message, filename, lineno) {
+    window.onerror = oldOnerror;
+    file = filename;
+    line = lineno;
+    msg = message;
+  }
+  throw new Error("hello");
+</script>
+<script>
+  generate_tests(assert_equals, [
+    [ "Event filename", errorEvent.filename, location.href ],
+    [ "Callback filename", file, location.href ],
+    [ "Event line number", errorEvent.lineno, 23 ],
+    [ "Callback line number", line, 23 ],
+    [ "Event message", errorEvent.message, "Error: hello" ],
+    [ "Callback message", msg, "Error: hello" ]
+  ]);
+</script>
+<script>
+  var workerLocation = location.protocol + "//" + location.host +
+    location.pathname.replace("test_error_events.html", "error_event_worker.js");
+  var eventFileTest = async_test("Worker event filename");
+  var eventLineTest = async_test("Worker event line number");
+  var eventMessageTest = async_test("Worker event message");
+  var callbackFileTest = async_test("Worker callback filename");
+  var callbackLineTest = async_test("Worker callback line number");
+  var callbackMessageTest = async_test("Worker callback message");
+  var w = new Worker("error_event_worker.js");
+  w.addEventListener("message", function(msg) {
+    if (msg.data.type == "event") {
+      eventFileTest.step(function() { assert_equals(msg.data.filename, workerLocation); });
+      eventFileTest.done();
+      eventLineTest.step(function() { assert_equals(msg.data.lineno, 15); });
+      eventLineTest.done();
+      eventMessageTest.step(function() { assert_equals(msg.data.message, "Error: workerhello"); });
+      eventMessageTest.done();
+    } else {
+      callbackFileTest.step(function() { assert_equals(msg.data.filename, workerLocation); });
+      callbackFileTest.done();
+      callbackLineTest.step(function() { assert_equals(msg.data.lineno, 15); });
+      callbackLineTest.done();
+      callbackMessageTest.step(function() { assert_equals(msg.data.message, "Error: workerhello"); });
+      callbackMessageTest.done();
+    }
+  });
+</script>
deleted file mode 100644
--- a/dom/file/DOMFileHandle.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "DOMFileHandle.h"
-
-#include "nsIFileStreams.h"
-
-#include "nsDOMClassInfoID.h"
-#include "nsNetUtil.h"
-
-#include "File.h"
-#include "LockedFile.h"
-
-USING_FILE_NAMESPACE
-
-// static
-already_AddRefed<DOMFileHandle>
-DOMFileHandle::Create(nsPIDOMWindow* aWindow,
-                      nsIFileStorage* aFileStorage,
-                      nsIFile* aFile)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-  nsRefPtr<DOMFileHandle> newFile(new DOMFileHandle(aWindow));
-
-  newFile->mFileStorage = aFileStorage;
-  nsresult rv = aFile->GetLeafName(newFile->mName);
-  NS_ENSURE_SUCCESS(rv, nullptr);
-
-  newFile->mFile = aFile;
-  newFile->mFileName = newFile->mName;
-
-  return newFile.forget();
-}
-
-already_AddRefed<nsISupports>
-DOMFileHandle::CreateStream(nsIFile* aFile, bool aReadOnly)
-{
-  nsresult rv;
-
-  if (aReadOnly) {
-    nsCOMPtr<nsIInputStream> stream;
-    rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), aFile, -1, -1,
-                                    nsIFileInputStream::DEFER_OPEN);
-    NS_ENSURE_SUCCESS(rv, nullptr);
-    return stream.forget();
-  }
-
-  nsCOMPtr<nsIFileStream> stream;
-  rv = NS_NewLocalFileStream(getter_AddRefs(stream), aFile, -1, -1,
-                             nsIFileStream::DEFER_OPEN);
-  NS_ENSURE_SUCCESS(rv, nullptr);
-  return stream.forget();
-}
-
-already_AddRefed<nsIDOMFile>
-DOMFileHandle::CreateFileObject(LockedFile* aLockedFile, uint32_t aFileSize)
-{
-  nsCOMPtr<nsIDOMFile> file = 
-    new File(mName, mType, aFileSize, mFile, aLockedFile);
-
-  return file.forget();
-}
deleted file mode 100644
--- a/dom/file/DOMFileHandle.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_file_domfilehandle_h__
-#define mozilla_dom_file_domfilehandle_h__
-
-#include "mozilla/Attributes.h"
-#include "FileCommon.h"
-
-#include "FileHandle.h"
-
-BEGIN_FILE_NAMESPACE
-
-class DOMFileHandle : public FileHandle
-{
-public:
-  static already_AddRefed<DOMFileHandle>
-  Create(nsPIDOMWindow* aWindow,
-         nsIFileStorage* aFileStorage,
-         nsIFile* aFile);
-
-  virtual already_AddRefed<nsISupports>
-  CreateStream(nsIFile* aFile, bool aReadOnly) MOZ_OVERRIDE;
-
-  virtual already_AddRefed<nsIDOMFile>
-  CreateFileObject(LockedFile* aLockedFile, uint32_t aFileSize) MOZ_OVERRIDE;
-
-protected:
-  DOMFileHandle(nsPIDOMWindow* aWindow)
-    : FileHandle(aWindow)
-  { }
-
-  ~DOMFileHandle()
-  { }
-};
-
-END_FILE_NAMESPACE
-
-#endif // mozilla_dom_file_domfilehandle_h__
--- a/dom/file/FileHandle.cpp
+++ b/dom/file/FileHandle.cpp
@@ -3,20 +3,22 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "FileHandle.h"
 
 #include "nsContentUtils.h"
 #include "nsDOMClassInfoID.h"
+#include "nsNetUtil.h"
 
 #include "nsIDOMFile.h"
 #include "nsIFileStorage.h"
 
+#include "File.h"
 #include "FileRequest.h"
 #include "FileService.h"
 #include "LockedFile.h"
 #include "MetadataHelper.h"
 #include "mozilla/dom/FileHandleBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -30,83 +32,105 @@ public:
   GetFileHelper(LockedFile* aLockedFile,
                 FileRequest* aFileRequest,
                 MetadataParameters* aParams,
                 FileHandle* aFileHandle)
   : MetadataHelper(aLockedFile, aFileRequest, aParams),
     mFileHandle(aFileHandle)
   { }
 
-  nsresult
+  virtual nsresult
   GetSuccessResult(JSContext* aCx,
                    JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
 
-  void
-  ReleaseObjects()
+  virtual void
+  ReleaseObjects() MOZ_OVERRIDE
   {
     mFileHandle = nullptr;
 
     MetadataHelper::ReleaseObjects();
   }
 
 private:
   nsRefPtr<FileHandle> mFileHandle;
 };
 
 } // anonymous namespace
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED_1(FileHandle, nsDOMEventTargetHelper,
                                      mFileStorage)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FileHandle)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMFileHandle)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(FileHandle, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(FileHandle, nsDOMEventTargetHelper)
 
-NS_IMPL_EVENT_HANDLER(FileHandle, abort)
-NS_IMPL_EVENT_HANDLER(FileHandle, error)
-
-NS_IMETHODIMP
-FileHandle::GetDOMName(nsAString& aName)
+// static
+already_AddRefed<FileHandle>
+FileHandle::Create(nsPIDOMWindow* aWindow,
+                   nsIFileStorage* aFileStorage,
+                   nsIFile* aFile)
 {
-  aName = mName;
-  return NS_OK;
-}
+  MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+
+  nsRefPtr<FileHandle> newFileHandle = new FileHandle(aWindow);
 
-NS_IMETHODIMP
-FileHandle::GetDOMType(nsAString& aType)
-{
-  aType = mType;
-  return NS_OK;
+  newFileHandle->mFileStorage = aFileStorage;
+  nsresult rv = aFile->GetLeafName(newFileHandle->mName);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return nullptr;
+  }
+
+  newFileHandle->mFile = aFile;
+  newFileHandle->mFileName = newFileHandle->mName;
+
+  return newFileHandle.forget();
 }
 
-NS_IMETHODIMP
-FileHandle::Open(const nsAString& aMode,
-                 uint8_t aOptionalArgCount,
-                 nsIDOMLockedFile** _retval)
+// virtual
+already_AddRefed<nsISupports>
+FileHandle::CreateStream(nsIFile* aFile, bool aReadOnly)
 {
-  FileMode mode;
-  if (aOptionalArgCount) {
-    if (aMode.EqualsLiteral("readwrite")) {
-      mode = FileMode::Readwrite;
-    } else if (aMode.EqualsLiteral("readonly")) {
-      mode = FileMode::Readonly;
-    } else {
-      return NS_ERROR_TYPE_ERR;
+  nsresult rv;
+
+  if (aReadOnly) {
+    nsCOMPtr<nsIInputStream> stream;
+    rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), aFile, -1, -1,
+                                    nsIFileInputStream::DEFER_OPEN);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return nullptr;
     }
-  } else {
-    mode = FileMode::Readonly;
+    return stream.forget();
   }
 
-  ErrorResult rv;
-  nsCOMPtr<nsIDOMLockedFile> lockedFile = Open(mode, rv);
-  lockedFile.forget(_retval);
-  return rv.ErrorCode();
+  nsCOMPtr<nsIFileStream> stream;
+  rv = NS_NewLocalFileStream(getter_AddRefs(stream), aFile, -1, -1,
+                             nsIFileStream::DEFER_OPEN);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return nullptr;
+  }
+  return stream.forget();
+}
+
+// virtual
+already_AddRefed<nsIDOMFile>
+FileHandle::CreateFileObject(LockedFile* aLockedFile, uint32_t aFileSize)
+{
+  nsCOMPtr<nsIDOMFile> file =
+    new File(mName, mType, aFileSize, mFile, aLockedFile);
+
+  return file.forget();
+}
+
+// virtual
+JSObject*
+FileHandle::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return FileHandleBinding::Wrap(aCx, aScope, this);
 }
 
 already_AddRefed<nsIDOMLockedFile>
 FileHandle::Open(FileMode aMode, ErrorResult& aError)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (FileService::IsShuttingDown() || mFileStorage->IsShuttingDown()) {
@@ -118,25 +142,16 @@ FileHandle::Open(FileMode aMode, ErrorRe
   if (!lockedFile) {
     aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR);
     return nullptr;
   }
 
   return lockedFile.forget();
 }
 
-NS_IMETHODIMP
-FileHandle::GetFile(nsIDOMDOMRequest** _retval)
-{
-  ErrorResult rv;
-  nsRefPtr<DOMRequest> request = GetFile(rv);
-  request.forget(_retval);
-  return rv.ErrorCode();
-}
-
 already_AddRefed<DOMRequest>
 FileHandle::GetFile(ErrorResult& aError)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Do nothing if the window is closed
   if (!GetOwner()) {
     return nullptr;
@@ -160,41 +175,22 @@ FileHandle::GetFile(ErrorResult& aError)
   if (NS_FAILED(rv)) {
     aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR);
     return nullptr;
   }
 
   return request.forget();
 }
 
-NS_IMETHODIMP_(int64_t)
-FileHandle::GetFileId()
-{
-  return -1;
-}
-
-NS_IMETHODIMP_(mozilla::dom::indexedDB::FileInfo*)
-FileHandle::GetFileInfo()
-{
-  return nullptr;
-}
-
 nsresult
 GetFileHelper::GetSuccessResult(JSContext* aCx,
                                 JS::MutableHandle<JS::Value> aVal)
 {
   nsCOMPtr<nsIDOMFile> domFile =
     mFileHandle->CreateFileObject(mLockedFile, mParams->Size());
 
   JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
   nsresult rv =
     nsContentUtils::WrapNative(aCx, global, domFile,
                                &NS_GET_IID(nsIDOMFile), aVal);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR);
   return NS_OK;
 }
-
-/* virtual */
-JSObject*
-FileHandle::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
-{
-  return FileHandleBinding::Wrap(aCx, aScope, this);
-}
--- a/dom/file/FileHandle.h
+++ b/dom/file/FileHandle.h
@@ -4,113 +4,143 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_file_filehandle_h__
 #define mozilla_dom_file_filehandle_h__
 
 #include "FileCommon.h"
 
-#include "nsIDOMFileHandle.h"
 #include "nsIFile.h"
 #include "nsIFileStorage.h"
 
 #include "nsDOMEventTargetHelper.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/FileModeBinding.h"
 
 class nsIDOMFile;
+class nsIDOMLockedFile;
 class nsIFileStorage;
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 class DOMRequest;
+namespace indexedDB {
+class FileInfo;
+} // namespace indexedDB
 } // namespace dom
 } // namespace mozilla
 
 BEGIN_FILE_NAMESPACE
 
 class FileService;
 class LockedFile;
 class FinishHelper;
 class FileHelper;
 
 /**
- * Must be subclassed. The subclass must implement CreateStream and
- * CreateFileObject. Basically, every file storage implementation provides its
- * own FileHandle implementation (for example IDBFileHandle provides IndexedDB
- * specific implementation).
+ * This class provides a default FileHandle implementation, but it can be also
+ * subclassed. The subclass can override implementation of GetFileId,
+ * GetFileInfo, CreateStream and CreateFileObject.
+ * (for example IDBFileHandle provides IndexedDB specific implementation).
  */
-class FileHandle : public nsDOMEventTargetHelper,
-                   public nsIDOMFileHandle
+class FileHandle : public nsDOMEventTargetHelper
 {
   friend class FileService;
   friend class LockedFile;
   friend class FinishHelper;
   friend class FileHelper;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIDOMFILEHANDLE
-
-  nsPIDOMWindow* GetParentObject() const
-  {
-    return GetOwner();
-  }
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FileHandle, nsDOMEventTargetHelper)
 
-  void GetName(nsString& aName) const
-  {
-    aName = mName;
-  }
-  void GetType(nsString& aType) const
-  {
-    aType = mType;
-  }
-  already_AddRefed<nsIDOMLockedFile> Open(FileMode aMode, ErrorResult& aError);
-  already_AddRefed<DOMRequest> GetFile(ErrorResult& aError);
-  IMPL_EVENT_HANDLER(abort)
-  IMPL_EVENT_HANDLER(error)
-
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FileHandle, nsDOMEventTargetHelper)
+  static already_AddRefed<FileHandle>
+  Create(nsPIDOMWindow* aWindow,
+         nsIFileStorage* aFileStorage,
+         nsIFile* aFile);
 
   const nsAString&
   Name() const
   {
     return mName;
   }
 
   const nsAString&
   Type() const
   {
     return mType;
   }
 
+  virtual int64_t
+  GetFileId()
+  {
+    return -1;
+  }
+
+  virtual mozilla::dom::indexedDB::FileInfo*
+  GetFileInfo()
+  {
+    return nullptr;
+  }
+
   virtual already_AddRefed<nsISupports>
-  CreateStream(nsIFile* aFile, bool aReadOnly) = 0;
+  CreateStream(nsIFile* aFile, bool aReadOnly);
 
   virtual already_AddRefed<nsIDOMFile>
-  CreateFileObject(LockedFile* aLockedFile, uint32_t aFileSize) = 0;
+  CreateFileObject(LockedFile* aLockedFile, uint32_t aFileSize);
+
+  // nsWrapperCache
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  // WebIDL
+  nsPIDOMWindow*
+  GetParentObject() const
+  {
+    return GetOwner();
+  }
+
+  void
+  GetName(nsString& aName) const
+  {
+    aName = mName;
+  }
+
+  void
+  GetType(nsString& aType) const
+  {
+    aType = mType;
+  }
+
+  already_AddRefed<nsIDOMLockedFile>
+  Open(FileMode aMode, ErrorResult& aError);
+
+  already_AddRefed<DOMRequest>
+  GetFile(ErrorResult& aError);
+
+  IMPL_EVENT_HANDLER(abort)
+  IMPL_EVENT_HANDLER(error)
 
 protected:
   FileHandle(nsPIDOMWindow* aWindow)
     : nsDOMEventTargetHelper(aWindow)
   {
   }
 
   FileHandle(nsDOMEventTargetHelper* aOwner)
     : nsDOMEventTargetHelper(aOwner)
   {
   }
 
   ~FileHandle()
-  { }
+  {
+  }
 
   nsCOMPtr<nsIFileStorage> mFileStorage;
 
   nsString mName;
   nsString mType;
 
   nsCOMPtr<nsIFile> mFile;
   nsString mFileName;
--- a/dom/file/LockedFile.cpp
+++ b/dom/file/LockedFile.cpp
@@ -453,19 +453,19 @@ LockedFile::IsOpen() const
       return true;
     }
   }
 
   return false;
 }
 
 NS_IMETHODIMP
-LockedFile::GetFileHandle(nsIDOMFileHandle** aFileHandle)
+LockedFile::GetFileHandle(nsISupports** aFileHandle)
 {
-  nsCOMPtr<nsIDOMFileHandle> result(mFileHandle);
+  nsCOMPtr<nsISupports> result(mFileHandle);
   result.forget(aFileHandle);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 LockedFile::GetMode(nsAString& aMode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
--- a/dom/file/moz.build
+++ b/dom/file/moz.build
@@ -2,50 +2,47 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 TEST_DIRS += ['test']
 
 XPIDL_SOURCES += [
-    'nsIDOMFileHandle.idl',
     'nsIDOMLockedFile.idl',
 ]
 
 XPIDL_MODULE = 'dom_file'
 
 EXPORTS += [
     'nsIFileStorage.h',
 ]
 
 EXPORTS.mozilla.dom.file += [
     'ArchiveEvent.h',
     'ArchiveReader.h',
     'ArchiveRequest.h',
     'ArchiveZipEvent.h',
     'ArchiveZipFile.h',
-    'DOMFileHandle.h',
     'DOMFileRequest.h',
     'File.h',
     'FileCommon.h',
     'FileHandle.h',
     'FileHelper.h',
     'FileService.h',
     'LockedFile.h',
 ]
 
 UNIFIED_SOURCES += [
     'ArchiveEvent.cpp',
     'ArchiveReader.cpp',
     'ArchiveRequest.cpp',
     'ArchiveZipEvent.cpp',
     'ArchiveZipFile.cpp',
     'AsyncHelper.cpp',
-    'DOMFileHandle.cpp',
     'DOMFileRequest.cpp',
     'File.cpp',
     'FileHandle.cpp',
     'FileHelper.cpp',
     'FileRequest.cpp',
     'FileService.cpp',
     'FileStreamWrappers.cpp',
     'LockedFile.cpp',
deleted file mode 100644
--- a/dom/file/nsIDOMFileHandle.idl
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-%{C++
-namespace mozilla {
-namespace dom {
-namespace indexedDB {
-class FileInfo;
-}
-}
-}
-%}
-
-[ptr] native FileInfo(mozilla::dom::indexedDB::FileInfo);
-
-interface nsIDOMDOMRequest;
-interface nsIDOMEventListener;
-interface nsIDOMLockedFile;
-
-[scriptable, builtinclass, uuid(47438729-7f3f-4a66-b6d4-d1297c593d46)]
-interface nsIDOMFileHandle : nsISupports
-{
-  [binaryname(DOMName)]
-  readonly attribute DOMString name;
-
-  [binaryname(DOMType)]
-  readonly attribute DOMString type;
-
-  // mode can be either "readonly" or "readwrite"
-  [optional_argc]
-  nsIDOMLockedFile
-  open([optional /* "readonly" */] in DOMString mode);
-
-  nsIDOMDOMRequest
-  getFile();
-
-  [notxpcom]
-  long long
-  getFileId();
-
-  [notxpcom]
-  FileInfo
-  getFileInfo();
-
-  [implicit_jscontext] attribute jsval onabort;
-
-  [implicit_jscontext] attribute jsval onerror;
-};
--- a/dom/file/nsIDOMLockedFile.idl
+++ b/dom/file/nsIDOMLockedFile.idl
@@ -2,22 +2,21 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMEventListener;
-interface nsIDOMFileHandle;
 
 [scriptable, builtinclass, uuid(a09cdc35-6b1e-42ce-95bb-f8f10a354202)]
 interface nsIDOMLockedFile : nsISupports
 {
-  readonly attribute nsIDOMFileHandle fileHandle;
+  readonly attribute nsISupports /* FileHandle */ fileHandle;
 
   // "readonly" or "readwrite"
   readonly attribute DOMString mode;
 
   readonly attribute boolean active;
 
   [implicit_jscontext]
   attribute jsval location;
--- a/dom/imptests/html/dom/events/test_Event-constructors.html
+++ b/dom/imptests/html/dom/events/test_Event-constructors.html
@@ -37,17 +37,17 @@ test(function() {
   assert_equals(ev.bubbles, false)
   assert_equals(ev.cancelable, false)
   assert_equals(ev.defaultPrevented, false)
   assert_equals(ev.isTrusted, false)
   assert_true(ev.timeStamp > 0)
   assert_true("initEvent" in ev)
 })
 test(function() {
-  var ev = Event("test")
+  var ev = new Event("test")
   assert_equals(ev.type, "test")
   assert_equals(ev.target, null)
   assert_equals(ev.currentTarget, null)
   assert_equals(ev.eventPhase, Event.NONE)
   assert_equals(ev.bubbles, false)
   assert_equals(ev.cancelable, false)
   assert_equals(ev.defaultPrevented, false)
   assert_equals(ev.isTrusted, false)
--- a/dom/imptests/html/domxpath/test_evaluator-constructor.html
+++ b/dom/imptests/html/domxpath/test_evaluator-constructor.html
@@ -5,13 +5,9 @@
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <div id=log></div>
 <script>
 test(function() {
   var x = new XPathEvaluator();
   assert_true(x instanceof XPathEvaluator);
 }, "Constructor with 'new'");
-test(function() {
-  var x = XPathEvaluator();
-  assert_true(x instanceof XPathEvaluator);
-}, "Constructor without 'new'");
 </script>
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -948,11 +948,10 @@ CreateFileHelper::DoDatabaseWork(mozISto
 nsresult
 CreateFileHelper::GetSuccessResult(JSContext* aCx,
                                    JS::MutableHandle<JS::Value> aVal)
 {
   nsRefPtr<IDBFileHandle> fileHandle =
     IDBFileHandle::Create(mDatabase, mName, mType, mFileInfo.forget());
   IDB_ENSURE_TRUE(fileHandle, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
-  return WrapNative(aCx, NS_ISUPPORTS_CAST(nsIDOMFileHandle*, fileHandle),
-                    aVal);
+  return WrapNative(aCx, NS_ISUPPORTS_CAST(EventTarget*, fileHandle), aVal);
 }
--- a/dom/indexedDB/IDBFileHandle.cpp
+++ b/dom/indexedDB/IDBFileHandle.cpp
@@ -35,23 +35,16 @@ GetFileFor(FileInfo* aFileInfo)
 
 } // anonymous namespace
 
 IDBFileHandle::IDBFileHandle(IDBDatabase* aOwner)
   : FileHandle(aOwner)
 {
 }
 
-// virtual
-JSObject*
-IDBFileHandle::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
-{
-  return IDBFileHandleBinding::Wrap(aCx, aScope, this);
-}
-
 // static
 already_AddRefed<IDBFileHandle>
 IDBFileHandle::Create(IDBDatabase* aDatabase,
                       const nsAString& aName,
                       const nsAString& aType,
                       already_AddRefed<FileInfo> aFileInfo)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@@ -108,16 +101,23 @@ IDBFileHandle::CreateFileObject(mozilla:
                                 uint32_t aFileSize)
 {
   nsCOMPtr<nsIDOMFile> file = new mozilla::dom::file::File(
     mName, mType, aFileSize, mFile, aLockedFile, mFileInfo);
 
   return file.forget();
 }
 
+// virtual
+JSObject*
+IDBFileHandle::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return IDBFileHandleBinding::Wrap(aCx, aScope, this);
+}
+
 IDBDatabase*
 IDBFileHandle::Database()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBDatabase* database = static_cast<IDBDatabase*>(mFileStorage.get());
   MOZ_ASSERT(database);
 
--- a/dom/indexedDB/IDBFileHandle.h
+++ b/dom/indexedDB/IDBFileHandle.h
@@ -13,49 +13,55 @@
 #include "mozilla/dom/indexedDB/FileInfo.h"
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class IDBDatabase;
 
 class IDBFileHandle : public file::FileHandle
 {
+  typedef mozilla::dom::file::LockedFile LockedFile;
+
 public:
-  virtual JSObject*
-  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+  static already_AddRefed<IDBFileHandle>
+  Create(IDBDatabase* aDatabase, const nsAString& aName,
+         const nsAString& aType, already_AddRefed<FileInfo> aFileInfo);
 
-  NS_IMETHOD_(int64_t)
-  GetFileId()
+
+  virtual int64_t
+  GetFileId() MOZ_OVERRIDE
   {
     return mFileInfo->Id();
   }
 
-  NS_IMETHOD_(FileInfo*)
-  GetFileInfo()
+  virtual FileInfo*
+  GetFileInfo() MOZ_OVERRIDE
   {
     return mFileInfo;
   }
 
-  static already_AddRefed<IDBFileHandle>
-  Create(IDBDatabase* aDatabase, const nsAString& aName,
-         const nsAString& aType, already_AddRefed<FileInfo> aFileInfo);
-
   virtual already_AddRefed<nsISupports>
-  CreateStream(nsIFile* aFile, bool aReadOnly);
+  CreateStream(nsIFile* aFile, bool aReadOnly) MOZ_OVERRIDE;
 
   virtual already_AddRefed<nsIDOMFile>
-  CreateFileObject(file::LockedFile* aLockedFile, uint32_t aFileSize);
+  CreateFileObject(LockedFile* aLockedFile, uint32_t aFileSize) MOZ_OVERRIDE;
 
+  // nsWrapperCache
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  // WebIDL
   IDBDatabase*
   Database();
 
 private:
   IDBFileHandle(IDBDatabase* aOwner);
 
   ~IDBFileHandle()
-  { }
+  {
+  }
 
   nsRefPtr<FileInfo> mFileInfo;
 };
 
 END_INDEXEDDB_NAMESPACE
 
 #endif // mozilla_dom_indexeddb_idbfilehandle_h__
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -775,29 +775,21 @@ public:
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     nsRefPtr<FileInfo>& fileInfo = aFile.mFileInfo;
 
     nsRefPtr<IDBFileHandle> fileHandle = IDBFileHandle::Create(aDatabase,
       aData.name, aData.type, fileInfo.forget());
 
-    JS::Rooted<JS::Value> wrappedFileHandle(aCx);
     JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
-    nsresult rv =
-      nsContentUtils::WrapNative(aCx, global,
-                                 static_cast<nsIDOMFileHandle*>(fileHandle),
-                                 &NS_GET_IID(nsIDOMFileHandle),
-                                 &wrappedFileHandle);
-    if (NS_FAILED(rv)) {
-      NS_WARNING("Failed to wrap native!");
+    if (!global) {
       return nullptr;
     }
-
-    return JSVAL_TO_OBJECT(wrappedFileHandle);
+    return fileHandle->WrapObject(aCx, global);
   }
 
   static JSObject* CreateAndWrapBlobOrFile(JSContext* aCx,
                                            IDBDatabase* aDatabase,
                                            StructuredCloneFile& aFile,
                                            const BlobOrFileData& aData)
   {
     MOZ_ASSERT(NS_IsMainThread());
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "IDBRequest.h"
 
 #include "nsIScriptContext.h"
 
 #include "mozilla/ContentEvents.h"
+#include "mozilla/dom/ErrorEventBinding.h"
 #include "mozilla/dom/IDBOpenDBRequestBinding.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "nsComponentManagerUtils.h"
 #include "nsDOMClassInfoID.h"
 #include "nsDOMJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
 #include "nsEventDispatcher.h"
@@ -37,16 +38,17 @@ namespace {
 #ifdef MOZ_ENABLE_PROFILER_SPS
 uint64_t gNextRequestSerialNumber = 1;
 #endif
 
 } // anonymous namespace
 
 USING_INDEXEDDB_NAMESPACE
 using mozilla::dom::OwningIDBObjectStoreOrIDBIndexOrIDBCursor;
+using mozilla::dom::ErrorEventInit;
 using namespace mozilla;
 
 IDBRequest::IDBRequest(IDBDatabase* aDatabase)
 : IDBWrapperCache(aDatabase),
   mResultVal(JSVAL_VOID),
   mActorParent(nullptr),
 #ifdef MOZ_ENABLE_PROFILER_SPS
   mSerialNumber(gNextRequestSerialNumber++),
@@ -295,20 +297,20 @@ IDBRequest::CaptureCaller()
     return;
   }
 
   mFilename.Assign(NS_ConvertUTF8toUTF16(filename));
   mLineNo = lineNo;
 }
 
 void
-IDBRequest::FillScriptErrorEvent(InternalScriptErrorEvent* aEvent) const
+IDBRequest::FillScriptErrorEvent(ErrorEventInit& aEventInit) const
 {
-  aEvent->lineNr = mLineNo;
-  aEvent->fileName = mFilename.get();
+  aEventInit.mLineno = mLineNo;
+  aEventInit.mFilename = mFilename;
 }
 
 mozilla::dom::IDBRequestReadyState
 IDBRequest::ReadyState() const
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (IsPending()) {
--- a/dom/indexedDB/IDBRequest.h
+++ b/dom/indexedDB/IDBRequest.h
@@ -20,16 +20,17 @@
 #include "mozilla/dom/indexedDB/IDBWrapperCache.h"
 
 class nsIScriptContext;
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 class OwningIDBObjectStoreOrIDBIndexOrIDBCursor;
+class ErrorEventInit;
 }
 }
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class HelperBase;
 class IDBCursor;
 class IDBFactory;
@@ -96,17 +97,17 @@ public:
   IndexedDBRequestParentBase*
   GetActorParent() const
   {
     return mActorParent;
   }
 
   void CaptureCaller();
 
-  void FillScriptErrorEvent(mozilla::InternalScriptErrorEvent* aEvent) const;
+  void FillScriptErrorEvent(ErrorEventInit& aEventInit) const;
 
   bool
   IsPending() const
   {
     return !mHaveResultOrErrorCode;
   }
 
 #ifdef MOZ_ENABLE_PROFILER_SPS
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -12,16 +12,17 @@
 #include "nsIFileStorage.h"
 #include "nsIObserverService.h"
 #include "nsIScriptError.h"
 
 #include "jsapi.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/CondVar.h"
 #include "mozilla/ContentEvents.h"
+#include "mozilla/dom/ErrorEventBinding.h"
 #include "mozilla/dom/quota/OriginOrPatternString.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/quota/Utilities.h"
 #include "mozilla/dom/TabContext.h"
 #include "mozilla/Services.h"
 #include "mozilla/storage.h"
 #include "nsContentUtils.h"
 #include "nsEventDispatcher.h"
@@ -335,46 +336,45 @@ IndexedDatabaseManager::FireWindowOnErro
     return ret.ErrorCode();
   }
 
   nsString errorName;
   if (error) {
     error->GetName(errorName);
   }
 
-  mozilla::InternalScriptErrorEvent event(true, NS_LOAD_ERROR);
-  request->FillScriptErrorEvent(&event);
-  NS_ABORT_IF_FALSE(event.fileName,
-                    "FillScriptErrorEvent should give us a non-null string "
-                    "for our error's fileName");
+  ErrorEventInit init;
+  request->FillScriptErrorEvent(init);
 
-  event.errorMsg = errorName.get();
+  init.mMessage = errorName;
+  init.mCancelable = true;
+  init.mBubbles = true;
 
   nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(aOwner));
   NS_ASSERTION(sgo, "How can this happen?!");
 
   nsEventStatus status = nsEventStatus_eIgnore;
-  if (NS_FAILED(sgo->HandleScriptError(&event, &status))) {
+  if (NS_FAILED(sgo->HandleScriptError(init, &status))) {
     NS_WARNING("Failed to dispatch script error event");
     status = nsEventStatus_eIgnore;
   }
 
   bool preventDefaultCalled = status == nsEventStatus_eConsumeNoDefault;
   if (preventDefaultCalled) {
     return NS_OK;
   }
 
   // Log an error to the error console.
   nsCOMPtr<nsIScriptError> scriptError =
     do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (NS_FAILED(scriptError->InitWithWindowID(errorName,
-                                              nsDependentString(event.fileName),
-                                              EmptyString(), event.lineNr,
+                                              init.mFilename,
+                                              EmptyString(), init.mLineno,
                                               0, 0,
                                               "IndexedDB",
                                               aOwner->WindowID()))) {
     NS_WARNING("Failed to init script error!");
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIConsoleService> consoleService =
--- a/dom/interfaces/base/nsIContentPermissionPrompt.idl
+++ b/dom/interfaces/base/nsIContentPermissionPrompt.idl
@@ -7,29 +7,34 @@
 interface nsIPrincipal;
 interface nsIDOMWindow;
 interface nsIDOMElement;
 interface nsIArray;
 
 /**
  *  Interface provides the request type and its access.
  */
-[scriptable, uuid(384b6cc4-a66b-4bea-98e0-eb10562a9ba4)]
+[scriptable, uuid(ef4db3b8-ca9c-4b1d-8f81-fd88ec32af13)]
 interface nsIContentPermissionType : nsISupports {
   /**
    *  The type of the permission request, such as
    *  "geolocation".
    */
   readonly attribute ACString type;
 
   /**
    *  The access of the permission request, such as
    *  "read".
    */
   readonly attribute ACString access;
+
+  /**
+   * The array of available options.
+   */
+  readonly attribute nsIArray options; // ["choice1", "choice2"]
 };
 
 /**
  * Interface allows access to a content to request
  * permission to perform a privileged operation such as
  * geolocation.
  */
 [scriptable, uuid(69a39d88-d1c4-4ba9-9b19-bafc7a1bb783)]
@@ -54,17 +59,17 @@ interface nsIContentPermissionRequest : 
   readonly attribute nsIDOMWindow window;
   readonly attribute nsIDOMElement element;
 
   /**
    * allow or cancel the request
    */
 
   void cancel();
-  void allow();
+  void allow([optional] in jsval choices); // {"type1": "choice1", "type2": "choiceA"}
 };
 
 /**
  * Interface provides a way for the application to handle
  * the UI prompts associated with geo position.
  */
 [scriptable, function, uuid(F72DE90D-E954-4E69-9A61-917303029301)]
 interface nsIContentPermissionPrompt : nsISupports {
--- a/dom/ipc/Blob.cpp
+++ b/dom/ipc/Blob.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=4 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Assertions.h"
 #include "mozilla/DebugOnly.h"
 
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -18,16 +18,17 @@
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/asmjscache/AsmJSCache.h"
 #include "mozilla/dom/asmjscache/PAsmJSCacheEntryChild.h"
 #include "mozilla/dom/ExternalHelperAppChild.h"
 #include "mozilla/dom/PCrashReporterChild.h"
 #include "mozilla/dom/DOMStorageIPC.h"
 #include "mozilla/hal_sandbox/PHalChild.h"
+#include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/ipc/TestShellChild.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/PCompositorChild.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/Preferences.h"
 
@@ -38,16 +39,17 @@
 #elif defined(XP_UNIX) && !defined(XP_MACOSX)
 #include "mozilla/Sandbox.h"
 #endif
 #endif
 
 #include "mozilla/unused.h"
 
 #include "nsIConsoleListener.h"
+#include "nsIIPCBackgroundChildCreateCallback.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMemoryInfoDumper.h"
 #include "nsIMutable.h"
 #include "nsIObserverService.h"
 #include "nsIObserver.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsServiceManagerUtils.h"
@@ -305,16 +307,44 @@ SystemMessageHandledObserver::Observe(ns
     if (ContentChild::GetSingleton()) {
         ContentChild::GetSingleton()->SendSystemMessageHandled();
     }
     return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS1(SystemMessageHandledObserver, nsIObserver)
 
+class BackgroundChildPrimer MOZ_FINAL :
+  public nsIIPCBackgroundChildCreateCallback
+{
+public:
+    BackgroundChildPrimer()
+    { }
+
+    NS_DECL_ISUPPORTS
+
+private:
+    ~BackgroundChildPrimer()
+    { }
+
+    virtual void
+    ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE
+    {
+        MOZ_ASSERT(aActor, "Failed to create a PBackgroundChild actor!");
+    }
+
+    virtual void
+    ActorFailed() MOZ_OVERRIDE
+    {
+        MOZ_CRASH("Failed to create a PBackgroundChild actor!");
+    }
+};
+
+NS_IMPL_ISUPPORTS1(BackgroundChildPrimer, nsIIPCBackgroundChildCreateCallback)
+
 ContentChild* ContentChild::sSingleton;
 
 // Performs initialization that is not fork-safe, i.e. that must be done after
 // forking from the Nuwa process.
 static void
 InitOnContentProcessCreated()
 {
     // This will register cross-process observer.
@@ -446,16 +476,26 @@ ContentChild::AppendProcessId(nsACString
     }
     unsigned pid = getpid();
     aName.Append(nsPrintfCString("(pid %u)", pid));
 }
 
 void
 ContentChild::InitXPCOM()
 {
+    // Do this as early as possible to get the parent process to initialize the
+    // background thread since we'll likely need database information very soon.
+    BackgroundChild::Startup();
+
+    nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback =
+        new BackgroundChildPrimer();
+    if (!BackgroundChild::GetOrCreateForCurrentThread(callback)) {
+        MOZ_CRASH("Failed to create PBackgroundChild!");
+    }
+
     nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
     if (!svc) {
         NS_WARNING("Couldn't acquire console service");
         return;
     }
 
     mConsoleListener = new ConsoleListener(this);
     if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
@@ -601,16 +641,23 @@ ContentChild::AllocPCompositorChild(mozi
 
 PImageBridgeChild*
 ContentChild::AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport,
                                      base::ProcessId aOtherProcess)
 {
     return ImageBridgeChild::StartUpInChildProcess(aTransport, aOtherProcess);
 }
 
+PBackgroundChild*
+ContentChild::AllocPBackgroundChild(Transport* aTransport,
+                                    ProcessId aOtherProcess)
+{
+    return BackgroundChild::Alloc(aTransport, aOtherProcess);
+}
+
 bool
 ContentChild::RecvSetProcessPrivileges(const ChildPrivileges& aPrivs)
 {
   ChildPrivileges privs = (aPrivs == PRIVILEGES_DEFAULT) ?
                           GeckoChildProcessHost::DefaultChildPrivileges() :
                           aPrivs;
   // If this fails, we die.
   SetCurrentProcessPrivileges(privs);
@@ -1681,16 +1728,30 @@ bool
 ContentChild::RecvNuwaFork()
 {
 #ifdef MOZ_NUWA_PROCESS
     if (sNuwaForking) {           // No reentry.
         return true;
     }
     sNuwaForking = true;
 
+    // We want to ensure that the PBackground actor gets cloned in the Nuwa
+    // process before we freeze. Also, we have to do this to avoid deadlock.
+    // Protocols that are "opened" (e.g. PBackground, PCompositor) block the
+    // main thread to wait for the IPC thread during the open operation.
+    // NuwaSpawnWait() blocks the IPC thread to wait for the main thread when
+    // the Nuwa process is forked. Unless we ensure that the two cannot happen
+    // at the same time then we risk deadlock. Spinning the event loop here
+    // guarantees the ordering is safe for PBackground.
+    while (!BackgroundChild::GetForCurrentThread()) {
+        if (NS_WARN_IF(!NS_ProcessNextEvent())) {
+            return false;
+        }
+    }
+
     MessageLoop* ioloop = XRE_GetIOMessageLoop();
     ioloop->PostTask(FROM_HERE, NewRunnableFunction(RunNuwaFork));
     return true;
 #else
     return false; // Makes the underlying IPC channel abort.
 #endif
 }
 
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -83,16 +83,20 @@ public:
     AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
                           base::ProcessId aOtherProcess) MOZ_OVERRIDE;
     PImageBridgeChild*
     AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport,
                            base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
     virtual bool RecvSetProcessPrivileges(const ChildPrivileges& aPrivs) MOZ_OVERRIDE;
 
+    PBackgroundChild*
+    AllocPBackgroundChild(Transport* aTransport, ProcessId aOtherProcess)
+                          MOZ_OVERRIDE;
+
     virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext &aContext,
                                               const uint32_t &chromeFlags);
     virtual bool DeallocPBrowserChild(PBrowserChild*);
 
     virtual PDeviceStorageRequestChild* AllocPDeviceStorageRequestChild(const DeviceStorageParams&);
     virtual bool DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild*);
 
     virtual PBlobChild* AllocPBlobChild(const BlobConstructorParams& aParams);
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -34,16 +34,18 @@
 #include "mozilla/dom/DOMStorageIPC.h"
 #include "mozilla/dom/bluetooth/PBluetoothParent.h"
 #include "mozilla/dom/PFMRadioParent.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
 #include "mozilla/dom/GeolocationBinding.h"
 #include "mozilla/dom/telephony/TelephonyParent.h"
 #include "SmsParent.h"
 #include "mozilla/hal_sandbox/PHalParent.h"
+#include "mozilla/ipc/BackgroundChild.h"
+#include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/TestShellParent.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/layers/CompositorParent.h"
 #include "mozilla/layers/ImageBridgeParent.h"
 #include "mozilla/net/NeckoParent.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
@@ -133,16 +135,21 @@ using namespace mozilla::system;
 #endif
 
 #include "Crypto.h"
 
 #ifdef MOZ_WEBSPEECH
 #include "mozilla/dom/SpeechSynthesisParent.h"
 #endif
 
+#ifdef ENABLE_TESTS
+#include "mozilla/ipc/PBackgroundChild.h"
+#include "nsIIPCBackgroundChildCreateCallback.h"
+#endif
+
 static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
 static const char* sClipboardTextFlavors[] = { kUnicodeMime };
 
 using base::ChildPrivileges;
 using base::KillProcess;
 using namespace mozilla::dom::bluetooth;
 using namespace mozilla::dom::devicestorage;
 using namespace mozilla::dom::indexedDB;
@@ -150,16 +157,137 @@ using namespace mozilla::dom::power;
 using namespace mozilla::dom::mobilemessage;
 using namespace mozilla::dom::telephony;
 using namespace mozilla::hal;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 using namespace mozilla::net;
 using namespace mozilla::jsipc;
 
+#ifdef ENABLE_TESTS
+
+class BackgroundTester MOZ_FINAL : public nsIIPCBackgroundChildCreateCallback,
+                                   public nsIObserver
+{
+    static uint32_t sCallbackCount;
+
+private:
+    ~BackgroundTester()
+    { }
+
+    virtual void
+    ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE
+    {
+        MOZ_RELEASE_ASSERT(aActor,
+                           "Failed to create a PBackgroundChild actor!");
+
+        NS_NAMED_LITERAL_CSTRING(testStr, "0123456789");
+
+        PBackgroundTestChild* testActor =
+            aActor->SendPBackgroundTestConstructor(testStr);
+        MOZ_RELEASE_ASSERT(testActor);
+
+        if (!sCallbackCount) {
+            PBackgroundChild* existingBackgroundChild =
+                BackgroundChild::GetForCurrentThread();
+
+            MOZ_RELEASE_ASSERT(existingBackgroundChild);
+            MOZ_RELEASE_ASSERT(existingBackgroundChild == aActor);
+
+            bool ok =
+                existingBackgroundChild->
+                    SendPBackgroundTestConstructor(testStr);
+            MOZ_RELEASE_ASSERT(ok);
+
+            // Callback 3.
+            ok = BackgroundChild::GetOrCreateForCurrentThread(this);
+            MOZ_RELEASE_ASSERT(ok);
+        }
+
+        sCallbackCount++;
+    }
+
+    virtual void
+    ActorFailed() MOZ_OVERRIDE
+    {
+        MOZ_CRASH("Failed to create a PBackgroundChild actor!");
+    }
+
+    NS_IMETHOD
+    Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
+            MOZ_OVERRIDE
+    {
+        nsCOMPtr<nsIObserverService> observerService =
+            mozilla::services::GetObserverService();
+        MOZ_RELEASE_ASSERT(observerService);
+
+        nsresult rv = observerService->RemoveObserver(this, aTopic);
+        MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
+
+        if (!strcmp(aTopic, "profile-after-change")) {
+            if (mozilla::Preferences::GetBool("pbackground.testing", false)) {
+                rv = observerService->AddObserver(this, "xpcom-shutdown",
+                                                  false);
+                MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
+
+                // Callback 1.
+                bool ok = BackgroundChild::GetOrCreateForCurrentThread(this);
+                MOZ_RELEASE_ASSERT(ok);
+
+                // Callback 2.
+                ok = BackgroundChild::GetOrCreateForCurrentThread(this);
+                MOZ_RELEASE_ASSERT(ok);
+            }
+
+            return NS_OK;
+        }
+
+        if (!strcmp(aTopic, "xpcom-shutdown")) {
+            MOZ_RELEASE_ASSERT(sCallbackCount == 3);
+
+            return NS_OK;
+        }
+
+        MOZ_CRASH("Unknown observer topic!");
+    }
+
+public:
+    NS_DECL_ISUPPORTS
+};
+
+uint32_t BackgroundTester::sCallbackCount = 0;
+
+NS_IMPL_ISUPPORTS2(BackgroundTester, nsIIPCBackgroundChildCreateCallback,
+                                     nsIObserver)
+
+#endif // ENABLE_TESTS
+
+void
+MaybeTestPBackground()
+{
+#ifdef ENABLE_TESTS
+    // This test relies on running the event loop and XPCShell does not always
+    // do so. Bail out here if we detect that we're running in XPCShell.
+    if (PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR")) {
+        return;
+    }
+
+    // This is called too early at startup to test preferences directly. We have
+    // to install an observer to be notified when preferences are available.
+    nsCOMPtr<nsIObserverService> observerService =
+        mozilla::services::GetObserverService();
+    MOZ_RELEASE_ASSERT(observerService);
+
+    nsCOMPtr<nsIObserver> observer = new BackgroundTester();
+    nsresult rv = observerService->AddObserver(observer, "profile-after-change",
+                                               false);
+    MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
+#endif
+}
+
 namespace mozilla {
 namespace dom {
 
 #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
 
 class MemoryReportRequestParent : public PMemoryReportRequestParent
 {
 public:
@@ -355,20 +483,26 @@ ContentParent::StartUp()
 {
     if (XRE_GetProcessType() != GeckoProcessType_Default) {
         return;
     }
 
     // Note: This reporter measures all ContentParents.
     RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
 
+    BackgroundChild::Startup();
+
     sCanLaunchSubprocesses = true;
 
     // Try to preallocate a process that we can transform into an app later.
     PreallocatedProcessManager::AllocateAfterDelay();
+
+    // Test the PBackground infrastructure on ENABLE_TESTS builds when a special
+    // testing preference is set.
+    MaybeTestPBackground();
 }
 
 /*static*/ void
 ContentParent::ShutDown()
 {
     // No-op for now.  We rely on normal process shutdown and
     // ClearOnShutdown() to clean up our state.
     sCanLaunchSubprocesses = false;
@@ -1968,16 +2102,23 @@ ContentParent::AllocPCompositorParent(mo
 
 PImageBridgeParent*
 ContentParent::AllocPImageBridgeParent(mozilla::ipc::Transport* aTransport,
                                        base::ProcessId aOtherProcess)
 {
     return ImageBridgeParent::Create(aTransport, aOtherProcess);
 }
 
+PBackgroundParent*
+ContentParent::AllocPBackgroundParent(Transport* aTransport,
+                                      ProcessId aOtherProcess)
+{
+    return BackgroundParent::Alloc(this, aTransport, aOtherProcess);
+}
+
 bool
 ContentParent::RecvGetProcessAttributes(uint64_t* aId,
                                         bool* aIsForApp, bool* aIsForBrowser)
 {
     *aId = mChildID;
     *aIsForApp = IsForApp();
     *aIsForBrowser = mIsForBrowser;
 
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -322,16 +322,20 @@ private:
 
     PCompositorParent*
     AllocPCompositorParent(mozilla::ipc::Transport* aTransport,
                            base::ProcessId aOtherProcess) MOZ_OVERRIDE;
     PImageBridgeParent*
     AllocPImageBridgeParent(mozilla::ipc::Transport* aTransport,
                             base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
+    PBackgroundParent*
+    AllocPBackgroundParent(Transport* aTransport, ProcessId aOtherProcess)
+                           MOZ_OVERRIDE;
+
     virtual bool RecvGetProcessAttributes(uint64_t* aId,
                                           bool* aIsForApp,
                                           bool* aIsForBrowser) MOZ_OVERRIDE;
     virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline) MOZ_OVERRIDE;
 
     virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) MOZ_OVERRIDE;
 
     virtual PBrowserParent* AllocPBrowserParent(const IPCTabContext& aContext,
--- a/dom/ipc/DOMTypes.ipdlh
+++ b/dom/ipc/DOMTypes.ipdlh
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
 /* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PBlob;
 include InputStreamParams;
 
--- a/dom/ipc/FilePickerParent.cpp
+++ b/dom/ipc/FilePickerParent.cpp
@@ -1,23 +1,28 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set sw=4 ts=8 et tw=80 :
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "FilePickerParent.h"
 #include "nsComponentManagerUtils.h"
+#include "nsDOMFile.h"
+#include "nsNetCID.h"
 #include "nsIDocument.h"
+#include "nsIDOMFile.h"
 #include "nsIDOMWindow.h"
 #include "nsIFile.h"
 #include "nsISimpleEnumerator.h"
 #include "mozilla/unused.h"
+#include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/TabParent.h"
+#include "mozilla/dom/ipc/Blob.h"
 
 using mozilla::unused;
 using namespace mozilla::dom;
 
 NS_IMPL_ISUPPORTS1(FilePickerParent::FilePickerShownCallback,
                    nsIFilePickerShownCallback);
 
 NS_IMETHODIMP
@@ -34,49 +39,130 @@ FilePickerParent::FilePickerShownCallbac
 {
   mFilePickerParent = nullptr;
 }
 
 FilePickerParent::~FilePickerParent()
 {
 }
 
+// Before sending a blob to the child, we need to get its size and modification
+// date. Otherwise it will be sent as a "mystery blob" by
+// GetOrCreateActorForBlob, which will cause problems for the child
+// process. This runnable stat()s the file off the main thread.
+//
+// We run code in three places:
+// 1. The main thread calls Dispatch() to start the runnable.
+// 2. The stream transport thread stat()s the file in Run() and then dispatches
+// the same runnable on the main thread.
+// 3. The main thread sends the results over IPC.
+FilePickerParent::FileSizeAndDateRunnable::FileSizeAndDateRunnable(FilePickerParent *aFPParent,
+                                                                   nsCOMArray<nsIDOMFile>& aDomfiles)
+ : mFilePickerParent(aFPParent)
+{
+  mDomfiles.SwapElements(aDomfiles);
+}
+
+bool
+FilePickerParent::FileSizeAndDateRunnable::Dispatch()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  mEventTarget = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+  if (!mEventTarget) {
+    return false;
+  }
+
+  nsresult rv = mEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
+  return NS_SUCCEEDED(rv);
+}
+
+NS_IMETHODIMP
+FilePickerParent::FileSizeAndDateRunnable::Run()
+{
+  // If we're on the main thread, then that means we're done. Just send the
+  // results.
+  if (NS_IsMainThread()) {
+    if (mFilePickerParent) {
+      mFilePickerParent->SendFiles(mDomfiles);
+    }
+    return NS_OK;
+  }
+
+  // We're not on the main thread, so do the stat().
+  for (unsigned i = 0; i < mDomfiles.Length(); i++) {
+    uint64_t size, lastModified;
+    mDomfiles[i]->GetSize(&size);
+    mDomfiles[i]->GetMozLastModifiedDate(&lastModified);
+  }
+
+  // Dispatch ourselves back on the main thread.
+  if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
+    // It's hard to see how we can recover gracefully in this case. The child
+    // process is waiting for an IPC, but that can only happen on the main
+    // thread.
+    MOZ_CRASH();
+  }
+  return NS_OK;
+}
+
+void
+FilePickerParent::FileSizeAndDateRunnable::Destroy()
+{
+  mFilePickerParent = nullptr;
+}
+
+void
+FilePickerParent::SendFiles(const nsCOMArray<nsIDOMFile>& aDomfiles)
+{
+  ContentParent* parent = static_cast<ContentParent*>(Manager()->Manager());
+  InfallibleTArray<PBlobParent*> files;
+
+  for (unsigned i = 0; i < aDomfiles.Length(); i++) {
+    BlobParent* blob = parent->GetOrCreateActorForBlob(aDomfiles[i]);
+    if (blob) {
+      files.AppendElement(blob);
+    }
+  }
+
+  InputFiles infiles;
+  infiles.filesParent().SwapElements(files);
+  unused << Send__delete__(this, infiles, mResult);
+}
+
 void
 FilePickerParent::Done(int16_t aResult)
 {
-  InfallibleTArray<nsString> files;
+  mResult = aResult;
+
+  nsCOMArray<nsIDOMFile> domfiles;
 
   if (mMode == nsIFilePicker::modeOpenMultiple) {
     nsCOMPtr<nsISimpleEnumerator> iter;
     NS_ENSURE_SUCCESS_VOID(mFilePicker->GetFiles(getter_AddRefs(iter)));
 
     nsCOMPtr<nsIFile> file;
     bool loop = true;
     while (NS_SUCCEEDED(iter->HasMoreElements(&loop)) && loop) {
       iter->GetNext(getter_AddRefs(file));
-      if (file) {
-        nsAutoString path;
-        if (NS_SUCCEEDED(file->GetPath(path))) {
-          files.AppendElement(path);
-        }
-      }
+      nsCOMPtr<nsIDOMFile> domfile = new nsDOMFileFile(file);
+      domfiles.AppendElement(domfile);
     }
   } else {
     nsCOMPtr<nsIFile> file;
     mFilePicker->GetFile(getter_AddRefs(file));
-
-    if (file) {
-      nsAutoString path;
-      if (NS_SUCCEEDED(file->GetPath(path))) {
-        files.AppendElement(path);
-      }
-    }
+    nsCOMPtr<nsIDOMFile> domfile = new nsDOMFileFile(file);
+    domfiles.AppendElement(domfile);
   }
 
-  unused << Send__delete__(this, InputFiles(files), aResult);
+  MOZ_ASSERT(!mRunnable);
+  mRunnable = new FileSizeAndDateRunnable(this, domfiles);
+  if (!mRunnable->Dispatch()) {
+    unused << Send__delete__(this, void_t(), nsIFilePicker::returnCancel);
+  }
 }
 
 bool
 FilePickerParent::CreateFilePicker()
 {
   mFilePicker = do_CreateInstance("@mozilla.org/filepicker;1");
   if (!mFilePicker) {
     return false;
@@ -124,10 +210,15 @@ FilePickerParent::RecvOpen(const int16_t
   return true;
 }
 
 void
 FilePickerParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   if (mCallback) {
     mCallback->Destroy();
+    mCallback = nullptr;
+  }
+  if (mRunnable) {
+    mRunnable->Destroy();
+    mRunnable = nullptr;
   }
 }
--- a/dom/ipc/FilePickerParent.h
+++ b/dom/ipc/FilePickerParent.h
@@ -2,17 +2,21 @@
  * vim: set sw=4 ts=8 et tw=80 :
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_FilePickerParent_h
 #define mozilla_dom_FilePickerParent_h
 
+#include "nsIDOMFile.h"
+#include "nsIEventTarget.h"
 #include "nsIFilePicker.h"
+#include "nsCOMArray.h"
+#include "nsThreadUtils.h"
 #include "mozilla/dom/PFilePickerParent.h"
 
 namespace mozilla {
 namespace dom {
 
 class FilePickerParent : public PFilePickerParent
 {
  public:
@@ -20,16 +24,17 @@ class FilePickerParent : public PFilePic
                    const int16_t& aMode)
   : mTitle(aTitle)
   , mMode(aMode)
   {}
 
   virtual ~FilePickerParent();
 
   void Done(int16_t aResult);
+  void SendFiles(const nsCOMArray<nsIDOMFile>& aDomfiles);
 
   virtual bool RecvOpen(const int16_t& aSelectedType,
                         const bool& aAddToRecentDocs,
                         const nsString& aDefaultFile,
                         const nsString& aDefaultExtension,
                         const InfallibleTArray<nsString>& aFilters,
                         const InfallibleTArray<nsString>& aFilterNames) MOZ_OVERRIDE;
 
@@ -50,19 +55,34 @@ class FilePickerParent : public PFilePic
 
   private:
     FilePickerParent* mFilePickerParent;
   };
 
  private:
   bool CreateFilePicker();
 
+  class FileSizeAndDateRunnable : public nsRunnable
+  {
+    FilePickerParent* mFilePickerParent;
+    nsCOMArray<nsIDOMFile> mDomfiles;
+    nsCOMPtr<nsIEventTarget> mEventTarget;
+
+  public:
+    FileSizeAndDateRunnable(FilePickerParent *aFPParent, nsCOMArray<nsIDOMFile>& aDomfiles);
+    bool Dispatch();
+    NS_IMETHOD Run();
+    void Destroy();
+  };
+
+  nsRefPtr<FileSizeAndDateRunnable> mRunnable;
   nsRefPtr<FilePickerShownCallback> mCallback;
   nsCOMPtr<nsIFilePicker> mFilePicker;
 
   nsString mTitle;
   int16_t mMode;
+  int16_t mResult;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */
 /* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PAsmJSCacheEntry;
+include protocol PBackground;
 include protocol PBlob;
 include protocol PBluetooth;
 include protocol PBrowser;
 include protocol PCompositor;
 include protocol PCrashReporter;
 include protocol PExternalHelperApp;
 include protocol PDeviceStorageRequest;
 include protocol PFMRadio;
@@ -194,16 +195,17 @@ struct PrefSetting {
   MaybePrefValue defaultValue;
   MaybePrefValue userValue;
 };
 
 intr protocol PContent
 {
     parent opens PCompositor;
     parent opens PImageBridge;
+    child opens PBackground;
 
     manages PAsmJSCacheEntry;
     manages PBlob;
     manages PBluetooth;
     manages PBrowser;
     manages PCrashReporter;
     manages PDeviceStorageRequest;
     manages PExternalHelperApp;
--- a/dom/ipc/PContentPermission.ipdlh
+++ b/dom/ipc/PContentPermission.ipdlh
@@ -3,12 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 namespace mozilla {
 namespace dom {
 
 struct PermissionRequest {
   nsCString type;
   nsCString access;
+  nsString[] options;
+};
+
+struct PermissionChoice {
+  nsCString type;
+  nsString choice;
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/PContentPermissionRequest.ipdl
+++ b/dom/ipc/PContentPermissionRequest.ipdl
@@ -1,23 +1,24 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PBrowser;
+include PContentPermission;
 
 namespace mozilla {
 namespace dom {
 
 protocol PContentPermissionRequest
 {
   manager PBrowser;
 
 parent:
   prompt();
 
 child:
-  __delete__(bool allow);
+  __delete__(bool allow, PermissionChoice[] choices);
 };
 
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/PFilePicker.ipdl
+++ b/dom/ipc/PFilePicker.ipdl
@@ -1,24 +1,25 @@
 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
 /* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+include protocol PBlob;
 include protocol PBrowser;
 
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 
 namespace mozilla {
 namespace dom {
 
 struct InputFiles
 {
-  nsString[] files;
+  PBlob[] files;
 };
 
 union MaybeInputFiles
 {
   InputFiles;
   void_t;
 };
 
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -541,29 +541,30 @@ TabChild::HandlePossibleViewportChange()
   mWebNav->GetDocument(getter_AddRefs(domDoc));
   nsCOMPtr<nsIDocument> document(do_QueryInterface(domDoc));
 
   nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
 
   nsViewportInfo viewportInfo = nsContentUtils::GetViewportInfo(document, mInnerSize);
   uint32_t presShellId;
   ViewID viewId;
-  if (APZCCallbackHelper::GetScrollIdentifiers(document->GetDocumentElement(),
-                                               &presShellId, &viewId)) {
+  bool scrollIdentifiersValid = APZCCallbackHelper::GetScrollIdentifiers(
+        document->GetDocumentElement(), &presShellId, &viewId);
+  if (scrollIdentifiersValid) {
     ZoomConstraints constraints(
       viewportInfo.IsZoomAllowed(),
+      viewportInfo.IsDoubleTapZoomAllowed(),
       viewportInfo.GetMinZoom(),
       viewportInfo.GetMaxZoom());
     SendUpdateZoomConstraints(presShellId,
                               viewId,
                               /* isRoot = */ true,
                               constraints);
   }
 
-
   float screenW = mInnerSize.width;
   float screenH = mInnerSize.height;
   CSSSize viewport(viewportInfo.GetSize());
 
   // We're not being displayed in any way; don't bother doing anything because
   // that will just confuse future adjustments.
   if (!screenW || !screenH) {
     return;
@@ -656,16 +657,35 @@ TabChild::HandlePossibleViewportChange()
     // Return early rather than divide by 0.
     return;
   }
   metrics.mScrollableRect = CSSRect(CSSPoint(), pageSize);
 
   // Force a repaint with these metrics. This, among other things, sets the
   // displayport, so we start with async painting.
   ProcessUpdateFrame(metrics);
+
+  if (viewportInfo.IsZoomAllowed() && scrollIdentifiersValid) {
+    // If the CSS viewport is narrower than the screen (i.e. width <= device-width)
+    // then we disable double-tap-to-zoom behaviour.
+    bool allowDoubleTapZoom = (viewport.width > screenW / metrics.mDevPixelsPerCSSPixel.scale);
+    if (allowDoubleTapZoom != viewportInfo.IsDoubleTapZoomAllowed()) {
+      viewportInfo.SetAllowDoubleTapZoom(allowDoubleTapZoom);
+
+      ZoomConstraints constraints(
+        viewportInfo.IsZoomAllowed(),
+        viewportInfo.IsDoubleTapZoomAllowed(),
+        viewportInfo.GetMinZoom(),
+        viewportInfo.GetMaxZoom());
+      SendUpdateZoomConstraints(presShellId,
+                                viewId,
+                                /* isRoot = */ true,
+                                constraints);
+    }
+  }
 }
 
 nsresult
 TabChild::Init()
 {
   nsCOMPtr<nsIWebBrowser> webBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
   if (!webBrowser) {
     NS_ERROR("Couldn't create a nsWebBrowser?");
@@ -2555,22 +2575,22 @@ TabChild::DoSendBlockingMessage(JSContex
   }
   InfallibleTArray<CpowEntry> cpows;
   if (sCpowsEnabled) {
     if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
       return false;
     }
   }
   if (aIsSync) {
-    return SendSyncMessage(nsString(aMessage), data, cpows, aPrincipal,
-                           aJSONRetVal);
+    return SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
+                           aPrincipal, aJSONRetVal);
   }
 
-  return CallRpcMessage(nsString(aMessage), data, cpows, aPrincipal,
-                        aJSONRetVal);
+  return CallRpcMessage(PromiseFlatString(aMessage), data, cpows,
+                        aPrincipal, aJSONRetVal);
 }
 
 bool
 TabChild::DoSendAsyncMessage(JSContext* aCx,
                              const nsAString& aMessage,
                              const StructuredCloneData& aData,
                              JS::Handle<JSObject *> aCpows,
                              nsIPrincipal* aPrincipal)
@@ -2581,17 +2601,17 @@ TabChild::DoSendAsyncMessage(JSContext* 
     return false;
   }
   InfallibleTArray<CpowEntry> cpows;
   if (sCpowsEnabled) {
     if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
       return false;
     }
   }
-  return SendAsyncMessage(nsString(aMessage), data, cpows,
+  return SendAsyncMessage(PromiseFlatString(aMessage), data, cpows,
                           aPrincipal);
 }
 
 TabChild*
 TabChild::GetFrom(nsIPresShell* aPresShell)
 {
   nsIDocument* doc = aPresShell->GetDocument();
   if (!doc) {
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -119,9 +119,13 @@ DEFINES['BIN_SUFFIX'] = '"%s"' % CONFIG[
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gonk', 'qt'):
     DEFINES['MOZ_ENABLE_FREETYPE'] = True
 
 for var in ('MOZ_PERMISSIONS', 'MOZ_CHILD_PERMISSIONS'):
     if CONFIG[var]:
         DEFINES[var] = True
 
+if CONFIG['ENABLE_TESTS']:
+    DEFINES['ENABLE_TESTS'] = 1
+
 JAR_MANIFESTS += ['jar.mn']
+
--- a/dom/media/MediaPermissionGonk.cpp
+++ b/dom/media/MediaPermissionGonk.cpp
@@ -5,17 +5,19 @@
 #include "MediaManager.h"
 #include "MediaPermissionGonk.h"
 
 #include "nsCOMPtr.h"
 #include "nsCxPusher.h"
 #include "nsIContentPermissionPrompt.h"
 #include "nsIDocument.h"
 #include "nsIDOMNavigatorUserMedia.h"
+#include "nsIStringEnumerator.h"
 #include "nsISupportsArray.h"
+#include "nsJSUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsTArray.h"
 #include "GetUserMediaRequest.h"
 #include "PCOMContentPermissionRequestChild.h"
 #include "mozilla/dom/PBrowserChild.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/MediaStreamTrackBinding.h"
 #include "nsISupportsPrimitives.h"
@@ -40,21 +42,64 @@ ConvertArrayToPermissionRequest(nsIArray
   uint32_t len = 0;
   aSrcArray->GetLength(&len);
   for (uint32_t i = 0; i < len; i++) {
     nsCOMPtr<nsIContentPermissionType> cpt = do_QueryElementAt(aSrcArray, i);
     nsAutoCString type;
     nsAutoCString access;
     cpt->GetType(type);
     cpt->GetAccess(access);
-    aDesArray.AppendElement(PermissionRequest(type, access));
+
+    nsCOMPtr<nsIArray> optionArray;
+    cpt->GetOptions(getter_AddRefs(optionArray));
+    uint32_t optionsLength = 0;
+    optionArray->GetLength(&optionsLength);
+    nsTArray<nsString> options;
+    for (uint32_t j = 0; j < optionsLength; ++j) {
+      nsCOMPtr<nsISupportsString> isupportsString = do_QueryElementAt(optionArray, j);
+      if (isupportsString) {
+        nsString option;
+        isupportsString->GetData(option);
+        options.AppendElement(option);
+      }
+    }
+
+    aDesArray.AppendElement(PermissionRequest(type, access, options));
   }
   return len;
 }
 
+static void
+CreateDeviceNameList(nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices,
+                     nsTArray<nsString> &aDeviceNameList)
+{
+  for (uint32_t i = 0; i < aDevices.Length(); ++i) {
+     nsString name;
+     nsresult rv = aDevices[i]->GetName(name);
+     NS_ENSURE_SUCCESS_VOID(rv);
+     aDeviceNameList.AppendElement(name);
+  }
+}
+
+static already_AddRefed<nsIMediaDevice>
+FindDeviceByName(nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices,
+                 const nsAString &aDeviceName)
+{
+  for (uint32_t i = 0; i < aDevices.Length(); ++i) {
+    nsCOMPtr<nsIMediaDevice> device = aDevices[i];
+    nsString deviceName;
+    device->GetName(deviceName);
+    if (deviceName.Equals(aDeviceName)) {
+      return device.forget();
+    }
+  }
+
+  return nullptr;
+}
+
 // Helper function for notifying permission granted
 static nsresult
 NotifyPermissionAllow(const nsAString &aCallID, nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
 {
   nsresult rv;
   nsCOMPtr<nsISupportsArray> array;
   rv = NS_NewISupportsArray(getter_AddRefs(array));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -103,26 +148,30 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTPERMISSIONREQUEST
 
   MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest> &aRequest,
                          nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices);
   virtual ~MediaPermissionRequest() {}
 
   // It will be called when prompt dismissed.
-  virtual bool Recv__delete__(const bool &allow) MOZ_OVERRIDE;
+  virtual bool Recv__delete__(const bool &allow,
+                              const InfallibleTArray<PermissionChoice>& choices) MOZ_OVERRIDE;
   virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
 
   already_AddRefed<nsPIDOMWindow> GetOwner();
 
 private:
+  nsresult DoAllow(const nsString &audioDevice, const nsString &videoDevice);
+
   bool mAudio; // Request for audio permission
   bool mVideo; // Request for video permission
   nsRefPtr<dom::GetUserMediaRequest> mRequest;
-  nsTArray<nsCOMPtr<nsIMediaDevice> > mDevices; // candiate device list
+  nsTArray<nsCOMPtr<nsIMediaDevice> > mAudioDevices; // candidate audio devices
+  nsTArray<nsCOMPtr<nsIMediaDevice> > mVideoDevices; // candidate video devices
 };
 
 // MediaPermissionRequest
 NS_IMPL_ISUPPORTS1(MediaPermissionRequest, nsIContentPermissionRequest)
 
 MediaPermissionRequest::MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest> &aRequest,
                                                nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
   : mRequest(aRequest)
@@ -133,39 +182,46 @@ MediaPermissionRequest::MediaPermissionR
   mAudio = constraints.mAudio;
   mVideo = constraints.mVideo;
 
   for (uint32_t i = 0; i < aDevices.Length(); ++i) {
     nsCOMPtr<nsIMediaDevice> device(aDevices[i]);
     nsAutoString deviceType;
     device->GetType(deviceType);
     if (mAudio && deviceType.EqualsLiteral("audio")) {
-      mDevices.AppendElement(device);
+      mAudioDevices.AppendElement(device);
     }
     if (mVideo && deviceType.EqualsLiteral("video")) {
-      mDevices.AppendElement(device);
+      mVideoDevices.AppendElement(device);
     }
   }
 }
 
 // nsIContentPermissionRequest methods
 NS_IMETHODIMP
 MediaPermissionRequest::GetTypes(nsIArray** aTypes)
 {
   nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
+  //XXX append device list
   if (mAudio) {
+    nsTArray<nsString> audioDeviceNames;
+    CreateDeviceNameList(mAudioDevices, audioDeviceNames);
     nsCOMPtr<ContentPermissionType> AudioType =
       new ContentPermissionType(NS_LITERAL_CSTRING(AUDIO_PERMISSION_NAME),
-                                NS_LITERAL_CSTRING("unused"));
+                                NS_LITERAL_CSTRING("unused"),
+                                audioDeviceNames);
     types->AppendElement(AudioType, false);
   }
   if (mVideo) {
+    nsTArray<nsString> videoDeviceNames;
+    CreateDeviceNameList(mVideoDevices, videoDeviceNames);
     nsCOMPtr<ContentPermissionType> VideoType =
       new ContentPermissionType(NS_LITERAL_CSTRING(VIDEO_PERMISSION_NAME),
-                                NS_LITERAL_CSTRING("unused"));
+                                NS_LITERAL_CSTRING("unused"),
+                                videoDeviceNames);
     types->AppendElement(VideoType, false);
   }
   NS_IF_ADDREF(*aTypes = types);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -207,38 +263,111 @@ MediaPermissionRequest::Cancel()
 {
   nsString callID;
   mRequest->GetCallID(callID);
   NotifyPermissionDeny(callID, NS_LITERAL_STRING("Permission Denied"));
   return NS_OK;
 }
 
 NS_IMETHODIMP
-MediaPermissionRequest::Allow()
+MediaPermissionRequest::Allow(JS::HandleValue aChoices)
 {
+  // check if JS object
+  if (!aChoices.isObject()) {
+    MOZ_ASSERT(false, "Not a correct format of PermissionChoice");
+    return NS_ERROR_INVALID_ARG;
+  }
+  // iterate through audio-capture and video-capture
+  AutoSafeJSContext cx;
+  JS::Rooted<JSObject*> obj(cx, &aChoices.toObject());
+  JSAutoCompartment ac(cx, obj);
+  JS::Rooted<JS::Value> v(cx);
+
+  // get selected audio device name
+  nsString audioDevice;
+  if (mAudio) {
+    if (!JS_GetProperty(cx, obj, AUDIO_PERMISSION_NAME, &v) || !v.isString()) {
+      return NS_ERROR_FAILURE;
+    }
+    nsDependentJSString deviceName;
+    if (!deviceName.init(cx, v)) {
+      MOZ_ASSERT(false, "Couldn't initialize string from aChoices");
+      return NS_ERROR_FAILURE;
+    }
+    audioDevice = deviceName;
+  }
+
+  // get selected video device name
+  nsString videoDevice;
+  if (mVideo) {
+    if (!JS_GetProperty(cx, obj, VIDEO_PERMISSION_NAME, &v) || !v.isString()) {
+      return NS_ERROR_FAILURE;
+    }
+    nsDependentJSString deviceName;
+    if (!deviceName.init(cx, v)) {
+      MOZ_ASSERT(false, "Couldn't initialize string from aChoices");
+      return NS_ERROR_FAILURE;
+    }
+    videoDevice = deviceName;
+  }
+
+  return DoAllow(audioDevice, videoDevice);
+}
+
+nsresult
+MediaPermissionRequest::DoAllow(const nsString &audioDevice,
+                                const nsString &videoDevice)
+{
+  nsTArray<nsCOMPtr<nsIMediaDevice> > selectedDevices;
+  if (mAudio) {
+    nsCOMPtr<nsIMediaDevice> device =
+      FindDeviceByName(mAudioDevices, audioDevice);
+    if (device) {
+      selectedDevices.AppendElement(device);
+    }
+  }
+
+  if (mVideo) {
+    nsCOMPtr<nsIMediaDevice> device =
+      FindDeviceByName(mVideoDevices, videoDevice);
+    if (device) {
+      selectedDevices.AppendElement(device);
+    }
+  }
+
   nsString callID;
   mRequest->GetCallID(callID);
-  NotifyPermissionAllow(callID, mDevices);
-  return NS_OK;
+  return NotifyPermissionAllow(callID, selectedDevices);
 }
 
 already_AddRefed<nsPIDOMWindow>
 MediaPermissionRequest::GetOwner()
 {
   nsCOMPtr<nsPIDOMWindow> window = static_cast<nsPIDOMWindow*>
       (nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID()));
   return window.forget();
 }
 
 //PCOMContentPermissionRequestChild
 bool
-MediaPermissionRequest::Recv__delete__(const bool& allow)
+MediaPermissionRequest::Recv__delete__(const bool& allow,
+                                       const InfallibleTArray<PermissionChoice>& choices)
 {
   if (allow) {
-    (void) Allow();
+    // get selected device name for audio and video
+    nsString audioDevice, videoDevice;
+    for (uint32_t i = 0; i < choices.Length(); ++i) {
+      const nsString &choice = choices[i].choice();
+      if (choices[i].type().EqualsLiteral(AUDIO_PERMISSION_NAME)) {
+        audioDevice = choice;
+      } else if (choices[i].type().EqualsLiteral(VIDEO_PERMISSION_NAME)) {
+        videoDevice = choice;
+      }
+    }
+    (void) DoAllow(audioDevice, videoDevice);
   } else {
     (void) Cancel();
   }
   return true;
 }
 
 // Success callback for MediaManager::GetUserMediaDevices().
 class MediaDeviceSuccessCallback: public nsIGetUserMediaDevicesSuccessCallback
--- a/dom/media/tests/crashtests/791330.html
+++ b/dom/media/tests/crashtests/791330.html
@@ -7,17 +7,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <meta charset="utf-8">
   <title>PeerConnection test - operate on closed connection</title>
   <script type="application/javascript">
     function finish() {
       document.documentElement.removeAttribute("class");
     }
 
     function runTest() {
-      var pc = mozRTCPeerConnection();
+      var pc = new mozRTCPeerConnection();
       pc.close();
 
       navigator.mozGetUserMedia({audio: true, fake: true}, function (stream) {
         try {
           pc.addStream(stream);
           pc.createOffer(function (offer) {});
         }
         finally {
--- a/dom/media/tests/crashtests/799419.html
+++ b/dom/media/tests/crashtests/799419.html
@@ -7,18 +7,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <meta charset="utf-8">
   <title>2 Peer Connections Create and Close + Fake Video</title>
   <script type="application/javascript">
     function finish() {
       document.documentElement.removeAttribute("class");
     }
 
     function boom() {
-      var v0 = mozRTCPeerConnection();
-      var v1 = mozRTCPeerConnection();
+      var v0 = new mozRTCPeerConnection();
+      var v1 = new mozRTCPeerConnection();
       var v2 = document.getElementById("pc1video");
       var v3 = document.getElementById("pc2video");
       navigator.mozGetUserMedia({video:true, fake: true},
         function(stream) {}, function() {});
       v0.close();
       v1.close();
 
       finish();
--- a/dom/media/tests/crashtests/837324.html
+++ b/dom/media/tests/crashtests/837324.html
@@ -7,17 +7,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <meta charset="utf-8">
   <title>Bug 837324</title>
   <script type="application/javascript">
     function finish() {
       document.documentElement.removeAttribute("class");
     }
 
     function start() {
-      var o0 = mozRTCPeerConnection();
+      var o0 = new mozRTCPeerConnection();
       var o1 = new mozRTCIceCandidate({"candidate":"0 -65535 IP 0 stun.sipgate.net 3227326073 type ::ffff:192.0.2.128 host 2302600701","sdpMid":"video 3907077665 RTP/SAVPF 5000","sdpMLineIndex":7});
       try {o0.addIceCandidate(o1);} catch(e) {} // bug 842075 - remove try when fixed
 
       finish();
     }
   </script>
 </head>
 
--- a/dom/media/tests/mochitest/test_peerConnection_addCandidateInHaveLocalOffer.html
+++ b/dom/media/tests/mochitest/test_peerConnection_addCandidateInHaveLocalOffer.html
@@ -21,17 +21,17 @@
     test = new PeerConnectionTest();
     test.setMediaConstraints([{audio: true}], [{audio: true}]);
     test.chain.removeAfter("PC_LOCAL_SET_LOCAL_DESCRIPTION");
 
     test.chain.append([[
       "PC_LOCAL_ADD_CANDIDATE",
       function (test) {
         test.pcLocal.addIceCandidateAndFail(
-          mozRTCIceCandidate(
+          new mozRTCIceCandidate(
             {candidate:"1 1 UDP 2130706431 192.168.2.1 50005 typ host",
              sdpMLineIndex: 1}),
           function(err) {
             is(err.name, "INVALID_STATE", "Error is INVALID_STATE");
             test.next();
           } );
       }
     ]]);
--- a/dom/permission/PermissionPromptHelper.jsm
+++ b/dom/permission/PermissionPromptHelper.jsm
@@ -69,20 +69,30 @@ this.PermissionPromptHelper = {
 
     if (permValue == Ci.nsIPermissionManager.DENY_ACTION ||
         permValue == Ci.nsIPermissionManager.UNKNOWN_ACTION) {
       aCallbacks.cancel();
       return;
     }
 
     if (permValue == Ci.nsIPermissionManager.PROMPT_ACTION) {
+
+      // create the options from permission request.
+      let options = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
+      if (msg.options) {
+        for (let option of options) {
+          options.appendElement(option);
+        }
+      }
+
       // create an array with a nsIContentPermissionType element
       let type = {
         type: msg.type,
         access: msg.access ? msg.access : "unused",
+        options: options,
         QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionType])
       };
       let typeArray = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
       typeArray.appendElement(type, false);
 
       // create a nsIContentPermissionRequest
       let request = {
         types: typeArray,
@@ -117,19 +127,20 @@ this.PermissionPromptHelper = {
     let result;
     if (aMessage.name == "PermissionPromptHelper:AskPermission") {
       this.askPermission(aMessage, {
         cancel: function() {
           mm.sendAsyncMessage("PermissionPromptHelper:AskPermission:OK",
                               { result: Ci.nsIPermissionManager.DENY_ACTION,
                                 requestID: msg.requestID });
         },
-        allow: function() {
+        allow: function(aChoice) {
           mm.sendAsyncMessage("PermissionPromptHelper:AskPermission:OK",
                               { result: Ci.nsIPermissionManager.ALLOW_ACTION,
+                                choice: aChoice,
                                 requestID: msg.requestID });
         }
       });
     }
   }
 }
 
 PermissionPromptHelper.init();
--- a/dom/phonenumberutils/PhoneNumberMetaData.jsm
+++ b/dom/phonenumberutils/PhoneNumberMetaData.jsm
@@ -18,17 +18,17 @@ this.PHONE_NUMBER_META_DATA = {
 "266": '["LS","00",,,,,"\\d{8}","[2568]\\d{7}",[["(\\d{4})(\\d{4})","$1 $2",,,]]]',
 "245": '["GW","00",,,,,"\\d{7}","[3-79]\\d{6}",[["(\\d{3})(\\d{4})","$1 $2",,,]]]',
 "374": '["AM","00","0",,,"($NP$FG)","\\d{5,8}","[1-9]\\d{7}",[["(\\d{2})(\\d{6})","$1 $2","1|47",,],["(\\d{2})(\\d{6})","$1 $2","[5-7]|9[1-9]","$NP$FG",],["(\\d{3})(\\d{5})","$1 $2","[23]",,],["(\\d{3})(\\d{2})(\\d{3})","$1 $2 $3","8|90","$NP $FG",]]]',
 "379": '["VA","00",,,,,"\\d{10}","06\\d{8}",[["(06)(\\d{4})(\\d{4})","$1 $2 $3",,,]]]',
 "61": ['["AU","(?:14(?:1[14]|34|4[17]|[56]6|7[47]|88))?001[14-689]","0",,,,"\\d{6,10}","[1-578]\\d{5,9}",[["([2378])(\\d{4})(\\d{4})","$1 $2 $3","[2378]","($NP$FG)",],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","[45]|14","$NP$FG",],["(16)(\\d{3})(\\d{2,4})","$1 $2 $3","16","$NP$FG",],["(1[389]\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","1(?:[38]0|90)","$FG",],["(180)(2\\d{3})","$1 $2","180","$FG",],["(19\\d)(\\d{3})","$1 $2","19[13]","$FG",],["(19\\d{2})(\\d{4})","$1 $2","19[67]","$FG",],["(13)(\\d{2})(\\d{2})","$1 $2 $3","13[1-9]","$FG",]]]','["CC","(?:14(?:1[14]|34|4[17]|[56]6|7[47]|88))?001[14-689]","0",,,,"\\d{6,10}","[1458]\\d{5,9}",]','["CX","(?:14(?:1[14]|34|4[17]|[56]6|7[47]|88))?001[14-689]","0",,,,"\\d{6,10}","[1458]\\d{5,9}",]'],
 "500": '["FK","00",,,,,"\\d{5}","[2-7]\\d{4}",]',
 "261": '["MG","00","0",,,"$NP$FG","\\d{7,9}","[23]\\d{8}",[["([23]\\d)(\\d{2})(\\d{3})(\\d{2})","$1 $2 $3 $4",,,]]]',
 "92": '["PK","00","0",,,"($NP$FG)","\\d{6,12}","1\\d{8}|[2-8]\\d{5,11}|9(?:[013-9]\\d{4,9}|2\\d(?:111\\d{6}|\\d{3,7}))",[["(\\d{2})(111)(\\d{3})(\\d{3})","$1 $2 $3 $4","(?:2[125]|4[0-246-9]|5[1-35-7]|6[1-8]|7[14]|8[16]|91)1",,],["(\\d{3})(111)(\\d{3})(\\d{3})","$1 $2 $3 $4","2[349]|45|54|60|72|8[2-5]|9[2-9]",,],["(\\d{2})(\\d{7,8})","$1 $2","(?:2[125]|4[0-246-9]|5[1-35-7]|6[1-8]|7[14]|8[16]|91)[2-9]",,],["(\\d{3})(\\d{6,7})","$1 $2","2[349]|45|54|60|72|8[2-5]|9[2-9]",,],["(3\\d{2})(\\d{7})","$1 $2","3","$NP$FG",],["([15]\\d{3})(\\d{5,6})","$1 $2","58[12]|1",,],["(586\\d{2})(\\d{5})","$1 $2","586",,],["([89]00)(\\d{3})(\\d{2})","$1 $2 $3","[89]00","$NP$FG",]]]',
-"234": '["NG","009","0",,,"$NP$FG","\\d{5,14}","[1-69]\\d{5,8}|[78]\\d{5,13}",[["([129])(\\d{3})(\\d{3,4})","$1 $2 $3","[129]",,],["([3-8]\\d)(\\d{3})(\\d{2,3})","$1 $2 $3","[3-6]|7(?:[1-79]|0[1-9])|8[2-9]",,],["([78]\\d{2})(\\d{3})(\\d{3,4})","$1 $2 $3","70|8[01]",,],["([78]00)(\\d{4})(\\d{4,5})","$1 $2 $3","[78]00",,],["([78]00)(\\d{5})(\\d{5,6})","$1 $2 $3","[78]00",,],["(78)(\\d{2})(\\d{3})","$1 $2 $3","78",,]]]',
+"234": '["NG","009","0",,,"$NP$FG","\\d{5,14}","[1-6]\\d{5,8}|9\\d{5,9}|[78]\\d{5,13}",[["([129])(\\d{3})(\\d{3,4})","$1 $2 $3","[129]",,],["(\\d{2})(\\d{3})(\\d{2,3})","$1 $2 $3","[3-6]|7(?:[1-79]|0[1-9])|8[2-9]",,],["(\\d{3})(\\d{3})(\\d{3,4})","$1 $2 $3","70|8[01]|90[39]",,],["([78]00)(\\d{4})(\\d{4,5})","$1 $2 $3","[78]00",,],["([78]00)(\\d{5})(\\d{5,6})","$1 $2 $3","[78]00",,],["(78)(\\d{2})(\\d{3})","$1 $2 $3","78",,]]]',
 "350": '["GI","00",,,,,"\\d{8}","[2568]\\d{7}",[["(\\d{3})(\\d{5})","$1 $2","2",,]]]',
 "45": '["DK","00",,,,,"\\d{8}","[2-9]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
 "963": '["SY","00","0",,,"$NP$FG","\\d{6,9}","[1-59]\\d{7,8}",[["(\\d{2})(\\d{3})(\\d{3,4})","$1 $2 $3","[1-5]",,],["(9\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","9",,]]]',
 "226": '["BF","00",,,,,"\\d{8}","[24-7]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
 "974": '["QA","00",,,,,"\\d{7,8}","[2-8]\\d{6,7}",[["([28]\\d{2})(\\d{4})","$1 $2","[28]",,],["([3-7]\\d{3})(\\d{4})","$1 $2","[3-7]",,]]]',
 "218": '["LY","00","0",,,"$NP$FG","\\d{7,9}","[25679]\\d{8}",[["([25679]\\d)(\\d{7})","$1-$2",,,]]]',
 "51": '["PE","19(?:1[124]|77|90)00","0",,,"($NP$FG)","\\d{6,9}","[14-9]\\d{7,8}",[["(1)(\\d{7})","$1 $2","1",,],["([4-8]\\d)(\\d{6})","$1 $2","[4-7]|8[2-4]",,],["(\\d{3})(\\d{5})","$1 $2","80",,],["(9\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","9","$FG",]]]',
 "62": '["ID","0(?:0[1789]|10(?:00|1[67]))","0",,,"$NP$FG","\\d{5,11}","[1-9]\\d{6,10}",[["(\\d{2})(\\d{7,8})","$1 $2","2[124]|[36]1","($NP$FG)",],["(\\d{3})(\\d{5,7})","$1 $2","[4579]|2[035-9]|[36][02-9]","($NP$FG)",],["(8\\d{2})(\\d{3,4})(\\d{3,4})","$1-$2-$3","8[1-35-9]",,],["(177)(\\d{6,8})","$1 $2","1",,],["(800)(\\d{5,7})","$1 $2","800",,],["(809)(\\d)(\\d{3})(\\d{3})","$1 $2 $3 $4","809",,]]]',
@@ -46,61 +46,61 @@ this.PHONE_NUMBER_META_DATA = {
 "267": '["BW","00",,,,,"\\d{7,8}","[2-79]\\d{6,7}",[["(\\d{3})(\\d{4})","$1 $2","[2-6]",,],["(7\\d)(\\d{3})(\\d{3})","$1 $2 $3","7",,],["(90)(\\d{5})","$1 $2","9",,]]]',
 "94": '["LK","00","0",,,"$NP$FG","\\d{7,9}","[1-9]\\d{8}",[["(\\d{2})(\\d{1})(\\d{6})","$1 $2 $3","[1-689]",,],["(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","7",,]]]',
 "356": '["MT","00",,,,,"\\d{8}","[2357-9]\\d{7}",[["(\\d{4})(\\d{4})","$1 $2",,,]]]',
 "375": '["BY","810","8","8?0?",,,"\\d{7,11}","[1-4]\\d{8}|[89]\\d{9,10}",[["(\\d{2})(\\d{3})(\\d{2})(\\d{2})","$1 $2-$3-$4","17[0-3589]|2[4-9]|[34]","$NP 0$FG",],["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2-$3-$4","1(?:5[24]|6[235]|7[467])|2(?:1[246]|2[25]|3[26])","$NP 0$FG",],["(\\d{4})(\\d{2})(\\d{3})","$1 $2-$3","1(?:5[169]|6[3-5]|7[179])|2(?:1[35]|2[34]|3[3-5])","$NP 0$FG",],["([89]\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","8[01]|9","$NP $FG",],["(8\\d{2})(\\d{4})(\\d{4})","$1 $2 $3","82","$NP $FG",]]]',
 "690": '["TK","00",,,,,"\\d{4}","[2-9]\\d{3}",]',
 "507": '["PA","00",,,,,"\\d{7,8}","[1-9]\\d{6,7}",[["(\\d{3})(\\d{4})","$1-$2","[1-57-9]",,],["(\\d{4})(\\d{4})","$1-$2","6",,]]]',
 "692": '["MH","011","1",,,,"\\d{7}","[2-6]\\d{6}",[["(\\d{3})(\\d{4})","$1-$2",,,]]]',
 "250": '["RW","00","0",,,,"\\d{8,9}","[027-9]\\d{7,8}",[["(2\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","2","$FG",],["([7-9]\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","[7-9]","$NP$FG",],["(0\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","0",,]]]',
-"81": '["JP","010","0",,,"$NP$FG","\\d{7,16}","[1-9]\\d{8,9}|0(?:[36]\\d{7,14}|7\\d{5,7}|8\\d{7})",[["(\\d{3})(\\d{3})(\\d{3})","$1-$2-$3","(?:12|57|99)0",,],["(\\d{3})(\\d{3})(\\d{4})","$1-$2-$3","800",,],["(\\d{3})(\\d{4})","$1-$2","077",,],["(\\d{3})(\\d{2})(\\d{3,4})","$1-$2-$3","077",,],["(\\d{3})(\\d{2})(\\d{4})","$1-$2-$3","088",,],["(\\d{3})(\\d{3})(\\d{3,4})","$1-$2-$3","0(?:37|66)",,],["(\\d{3})(\\d{4})(\\d{4,5})","$1-$2-$3","0(?:37|66)",,],["(\\d{3})(\\d{5})(\\d{5,6})","$1-$2-$3","0(?:37|66)",,],["(\\d{3})(\\d{6})(\\d{6,7})","$1-$2-$3","0(?:37|66)",,],["(\\d{2})(\\d{4})(\\d{4})","$1-$2-$3","[2579]0|80[1-9]",,],["(\\d{4})(\\d)(\\d{4})","$1-$2-$3","1(?:26|3[79]|4[56]|5[4-68]|6[3-5])|5(?:76|97)|499|746|8(?:3[89]|63|47|51)|9(?:49|80|9[16])",,],["(\\d{3})(\\d{2})(\\d{4})","$1-$2-$3","1(?:2[3-6]|3[3-9]|4[2-6]|5[2-8]|[68][2-7]|7[2-689]|9[1-578])|2(?:2[03-689]|3[3-58]|4[0-468]|5[04-8]|6[013-8]|7[06-9]|8[02-57-9]|9[13])|4(?:2[28]|3[689]|6[035-7]|7[05689]|80|9[3-5])|5(?:3[1-36-9]|4[4578]|5[013-8]|6[1-9]|7[2-8]|8[14-7]|9[4-9])|7(?:2[15]|3[5-9]|4[02-9]|6[135-8]|7[0-4689]|9[014-9])|8(?:2[49]|3[3-8]|4[5-8]|5[2-9]|6[35-9]|7[579]|8[03-579]|9[2-8])|9(?:[23]0|4[02-46-9]|5[024-79]|6[4-9]|7[2-47-9]|8[02-7]|9[3-7])",,],["(\\d{2})(\\d{3})(\\d{4})","$1-$2-$3","1|2(?:2[37]|5[5-9]|64|78|8[39]|91)|4(?:2[2689]|64|7[347])|5(?:[2-589]|39)|60|8(?:[46-9]|3[279]|2[124589])|9(?:[235-8]|93)",,],["(\\d{3})(\\d{2})(\\d{4})","$1-$2-$3","2(?:9[14-79]|74|[34]7|[56]9)|82|993",,],["(\\d)(\\d{4})(\\d{4})","$1-$2-$3","3|4(?:2[09]|7[01])|6[1-9]",,],["(\\d{2})(\\d{3})(\\d{4})","$1-$2-$3","[2479][1-9]",,]]]',
+"81": '["JP","010","0",,,"$NP$FG","\\d{8,17}","[1-9]\\d{8,9}|00(?:[36]\\d{7,14}|7\\d{5,7}|8\\d{7})",[["(\\d{3})(\\d{3})(\\d{3})","$1-$2-$3","(?:12|57|99)0",,],["(\\d{3})(\\d{3})(\\d{4})","$1-$2-$3","800",,],["(\\d{4})(\\d{4})","$1-$2","0077","$FG","NA"],["(\\d{4})(\\d{2})(\\d{3,4})","$1-$2-$3","0077","$FG","NA"],["(\\d{4})(\\d{2})(\\d{4})","$1-$2-$3","0088","$FG","NA"],["(\\d{4})(\\d{3})(\\d{3,4})","$1-$2-$3","00(?:37|66)","$FG","NA"],["(\\d{4})(\\d{4})(\\d{4,5})","$1-$2-$3","00(?:37|66)","$FG","NA"],["(\\d{4})(\\d{5})(\\d{5,6})","$1-$2-$3","00(?:37|66)","$FG","NA"],["(\\d{4})(\\d{6})(\\d{6,7})","$1-$2-$3","00(?:37|66)","$FG","NA"],["(\\d{2})(\\d{4})(\\d{4})","$1-$2-$3","[2579]0|80[1-9]",,],["(\\d{4})(\\d)(\\d{4})","$1-$2-$3","1(?:26|3[79]|4[56]|5[4-68]|6[3-5])|5(?:76|97)|499|746|8(?:3[89]|63|47|51)|9(?:49|80|9[16])",,],["(\\d{3})(\\d{2})(\\d{4})","$1-$2-$3","1(?:2[3-6]|3[3-9]|4[2-6]|5[2-8]|[68][2-7]|7[2-689]|9[1-578])|2(?:2[03-689]|3[3-58]|4[0-468]|5[04-8]|6[013-8]|7[06-9]|8[02-57-9]|9[13])|4(?:2[28]|3[689]|6[035-7]|7[05689]|80|9[3-5])|5(?:3[1-36-9]|4[4578]|5[013-8]|6[1-9]|7[2-8]|8[14-7]|9[4-9])|7(?:2[15]|3[5-9]|4[02-9]|6[135-8]|7[0-4689]|9[014-9])|8(?:2[49]|3[3-8]|4[5-8]|5[2-9]|6[35-9]|7[579]|8[03-579]|9[2-8])|9(?:[23]0|4[02-46-9]|5[024-79]|6[4-9]|7[2-47-9]|8[02-7]|9[3-7])",,],["(\\d{2})(\\d{3})(\\d{4})","$1-$2-$3","1|2(?:2[37]|5[5-9]|64|78|8[39]|91)|4(?:2[2689]|64|7[347])|5(?:[2-589]|39)|60|8(?:[46-9]|3[279]|2[124589])|9(?:[235-8]|93)",,],["(\\d{3})(\\d{2})(\\d{4})","$1-$2-$3","2(?:9[14-79]|74|[34]7|[56]9)|82|993",,],["(\\d)(\\d{4})(\\d{4})","$1-$2-$3","3|4(?:2[09]|7[01])|6[1-9]",,],["(\\d{2})(\\d{3})(\\d{4})","$1-$2-$3","[2479][1-9]",,]]]',
 "237": '["CM","00",,,,,"\\d{8}","[2357-9]\\d{7}",[["([2357-9]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[23579]|88",,],["(800)(\\d{2})(\\d{3})","$1 $2 $3","80",,]]]',
 "351": '["PT","00",,,,,"\\d{9}","[2-46-9]\\d{8}",[["(2\\d)(\\d{3})(\\d{4})","$1 $2 $3","2[12]",,],["([2-46-9]\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","2[3-9]|[346-9]",,]]]',
 "246": '["IO","00",,,,,"\\d{7}","3\\d{6}",[["(\\d{3})(\\d{4})","$1 $2",,,]]]',
 "227": '["NE","00",,,,,"\\d{8}","[0289]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[289]|09",,],["(08)(\\d{3})(\\d{3})","$1 $2 $3","08",,]]]',
 "27": '["ZA","00","0",,,"$NP$FG","\\d{5,9}","[1-79]\\d{8}|8(?:[067]\\d{7}|[1-4]\\d{3,7})",[["(860)(\\d{3})(\\d{3})","$1 $2 $3","860",,],["(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","[1-79]|8(?:[0-47]|6[1-9])",,],["(\\d{2})(\\d{3,4})","$1 $2","8[1-4]",,],["(\\d{2})(\\d{3})(\\d{2,3})","$1 $2 $3","8[1-4]",,]]]',
 "962": '["JO","00","0",,,"$NP$FG","\\d{7,9}","[235-9]\\d{7,8}",[["(\\d)(\\d{3})(\\d{4})","$1 $2 $3","[2356]|87","($NP$FG)",],["(7)(\\d{4})(\\d{4})","$1 $2 $3","7[457-9]",,],["(\\d{3})(\\d{5,6})","$1 $2","70|8[0158]|9",,]]]',
 "387": '["BA","00","0",,,"$NP$FG","\\d{6,9}","[3-9]\\d{7,8}",[["(\\d{2})(\\d{3})(\\d{3})","$1 $2-$3","[3-5]",,],["(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","6[1-356]|[7-9]",,],["(\\d{2})(\\d{2})(\\d{2})(\\d{3})","$1 $2 $3 $4","6[047]",,]]]',
 "33": '["FR","00","0",,,"$NP$FG","\\d{9}","[1-9]\\d{8}",[["([1-79])(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4 $5","[1-79]",,],["(1\\d{2})(\\d{3})","$1 $2","11","$FG","NA"],["(8\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","8","$NP $FG",]]]',
 "972": '["IL","0(?:0|1[2-9])","0",,,"$FG","\\d{4,10}","[17]\\d{6,9}|[2-589]\\d{3}(?:\\d{3,6})?|6\\d{3}",[["([2-489])(\\d{3})(\\d{4})","$1-$2-$3","[2-489]","$NP$FG",],["([57]\\d)(\\d{3})(\\d{4})","$1-$2-$3","[57]","$NP$FG",],["(1)([7-9]\\d{2})(\\d{3})(\\d{3})","$1-$2-$3-$4","1[7-9]",,],["(1255)(\\d{3})","$1-$2","125",,],["(1200)(\\d{3})(\\d{3})","$1-$2-$3","120",,],["(1212)(\\d{2})(\\d{2})","$1-$2-$3","121",,],["(1599)(\\d{6})","$1-$2","15",,],["(\\d{4})","*$1","[2-689]",,]]]',
 "248": '["SC","0[0-2]",,,,,"\\d{6,7}","[24689]\\d{5,6}",[["(\\d{3})(\\d{3})","$1 $2","[89]",,],["(\\d)(\\d{3})(\\d{3})","$1 $2 $3","[246]",,]]]',
 "297": '["AW","00",,,,,"\\d{7}","[25-9]\\d{6}",[["(\\d{3})(\\d{4})","$1 $2",,,]]]',
 "421": '["SK","00","0",,,"$NP$FG","\\d{9}","[2-689]\\d{8}",[["(2)(\\d{3})(\\d{3})(\\d{2})","$1/$2 $3 $4","2",,],["([3-5]\\d)(\\d{3})(\\d{2})(\\d{2})","$1/$2 $3 $4","[3-5]",,],["([689]\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","[689]",,]]]',
 "672": '["NF","00",,,,,"\\d{5,6}","[13]\\d{5}",[["(\\d{2})(\\d{4})","$1 $2","1",,],["(\\d)(\\d{5})","$1 $2","3",,]]]',
 "870": '["001",,,,,,"\\d{9}","[35-7]\\d{8}",[["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3",,,]]]',
-"883": '["001",,,,,,"\\d{9}(?:\\d{3})?","51\\d{7}(?:\\d{3})?",[["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3",,,],["(\\d{3})(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3 $4",,,]]]',
+"883": '["001",,,,,,"\\d{9}(?:\\d{3})?","51\\d{7}(?:\\d{3})?",[["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","510",,],["(\\d{3})(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3 $4","510",,],["(\\d{4})(\\d{4})(\\d{4})","$1 $2 $3","51[13]",,]]]',
 "264": '["NA","00","0",,,"$NP$FG","\\d{8,9}","[68]\\d{7,8}",[["(8\\d)(\\d{3})(\\d{4})","$1 $2 $3","8[1235]",,],["(6\\d)(\\d{2,3})(\\d{4})","$1 $2 $3","6",,],["(88)(\\d{3})(\\d{3})","$1 $2 $3","88",,],["(870)(\\d{3})(\\d{3})","$1 $2 $3","870",,]]]',
 "878": '["001",,,,,,"\\d{12}","1\\d{11}",[["(\\d{2})(\\d{5})(\\d{5})","$1 $2 $3",,,]]]',
 "239": '["ST","00",,,,,"\\d{7}","[29]\\d{6}",[["(\\d{3})(\\d{4})","$1 $2",,,]]]',
 "357": '["CY","00",,,,,"\\d{8}","[257-9]\\d{7}",[["(\\d{2})(\\d{6})","$1 $2",,,]]]',
 "240": '["GQ","00",,,,,"\\d{9}","[23589]\\d{8}",[["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","[235]",,],["(\\d{3})(\\d{6})","$1 $2","[89]",,]]]',
 "506": '["CR","00",,"(19(?:0[01468]|19|20|66|77))",,,"\\d{8,10}","[24-9]\\d{7,9}",[["(\\d{4})(\\d{4})","$1 $2","[24-7]|8[3-9]",,],["(\\d{3})(\\d{3})(\\d{4})","$1-$2-$3","[89]0",,]]]',
-"86": '["CN","(1[1279]\\d{3})?00","0","(1[1279]\\d{3})|0",,,"\\d{4,12}","1(?:00\\d{2}|\\d{6,11})|[2-7]\\d{6,11}|8[0-357-9]\\d{6,9}|9(?:5\\d{3,4}|\\d{9})",[["(80\\d{2})(\\d{4})","$1 $2","80[2678]","$NP$FG",],["([48]00)(\\d{3})(\\d{4})","$1 $2 $3","[48]00",,],["(\\d{5,6})","$1","100|95",,"NA"],["(\\d{2})(\\d{5,6})","$1 $2","(?:10|2\\d)[19]","$NP$FG",],["(\\d{3})(\\d{5,6})","$1 $2","[3-9]","$NP$FG",],["(\\d{3,4})(\\d{4})","$1 $2","[2-9]",,"NA"],["(21)(\\d{4})(\\d{4,6})","$1 $2 $3","21","$NP$FG",],["([12]\\d)(\\d{4})(\\d{4})","$1 $2 $3","10[1-9]|2[02-9]","$NP$FG",],["(\\d{3})(\\d{4})(\\d{4})","$1 $2 $3","3(?:11|7[179])|4(?:[15]1|3[12])|5(?:1|2[37]|3[12]|51|7[13-79]|9[15])|7(?:31|5[457]|6[09]|91)|8(?:71|98)","$NP$FG",],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","3(?:1[02-9]|35|49|5|7[02-68]|9[1-68])|4(?:1[02-9]|2[179]|[35][2-9]|6[4789]|7\\d|8[23])|5(?:3[03-9]|4[36]|5[02-9]|6[1-46]|7[028]|80|9[2-46-9])|6(?:3[1-5]|6[0238]|9[12])|7(?:01|[1579]|2[248]|3[04-9]|4[3-6]|6[2368])|8(?:1[236-8]|2[5-7]|3|5[1-9]|7[02-9]|8[3678]|9[1-7])|9(?:0[1-3689]|1[1-79]|[379]|4[13]|5[1-5])","$NP$FG",],["(1[3-58]\\d)(\\d{4})(\\d{4})","$1 $2 $3","1[3-58]",,],["(10800)(\\d{3})(\\d{4})","$1 $2 $3","108",,]]]',
+"86": '["CN","(1[1279]\\d{3})?00","0","(1[1279]\\d{3})|0",,,"\\d{4,12}","[1-7]\\d{6,11}|8[0-357-9]\\d{6,9}|9\\d{9}",[["(80\\d{2})(\\d{4})","$1 $2","80[2678]","$NP$FG",],["([48]00)(\\d{3})(\\d{4})","$1 $2 $3","[48]00",,],["(\\d{5,6})","$1","100|95",,"NA"],["(\\d{2})(\\d{5,6})","$1 $2","(?:10|2\\d)[19]","$NP$FG",],["(\\d{3})(\\d{5,6})","$1 $2","[3-9]","$NP$FG",],["(\\d{3,4})(\\d{4})","$1 $2","[2-9]",,"NA"],["(21)(\\d{4})(\\d{4,6})","$1 $2 $3","21","$NP$FG",],["([12]\\d)(\\d{4})(\\d{4})","$1 $2 $3","10[1-9]|2[02-9]","$NP$FG",],["(\\d{3})(\\d{4})(\\d{4})","$1 $2 $3","3(?:11|7[179])|4(?:[15]1|3[12])|5(?:1|2[37]|3[12]|51|7[13-79]|9[15])|7(?:31|5[457]|6[09]|91)|8(?:71|98)","$NP$FG",],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","3(?:1[02-9]|35|49|5|7[02-68]|9[1-68])|4(?:1[02-9]|2[179]|[35][2-9]|6[4789]|7\\d|8[23])|5(?:3[03-9]|4[36]|5[02-9]|6[1-46]|7[028]|80|9[2-46-9])|6(?:3[1-5]|6[0238]|9[12])|7(?:01|[1579]|2[248]|3[04-9]|4[3-6]|6[2368])|8(?:1[236-8]|2[5-7]|3|5[1-9]|7[02-9]|8[3678]|9[1-7])|9(?:0[1-3689]|1[1-79]|[379]|4[13]|5[1-5])","$NP$FG",],["(1[3-58]\\d)(\\d{4})(\\d{4})","$1 $2 $3","1[3-58]",,],["(10800)(\\d{3})(\\d{4})","$1 $2 $3","108",,]]]',
 "257": '["BI","00",,,,,"\\d{8}","[27]\\d{7}",[["([27]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
 "683": '["NU","00",,,,,"\\d{4}","[1-5]\\d{3}",]',
 "43": '["AT","00","0",,,"$NP$FG","\\d{3,13}","[1-9]\\d{3,12}",[["(1)(\\d{3,12})","$1 $2","1",,],["(5\\d)(\\d{3,5})","$1 $2","5[079]",,],["(5\\d)(\\d{3})(\\d{3,4})","$1 $2 $3","5[079]",,],["(5\\d)(\\d{4})(\\d{4,7})","$1 $2 $3","5[079]",,],["(\\d{3})(\\d{3,10})","$1 $2","316|46|51|732|6(?:44|5[0-3579]|[6-9])|7(?:1|[28]0)|[89]",,],["(\\d{4})(\\d{3,9})","$1 $2","2|3(?:1[1-578]|[3-8])|4[2378]|5[2-6]|6(?:[12]|4[1-35-9]|5[468])|7(?:2[1-8]|35|4[1-8]|[5-79])",,]]]',
 "247": '["AC","00",,,,,"\\d{4}","[2-467]\\d{3}",]',
 "675": '["PG","00",,,,,"\\d{7,8}","[1-9]\\d{6,7}",[["(\\d{3})(\\d{4})","$1 $2","[1-689]",,],["(7\\d{3})(\\d{4})","$1 $2","7",,]]]',
 "376": '["AD","00",,,,,"\\d{6,8}","(?:[346-9]|180)\\d{5}",[["(\\d{3})(\\d{3})","$1 $2","[346-9]",,],["(180[02])(\\d{4})","$1 $2","1",,]]]',
 "63": '["PH","00","0",,,,"\\d{5,13}","2\\d{5,7}|[3-9]\\d{7,9}|1800\\d{7,9}",[["(2)(\\d{3})(\\d{4})","$1 $2 $3","2","($NP$FG)",],["(2)(\\d{5})","$1 $2","2","($NP$FG)",],["(\\d{4})(\\d{4,6})","$1 $2","3(?:23|39|46)|4(?:2[3-6]|[35]9|4[26]|76)|5(?:22|44)|642|8(?:62|8[245])","($NP$FG)",],["(\\d{5})(\\d{4})","$1 $2","346|4(?:27|9[35])|883","($NP$FG)",],["([3-8]\\d)(\\d{3})(\\d{4})","$1 $2 $3","[3-8]","($NP$FG)",],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","81|9","$NP$FG",],["(1800)(\\d{3})(\\d{4})","$1 $2 $3","1",,],["(1800)(\\d{1,2})(\\d{3})(\\d{4})","$1 $2 $3 $4","1",,]]]',
 "236": '["CF","00",,,,,"\\d{8}","[278]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
 "590": ['["GP","00","0",,,"$NP$FG","\\d{9}","[56]\\d{8}",[["([56]90)(\\d{2})(\\d{4})","$1 $2-$3",,,]]]','["BL","00","0",,,,"\\d{9}","[56]\\d{8}",]','["MF","00","0",,,,"\\d{9}","[56]\\d{8}",]'],
 "53": '["CU","119","0",,,"($NP$FG)","\\d{4,8}","[2-57]\\d{5,7}",[["(\\d)(\\d{6,7})","$1 $2","7",,],["(\\d{2})(\\d{4,6})","$1 $2","[2-4]",,],["(\\d)(\\d{7})","$1 $2","5","$NP$FG",]]]',
-"64": '["NZ","0(?:0|161)","0",,,"$NP$FG","\\d{7,11}","6[235-9]\\d{6}|[2-57-9]\\d{7,10}",[["([34679])(\\d{3})(\\d{4})","$1-$2 $3","[3467]|9[1-9]",,],["(24099)(\\d{3})","$1 $2","240",,],["(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","21",,],["(\\d{2})(\\d{3})(\\d{3,4})","$1 $2 $3","2(?:1[1-9]|[69]|7[0-35-9])|86",,],["(2\\d)(\\d{3,4})(\\d{4})","$1 $2 $3","2[028]",,],["(\\d{3})(\\d{3})(\\d{3,4})","$1 $2 $3","2(?:10|74)|5|[89]0",,]]]',
+"64": '["NZ","0(?:0|161)","0",,,"$NP$FG","\\d{7,11}","6[235-9]\\d{6}|[2-57-9]\\d{7,10}",[["([34679])(\\d{3})(\\d{4})","$1-$2 $3","[3467]|9[1-9]",,],["(24099)(\\d{3})","$1 $2","240",,],["(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","21",,],["(\\d{2})(\\d{3})(\\d{3,5})","$1 $2 $3","2(?:1[1-9]|[69]|7[0-35-9])|86",,],["(2\\d)(\\d{3,4})(\\d{4})","$1 $2 $3","2[028]",,],["(\\d{3})(\\d{3})(\\d{3,4})","$1 $2 $3","2(?:10|74)|5|[89]0",,]]]',
 "965": '["KW","00",,,,,"\\d{7,8}","[12569]\\d{6,7}",[["(\\d{4})(\\d{3,4})","$1 $2","[1269]",,],["(5[015]\\d)(\\d{5})","$1 $2","5",,]]]',
 "224": '["GN","00",,,,,"\\d{8,9}","[367]\\d{7,8}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","3",,],["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[67]",,]]]',
 "973": '["BH","00",,,,,"\\d{8}","[136-9]\\d{7}",[["(\\d{4})(\\d{4})","$1 $2",,,]]]',
 "32": '["BE","00","0",,,"$NP$FG","\\d{8,9}","[1-9]\\d{7,8}",[["(4[6-9]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","4[6-9]",,],["([2-49])(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","[23]|[49][23]",,],["([15-8]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[156]|7[018]|8(?:0[1-9]|[1-79])",,],["([89]\\d{2})(\\d{2})(\\d{3})","$1 $2 $3","(?:80|9)0",,]]]',
 "249": '["SD","00","0",,,"$NP$FG","\\d{9}","[19]\\d{8}",[["(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3",,,]]]',
 "678": '["VU","00",,,,,"\\d{5,7}","[2-57-9]\\d{4,6}",[["(\\d{3})(\\d{4})","$1 $2","[579]",,]]]',
 "52": '["MX","0[09]","01","0[12]|04[45](\\d{10})","1$1","$NP $FG","\\d{7,11}","[1-9]\\d{9,10}",[["([358]\\d)(\\d{4})(\\d{4})","$1 $2 $3","33|55|81",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","[2467]|3[12457-9]|5[89]|8[02-9]|9[0-35-9]",,],["(1)([358]\\d)(\\d{4})(\\d{4})","044 $2 $3 $4","1(?:33|55|81)","$FG","$1 $2 $3 $4"],["(1)(\\d{3})(\\d{3})(\\d{4})","044 $2 $3 $4","1(?:[2467]|3[12457-9]|5[89]|8[2-9]|9[1-35-9])","$FG","$1 $2 $3 $4"]]]',
 "968": '["OM","00",,,,,"\\d{7,9}","(?:2[2-6]|5|9[1-9])\\d{6}|800\\d{5,6}",[["(2\\d)(\\d{6})","$1 $2","2",,],["(9\\d{3})(\\d{4})","$1 $2","9",,],["([58]00)(\\d{4,6})","$1 $2","[58]",,]]]',
 "599": ['["CW","00",,,,,"\\d{7,8}","[169]\\d{6,7}",[["(\\d{3})(\\d{4})","$1 $2","[13-7]",,],["(9)(\\d{3})(\\d{4})","$1 $2 $3","9",,]]]','["BQ","00",,,,,"\\d{7}","[347]\\d{6}",]'],
 "800": '["001",,,,,,"\\d{8}","\\d{8}",[["(\\d{4})(\\d{4})","$1 $2",,,]]]',
-"386": '["SI","00","0",,,"$NP$FG","\\d{5,8}","[1-7]\\d{6,7}|[89]\\d{4,7}",[["(\\d)(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","[12]|3[4-8]|4[24-8]|5[2-8]|7[3-8]","($NP$FG)",],["([3-7]\\d)(\\d{3})(\\d{3})","$1 $2 $3","[37][01]|4[019]|51|6",,],["([89][09])(\\d{3,6})","$1 $2","[89][09]",,],["([58]\\d{2})(\\d{5})","$1 $2","59|8[1-3]",,]]]',
+"386": '["SI","00","0",,,"$NP$FG","\\d{5,8}","[1-7]\\d{6,7}|[89]\\d{4,7}",[["(\\d)(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","[12]|3[4-8]|4[24-8]|5[2-8]|7[3-8]","($NP$FG)",],["([3-7]\\d)(\\d{3})(\\d{3})","$1 $2 $3","[37][01]|4[0139]|51|6",,],["([89][09])(\\d{3,6})","$1 $2","[89][09]",,],["([58]\\d{2})(\\d{5})","$1 $2","59|8[1-3]",,]]]',
 "679": '["FJ","0(?:0|52)",,,,,"\\d{7}(?:\\d{4})?","[36-9]\\d{6}|0\\d{10}",[["(\\d{3})(\\d{4})","$1 $2","[36-9]",,],["(\\d{4})(\\d{3})(\\d{4})","$1 $2 $3","0",,]]]',
 "238": '["CV","0",,,,,"\\d{7}","[259]\\d{6}",[["(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3",,,]]]',
 "691": '["FM","00",,,,,"\\d{7}","[39]\\d{6}",[["(\\d{3})(\\d{4})","$1 $2",,,]]]',
 "262": ['["RE","00","0",,,"$NP$FG","\\d{9}","[268]\\d{8}",[["([268]\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]','["YT","00","0",,,"$NP$FG","\\d{9}","[268]\\d{8}",]'],
 "241": '["GA","00",,,,,"\\d{8}","0\\d{7}",[["(0\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
 "370": '["LT","00","8","[08]",,"($NP-$FG)","\\d{8}","[3-9]\\d{7}",[["([34]\\d)(\\d{6})","$1 $2","37|4(?:1|5[45]|6[2-4])",,],["([3-6]\\d{2})(\\d{5})","$1 $2","3[148]|4(?:[24]|6[09])|528|6",,],["([7-9]\\d{2})(\\d{2})(\\d{3})","$1 $2 $3","[7-9]","$NP $FG",],["(5)(2\\d{2})(\\d{4})","$1 $2 $3","52[0-79]",,]]]',
 "256": '["UG","00[057]","0",,,"$NP$FG","\\d{5,9}","\\d{9}",[["(\\d{3})(\\d{6})","$1 $2","[7-9]|20(?:[013-8]|2[5-9])|4(?:6[45]|[7-9])",,],["(\\d{2})(\\d{7})","$1 $2","3|4(?:[1-5]|6[0-36-9])",,],["(2024)(\\d{5})","$1 $2","2024",,]]]',
 "677": '["SB","0[01]",,,,,"\\d{5,7}","[1-9]\\d{4,6}",[["(\\d{3})(\\d{4})","$1 $2","[7-9]",,]]]',
@@ -143,43 +143,43 @@ this.PHONE_NUMBER_META_DATA = {
 "888": '["001",,,,,,"\\d{11}","\\d{11}",[["(\\d{3})(\\d{3})(\\d{5})","$1 $2 $3",,,]]]',
 "353": '["IE","00","0",,,"($NP$FG)","\\d{5,10}","[124-9]\\d{6,9}",[["(1)(\\d{3,4})(\\d{4})","$1 $2 $3","1",,],["(\\d{2})(\\d{5})","$1 $2","2[24-9]|47|58|6[237-9]|9[35-9]",,],["(\\d{3})(\\d{5})","$1 $2","40[24]|50[45]",,],["(48)(\\d{4})(\\d{4})","$1 $2 $3","48",,],["(818)(\\d{3})(\\d{3})","$1 $2 $3","81",,],["(\\d{2})(\\d{3})(\\d{3,4})","$1 $2 $3","[24-69]|7[14]",,],["([78]\\d)(\\d{3,4})(\\d{4})","$1 $2 $3","76|8[35-9]","$NP$FG",],["(700)(\\d{3})(\\d{3})","$1 $2 $3","70","$NP$FG",],["(\\d{4})(\\d{3})(\\d{3})","$1 $2 $3","1(?:8[059]|5)","$FG",]]]',
 "966": '["SA","00","0",,,"$NP$FG","\\d{7,10}","1\\d{7,8}|(?:[2-467]|92)\\d{7}|5\\d{8}|8\\d{9}",[["([1-467])(\\d{3})(\\d{4})","$1 $2 $3","[1-467]",,],["(1\\d)(\\d{3})(\\d{4})","$1 $2 $3","1[1-467]",,],["(5\\d)(\\d{3})(\\d{4})","$1 $2 $3","5",,],["(92\\d{2})(\\d{5})","$1 $2","92","$FG",],["(800)(\\d{3})(\\d{4})","$1 $2 $3","80","$FG",],["(811)(\\d{3})(\\d{3,4})","$1 $2 $3","81",,]]]',
 "380": '["UA","00","0",,,"$NP$FG","\\d{5,9}","[3-689]\\d{8}",[["([3-689]\\d)(\\d{3})(\\d{4})","$1 $2 $3","[38]9|4(?:[45][0-5]|87)|5(?:0|6[37]|7[37])|6[36-8]|9[1-9]",,],["([3-689]\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","3[1-8]2|4[13678]2|5(?:[12457]2|6[24])|6(?:[49]2|[12][29]|5[24])|8[0-8]|90",,],["([3-6]\\d{3})(\\d{5})","$1 $2","3(?:5[013-9]|[1-46-8])|4(?:[137][013-9]|6|[45][6-9]|8[4-6])|5(?:[1245][013-9]|6[0135-9]|3|7[4-6])|6(?:[49][013-9]|5[0135-9]|[12][13-8])",,]]]',
 "98": '["IR","00","0",,,"$NP$FG","\\d{4,10}","[14-8]\\d{6,9}|[23]\\d{4,9}|9(?:[1-4]\\d{8}|9\\d{2,8})",[["(2[15])(\\d{3,5})","$1 $2","2(?:1|5[0-47-9])",,],["(2[15])(\\d{3})(\\d{3,4})","$1 $2 $3","2(?:1|5[0-47-9])",,],["(2\\d)(\\d{4})(\\d{4})","$1 $2 $3","2(?:[16]|5[0-47-9])",,],["(\\d{3})(\\d{3})(\\d{3,4})","$1 $2 $3","[13-9]|2[02-57-9]",,],["(\\d{3})(\\d{2})(\\d{2,3})","$1 $2 $3","[13-9]|2[02-57-9]",,],["(\\d{3})(\\d{3})","$1 $2","[13-9]|2[02-57-9]",,]]]',
 "971": '["AE","00","0",,,"$NP$FG","\\d{5,12}","[2-79]\\d{7,8}|800\\d{2,9}",[["([2-4679])(\\d{3})(\\d{4})","$1 $2 $3","[2-4679][2-8]",,],["(5[0256])(\\d{3})(\\d{4})","$1 $2 $3","5",,],["([479]00)(\\d)(\\d{5})","$1 $2 $3","[479]0","$FG",],["([68]00)(\\d{2,9})","$1 $2","60|8","$FG",]]]',
 "30": '["GR","00",,,,,"\\d{10}","[26-9]\\d{9}",[["([27]\\d)(\\d{4})(\\d{4})","$1 $2 $3","21|7",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","2[2-9]1|[689]",,],["(2\\d{3})(\\d{6})","$1 $2","2[2-9][02-9]",,]]]',
 "228": '["TG","00",,,,,"\\d{8}","[29]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
-"48": '["PL","00",,,,,"\\d{6,9}","[1-58]\\d{6,8}|9\\d{8}|[67]\\d{5,8}",[["(\\d{2})(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","[124]|3[2-4]|5[24-689]|6[1-3578]|7[14-7]|8[1-79]|9[145]",,],["(\\d{2})(\\d{4,6})","$1 $2","[124]|3[2-4]|5[24-689]|6[1-3578]|7[14-7]|8[1-7]",,],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","39|5[013]|6[0469]|7[02389]|8[08]",,],["(\\d{3})(\\d{2})(\\d{2,3})","$1 $2 $3","64",,],["(\\d{3})(\\d{3})","$1 $2","64",,]]]',
+"48": '["PL","00",,,,,"\\d{6,9}","[1-58]\\d{6,8}|9\\d{8}|[67]\\d{5,8}",[["(\\d{2})(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","[124]|3[2-4]|5[24-689]|6[1-3578]|7[14-7]|8[1-79]|9[145]",,],["(\\d{2})(\\d{4,6})","$1 $2","[124]|3[2-4]|5[24-689]|6[1-3578]|7[14-7]|8[1-7]",,],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","39|5[0137]|6[0469]|7[02389]|8[08]",,],["(\\d{3})(\\d{2})(\\d{2,3})","$1 $2 $3","64",,],["(\\d{3})(\\d{3})","$1 $2","64",,]]]',
 "886": '["TW","0(?:0[25679]|19)","0",,,"$NP$FG","\\d{8,9}","[2-9]\\d{7,8}",[["([2-8])(\\d{3,4})(\\d{4})","$1 $2 $3","[2-7]|8[1-9]",,],["([89]\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","80|9",,]]]',
 "212": ['["MA","00","0",,,"$NP$FG","\\d{9}","[5689]\\d{8}",[["([56]\\d{2})(\\d{6})","$1-$2","5(?:2[015-7]|3[0-4])|6",,],["([58]\\d{3})(\\d{5})","$1-$2","5(?:2[2-489]|3[5-9])|892",,],["(5\\d{4})(\\d{4})","$1-$2","5(?:29|38)",,],["(8[09])(\\d{7})","$1-$2","8(?:0|9[013-9])",,]]]','["EH","00","0",,,"$NP$FG","\\d{9}","[5689]\\d{8}",]'],
 "372": '["EE","00",,,,,"\\d{4,10}","1\\d{3,4}|[3-9]\\d{6,7}|800\\d{6,7}",[["([3-79]\\d{2})(\\d{4})","$1 $2","[369]|4[3-8]|5(?:[0-2]|5[0-478]|6[45])|7[1-9]",,],["(70)(\\d{2})(\\d{4})","$1 $2 $3","70",,],["(8000)(\\d{3})(\\d{3})","$1 $2 $3","800",,],["([458]\\d{3})(\\d{3,4})","$1 $2","40|5|8(?:00|[1-5])",,]]]',
 "598": '["UY","0(?:1[3-9]\\d|0)","0",,,,"\\d{7,8}","[2489]\\d{6,7}",[["(\\d{4})(\\d{4})","$1 $2","[24]",,],["(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","9[1-9]","$NP$FG",],["(\\d{3})(\\d{4})","$1 $2","[89]0","$NP$FG",]]]',
 "502": '["GT","00",,,,,"\\d{8}(?:\\d{3})?","[2-7]\\d{7}|1[89]\\d{9}",[["(\\d{4})(\\d{4})","$1 $2","[2-7]",,],["(\\d{4})(\\d{3})(\\d{4})","$1 $2 $3","1",,]]]',
 "82": '["KR","00(?:[124-68]|[37]\\d{2})","0","0(8[1-46-8]|85\\d{2})?",,"$NP$FG","\\d{4,10}","[1-7]\\d{3,9}|8\\d{8}",[["(\\d{2})(\\d{4})(\\d{4})","$1-$2-$3","1(?:0|1[19]|[69]9|5[458])|[57]0",,],["(\\d{2})(\\d{3,4})(\\d{4})","$1-$2-$3","1(?:[169][2-8]|[78]|5[1-4])|[68]0|[3-6][1-9][1-9]",,],["(\\d{3})(\\d)(\\d{4})","$1-$2-$3","131",,],["(\\d{3})(\\d{2})(\\d{4})","$1-$2-$3","131",,],["(\\d{3})(\\d{3})(\\d{4})","$1-$2-$3","13[2-9]",,],["(\\d{2})(\\d{2})(\\d{3})(\\d{4})","$1-$2-$3-$4","30",,],["(\\d)(\\d{3,4})(\\d{4})","$1-$2-$3","2[1-9]",,],["(\\d)(\\d{3,4})","$1-$2","21[0-46-9]",,],["(\\d{2})(\\d{3,4})","$1-$2","[3-6][1-9]1",,],["(\\d{4})(\\d{4})","$1-$2","1(?:5[46-9]|6[04678])","$FG",]]]',
 "253": '["DJ","00",,,,,"\\d{8}","[27]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
-"91": '["IN","00","0",,,"$NP$FG","\\d{6,13}","1\\d{7,12}|[2-9]\\d{9,10}",[["(\\d{2})(\\d{2})(\\d{6})","$1 $2 $3","7(?:2[0579]|3[057-9]|4[0-389]|6[0-35-9]|[57]|8[0-79])|8(?:0[015689]|1[0-57-9]|2[2356-9]|3[0-57-9]|[45]|6[02457-9]|7[1-69]|8[0124-9]|9[02-9])|9",,],["(\\d{2})(\\d{4})(\\d{4})","$1 $2 $3","11|2[02]|33|4[04]|79|80[2-46]",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","1(?:2[0-249]|3[0-25]|4[145]|[569][14]|7[1257]|8[1346]|[68][1-9])|2(?:1[257]|3[013]|4[01]|5[0137]|6[0158]|78|8[1568]|9[14])|3(?:26|4[1-3]|5[34]|6[01489]|7[02-46]|8[159])|4(?:1[36]|2[1-47]|3[15]|5[12]|6[126-9]|7[0-24-9]|8[013-57]|9[014-7])|5(?:[136][25]|22|4[28]|5[12]|[78]1|9[15])|6(?:12|[2345]1|57|6[13]|7[14]|80)",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","7(?:12|2[14]|3[134]|4[47]|5[15]|[67]1|88)",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","8(?:16|2[014]|3[126]|6[136]|7[078]|8[34]|91)",,],["(\\d{4})(\\d{3})(\\d{3})","$1 $2 $3","1(?:[2-579]|[68][1-9])|[2-8]",,],["(1600)(\\d{2})(\\d{4})","$1 $2 $3","160","$FG",],["(1800)(\\d{4,5})","$1 $2","180","$FG",],["(18[06]0)(\\d{2,4})(\\d{4})","$1 $2 $3","18[06]","$FG",],["(\\d{4})(\\d{3})(\\d{4})(\\d{2})","$1 $2 $3 $4","18[06]","$FG",]]]',
+"91": '["IN","00","0",,,"$NP$FG","\\d{6,13}","1\\d{7,12}|[2-9]\\d{9,10}",[["(\\d{2})(\\d{2})(\\d{6})","$1 $2 $3","7(?:2[0579]|3[057-9]|4[0-389]|6[0-35-9]|[57]|8[0-79])|8(?:0[015689]|1[0-57-9]|2[2356-9]|3[0-57-9]|[45]|6[02457-9]|7[1-69]|8[0124-9]|9[02-9])|9",,],["(\\d{2})(\\d{4})(\\d{4})","$1 $2 $3","11|2[02]|33|4[04]|79|80[2-46]",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","1(?:2[0-249]|3[0-25]|4[145]|[569][14]|7[1257]|8[1346]|[68][1-9])|2(?:1[257]|3[013]|4[01]|5[0137]|6[0158]|78|8[1568]|9[14])|3(?:26|4[1-3]|5[34]|6[01489]|7[02-46]|8[159])|4(?:1[36]|2[1-47]|3[15]|5[12]|6[126-9]|7[0-24-9]|8[013-57]|9[014-7])|5(?:[136][25]|22|4[28]|5[12]|[78]1|9[15])|6(?:12|[2345]1|57|6[13]|7[14]|80)",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","7(?:12|2[14]|3[134]|4[47]|5[15]|[67]1|88)",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","8(?:16|2[014]|3[126]|6[136]|7[078]|8[34]|91)",,],["(\\d{4})(\\d{3})(\\d{3})","$1 $2 $3","1(?:[23579]|[468][1-9])|[2-8]",,],["(1600)(\\d{2})(\\d{4})","$1 $2 $3","160","$FG",],["(1800)(\\d{4,5})","$1 $2","180","$FG",],["(18[06]0)(\\d{2,4})(\\d{4})","$1 $2 $3","18[06]","$FG",],["(140)(\\d{3})(\\d{4})","$1 $2 $3","140","$FG",],["(\\d{4})(\\d{3})(\\d{4})(\\d{2})","$1 $2 $3 $4","18[06]","$FG",]]]',
 "389": '["MK","00","0",,,"$NP$FG","\\d{8}","[2-578]\\d{7}",[["(2)(\\d{3})(\\d{4})","$1 $2 $3","2",,],["([347]\\d)(\\d{3})(\\d{3})","$1 $2 $3","[347]",,],["([58]\\d{2})(\\d)(\\d{2})(\\d{2})","$1 $2 $3 $4","[58]",,]]]',
 "1": ['["US","011","1",,,,"\\d{7}(?:\\d{3})?","[2-9]\\d{9}",[["(\\d{3})(\\d{4})","$1-$2",,,"NA"],["(\\d{3})(\\d{3})(\\d{4})","($1) $2-$3",,,"$1-$2-$3"]]]','["AI","011","1",,,,"\\d{7}(?:\\d{3})?","[2589]\\d{9}",]','["AS","011","1",,,,"\\d{7}(?:\\d{3})?","[5689]\\d{9}",]','["BB","011","1",,,,"\\d{7}(?:\\d{3})?","[2589]\\d{9}",]','["BM","011","1",,,,"\\d{7}(?:\\d{3})?","[4589]\\d{9}",]','["BS","011","1",,,,"\\d{7}(?:\\d{3})?","[2589]\\d{9}",]','["CA","011","1",,,,"\\d{7}(?:\\d{3})?","[2-9]\\d{9}|3\\d{6}",]','["DM","011","1",,,,"\\d{7}(?:\\d{3})?","[57-9]\\d{9}",]','["DO","011","1",,,,"\\d{7}(?:\\d{3})?","[589]\\d{9}",]','["GD","011","1",,,,"\\d{7}(?:\\d{3})?","[4589]\\d{9}",]','["GU","011","1",,,,"\\d{7}(?:\\d{3})?","[5689]\\d{9}",]','["JM","011","1",,,,"\\d{7}(?:\\d{3})?","[589]\\d{9}",]','["KN","011","1",,,,"\\d{7}(?:\\d{3})?","[589]\\d{9}",]','["KY","011","1",,,,"\\d{7}(?:\\d{3})?","[3589]\\d{9}",]','["LC","011","1",,,,"\\d{7}(?:\\d{3})?","[5789]\\d{9}",]','["MP","011","1",,,,"\\d{7}(?:\\d{3})?","[5689]\\d{9}",]','["MS","011","1",,,,"\\d{7}(?:\\d{3})?","[5689]\\d{9}",]','["PR","011","1",,,,"\\d{7}(?:\\d{3})?","[5789]\\d{9}",]','["SX","011","1",,,,"\\d{7}(?:\\d{3})?","[5789]\\d{9}",]','["TC","011","1",,,,"\\d{7}(?:\\d{3})?","[5689]\\d{9}",]','["TT","011","1",,,,"\\d{7}(?:\\d{3})?","[589]\\d{9}",]','["AG","011","1",,,,"\\d{7}(?:\\d{3})?","[2589]\\d{9}",]','["VC","011","1",,,,"\\d{7}(?:\\d{3})?","[5789]\\d{9}",]','["VG","011","1",,,,"\\d{7}(?:\\d{3})?","[2589]\\d{9}",]','["VI","011","1",,,,"\\d{7}(?:\\d{3})?","[3589]\\d{9}",]'],
 "60": '["MY","00","0",,,,"\\d{6,10}","[13-9]\\d{7,9}",[["([4-79])(\\d{3})(\\d{4})","$1-$2 $3","[4-79]","$NP$FG",],["(3)(\\d{4})(\\d{4})","$1-$2 $3","3","$NP$FG",],["([18]\\d)(\\d{3})(\\d{3,4})","$1-$2 $3","1[02-46-9][1-9]|8","$NP$FG",],["(1)([36-8]00)(\\d{2})(\\d{4})","$1-$2-$3-$4","1[36-8]0",,],["(11)(\\d{4})(\\d{4})","$1-$2 $3","11","$NP$FG",],["(15[49])(\\d{3})(\\d{4})","$1-$2 $3","15","$NP$FG",]]]',
 "355": '["AL","00","0",,,"$NP$FG","\\d{5,9}","[2-57]\\d{7}|6\\d{8}|8\\d{5,7}|9\\d{5}",[["(4)(\\d{3})(\\d{4})","$1 $2 $3","4[0-6]",,],["(6[6-9])(\\d{3})(\\d{4})","$1 $2 $3","6",,],["(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","[2358][2-5]|4[7-9]",,],["(\\d{3})(\\d{3,5})","$1 $2","[235][16-9]|8[016-9]|[79]",,]]]',
 "254": '["KE","000","0",,,"$NP$FG","\\d{5,10}","20\\d{6,7}|[4-9]\\d{6,9}",[["(\\d{2})(\\d{4,7})","$1 $2","[24-6]",,],["(\\d{3})(\\d{6,7})","$1 $2","7",,],["(\\d{3})(\\d{3})(\\d{3,4})","$1 $2 $3","[89]",,]]]',
 "223": '["ML","00",,,,,"\\d{8}","[246-9]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[246-9]",,],["(\\d{4})","$1","67|74",,"NA"]]]',
-"686": '["KI","00",,"0",,,"\\d{5,8}","[2-689]\\d{4}|7\\d{7}",]',
+"686": '["KI","00",,"0",,,"\\d{5,8}","[2-58]\\d{4}|7\\d{7}",]',
 "994": '["AZ","00","0",,,"($NP$FG)","\\d{7,9}","[1-9]\\d{8}",[["(\\d{2})(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","(?:1[28]|2(?:[45]2|[0-36])|365)",,],["(\\d{2})(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","[4-8]","$NP$FG",],["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","9","$NP$FG",]]]',
 "979": '["001",,,,,,"\\d{9}","\\d{9}",[["(\\d)(\\d{4})(\\d{4})","$1 $2 $3",,,]]]',
 "66": '["TH","00","0",,,"$NP$FG","\\d{4}|\\d{8,10}","[2-9]\\d{7,8}|1\\d{3}(?:\\d{6})?",[["(2)(\\d{3})(\\d{4})","$1 $2 $3","2",,],["([3-9]\\d)(\\d{3})(\\d{3,4})","$1 $2 $3","[3-9]",,],["(1[89]00)(\\d{3})(\\d{3})","$1 $2 $3","1","$FG",]]]',
 "233": '["GH","00","0",,,"$NP$FG","\\d{7,9}","[235]\\d{8}|8\\d{7}",[["(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","[235]",,],["(\\d{3})(\\d{5})","$1 $2","8",,]]]',
 "593": '["EC","00","0",,,"($NP$FG)","\\d{7,11}","1\\d{9,10}|[2-8]\\d{7}|9\\d{8}",[["(\\d)(\\d{3})(\\d{4})","$1 $2-$3","[247]|[356][2-8]",,"$1-$2-$3"],["(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","9","$NP$FG",],["(1800)(\\d{3})(\\d{3,4})","$1 $2 $3","1","$FG",]]]',
 "509": '["HT","00",,,,,"\\d{8}","[2-489]\\d{7}",[["(\\d{2})(\\d{2})(\\d{4})","$1 $2 $3",,,]]]',
 "54": '["AR","00","0","0?(?:(11|2(?:2(?:02?|[13]|2[13-79]|4[1-6]|5[2457]|6[124-8]|7[1-4]|8[13-6]|9[1267])|3(?:02?|1[467]|2[03-6]|3[13-8]|[49][2-6]|5[2-8]|[67])|4(?:7[3-578]|9)|6(?:[0136]|2[24-6]|4[6-8]?|5[15-8])|80|9(?:0[1-3]|[19]|2\\d|3[1-6]|4[02568]?|5[2-4]|6[2-46]|72?|8[23]?))|3(?:3(?:2[79]|6|8[2578])|4(?:0[124-9]|[12]|3[5-8]?|4[24-7]|5[4-68]?|6[02-9]|7[126]|8[2379]?|9[1-36-8])|5(?:1|2[1245]|3[237]?|4[1-46-9]|6[2-4]|7[1-6]|8[2-5]?)|6[24]|7(?:1[1568]|2[15]|3[145]|4[13]|5[14-8]|[069]|7[2-57]|8[126])|8(?:[01]|2[15-7]|3[2578]?|4[13-6]|5[4-8]?|6[1-357-9]|7[36-8]?|8[5-8]?|9[124])))15)?","9$1","$NP$FG","\\d{6,11}","[1-368]\\d{9}|9\\d{10}",[["([68]\\d{2})(\\d{3})(\\d{4})","$1-$2-$3","[68]",,],["(9)(11)(\\d{4})(\\d{4})","$2 15-$3-$4","911",,"$1 $2 $3-$4"],["(9)(\\d{3})(\\d{3})(\\d{4})","$2 15-$3-$4","9(?:2[234689]|3[3-8])",,"$1 $2 $3-$4"],["(9)(\\d{4})(\\d{3})(\\d{3})","$2 15-$3-$4","93[58]",,"$1 $2 $3-$4"],["(9)(\\d{4})(\\d{2})(\\d{4})","$2 15-$3-$4","9[23]",,"$1 $2 $3-$4"],["(11)(\\d{4})(\\d{4})","$1 $2-$3","1",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2-$3","2(?:2[013]|3[067]|49|6[01346]|80|9[147-9])|3(?:36|4[12358]|5[138]|6[24]|7[069]|8[013578])",,],["(\\d{4})(\\d{3})(\\d{3})","$1 $2-$3","3(?:53|8[78])",,],["(\\d{4})(\\d{2})(\\d{4})","$1 $2-$3","[23]",,],["(\\d{3})","$1","1[012]|911","$FG","NA"]]]',
 "57": '["CO","00(?:4(?:[14]4|56)|[579])","0","0([3579]|4(?:44|56))?",,,"\\d{7,11}","(?:[13]\\d{0,3}|[24-8])\\d{7}",[["(\\d)(\\d{7})","$1 $2","1(?:8[2-9]|9[0-3]|[2-7])|[24-8]","($FG)",],["(\\d{3})(\\d{7})","$1 $2","3",,],["(1)(\\d{3})(\\d{7})","$1-$2-$3","1(?:80|9[04])","$NP$FG","$1 $2 $3"]]]',
 "597": '["SR","00",,,,,"\\d{6,7}","[2-8]\\d{5,6}",[["(\\d{3})(\\d{3})","$1-$2","[2-4]|5[2-58]",,],["(\\d{2})(\\d{2})(\\d{2})","$1-$2-$3","56",,],["(\\d{3})(\\d{4})","$1-$2","[6-8]",,]]]',
 "676": '["TO","00",,,,,"\\d{5,7}","[02-8]\\d{4,6}",[["(\\d{2})(\\d{3})","$1-$2","[1-6]|7[0-4]|8[05]",,],["(\\d{3})(\\d{4})","$1 $2","7[5-9]|8[7-9]",,],["(\\d{4})(\\d{3})","$1 $2","0",,]]]',
-"505": '["NI","00",,,,,"\\d{8}","[1258]\\d{7}",[["(\\d{4})(\\d{4})","$1 $2",,,]]]',
+"505": '["NI","00",,,,,"\\d{8}","[12578]\\d{7}",[["(\\d{4})(\\d{4})","$1 $2",,,]]]',
 "850": '["KP","00|99","0",,,"$NP$FG","\\d{6,8}|\\d{10}","1\\d{9}|[28]\\d{7}",[["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","1",,],["(\\d)(\\d{3})(\\d{4})","$1 $2 $3","2",,],["(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","8",,]]]',
 "7": ['["RU","810","8",,,"$NP ($FG)","\\d{10}","[3489]\\d{9}",[["(\\d{3})(\\d{2})(\\d{2})","$1-$2-$3","[1-79]","$FG","NA"],["([3489]\\d{2})(\\d{3})(\\d{2})(\\d{2})","$1 $2-$3-$4","[34689]",,],["(7\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","7",,]]]','["KZ","810","8",,,,"\\d{10}","(?:33\\d|7\\d{2}|80[09])\\d{7}",]'],
 "268": '["SZ","00",,,,,"\\d{8}","[027]\\d{7}",[["(\\d{4})(\\d{4})","$1 $2","[027]",,]]]',
 "501": '["BZ","00",,,,,"\\d{7}(?:\\d{4})?","[2-8]\\d{6}|0\\d{10}",[["(\\d{3})(\\d{4})","$1-$2","[2-8]",,],["(0)(800)(\\d{4})(\\d{3})","$1-$2-$3-$4","0",,]]]',
 "252": '["SO","00","0",,,,"\\d{7,9}","[1-79]\\d{6,8}",[["(\\d)(\\d{6})","$1 $2","2[0-79]|[13-5]",,],["(\\d)(\\d{7})","$1 $2","24|[67]",,],["(\\d{2})(\\d{5,7})","$1 $2","15|28|6[1378]|9",,],["(69\\d)(\\d{6})","$1 $2","69",,]]]',
 "229": '["BJ","00",,,,,"\\d{4,8}","[2689]\\d{7}|7\\d{3}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
 "680": '["PW","01[12]",,,,,"\\d{7}","[2-8]\\d{6}",[["(\\d{3})(\\d{4})","$1 $2",,,]]]',
 "263": '["ZW","00","0",,,"$NP$FG","\\d{3,10}","2(?:[012457-9]\\d{3,8}|6\\d{3,6})|[13-79]\\d{4,8}|8[06]\\d{8}",[["([49])(\\d{3})(\\d{2,5})","$1 $2 $3","4|9[2-9]",,],["([179]\\d)(\\d{3})(\\d{3,4})","$1 $2 $3","[19]1|7",,],["(86\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","86[24]",,],["([2356]\\d{2})(\\d{3,5})","$1 $2","2(?:[278]|0[45]|[49]8)|3(?:08|17|3[78]|[78])|5[15][78]|6(?:[29]8|37|[68][78])",,],["(\\d{3})(\\d{3})(\\d{3,4})","$1 $2 $3","2(?:[278]|0[45]|48)|3(?:08|17|3[78]|[78])|5[15][78]|6(?:[29]8|37|[68][78])|80",,],["([1-356]\\d)(\\d{3,5})","$1 $2","1[3-9]|2(?:[1-469]|0[0-35-9]|[45][0-79])|3(?:0[0-79]|1[0-689]|[24-69]|3[0-69])|5(?:[02-46-9]|[15][0-69])|6(?:[0145]|[29][0-79]|3[0-689]|[68][0-69])",,],["([1-356]\\d)(\\d{3})(\\d{3})","$1 $2 $3","1[3-9]|2(?:[1-469]|0[0-35-9]|[45][0-79])|3(?:0[0-79]|1[0-689]|[24-69]|3[0-69])|5(?:[02-46-9]|[15][0-69])|6(?:[0145]|[29][0-79]|3[0-689]|[68][0-69])",,],["([25]\\d{3})(\\d{3,5})","$1 $2","(?:25|54)8",,],["([25]\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","(?:25|54)8",,],["(8\\d{3})(\\d{6})","$1 $2","86",,]]]',
@@ -190,19 +190,19 @@ this.PHONE_NUMBER_META_DATA = {
 "220": '["GM","00",,,,,"\\d{7}","[2-9]\\d{6}",[["(\\d{3})(\\d{4})","$1 $2",,,]]]',
 "687": '["NC","00",,,,,"\\d{6}","[2-57-9]\\d{5}",[["(\\d{2})(\\d{2})(\\d{2})","$1.$2.$3","[2-46-9]|5[0-4]",,]]]',
 "995": '["GE","00","0",,,,"\\d{6,9}","[34578]\\d{8}",[["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[348]","$NP$FG",],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","7","$NP$FG",],["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","5","$FG",]]]',
 "961": '["LB","00","0",,,,"\\d{7,8}","[13-9]\\d{6,7}",[["(\\d)(\\d{3})(\\d{3})","$1 $2 $3","[13-6]|7(?:[2-579]|62|8[0-7])|[89][2-9]","$NP$FG",],["([7-9]\\d)(\\d{3})(\\d{3})","$1 $2 $3","[89][01]|7(?:[01]|6[013-9]|8[89]|91)",,]]]',
 "40": '["RO","00","0",,,"$NP$FG","\\d{6,9}","2\\d{5,8}|[37-9]\\d{8}",[["([237]\\d)(\\d{3})(\\d{4})","$1 $2 $3","[23]1",,],["(21)(\\d{4})","$1 $2","21",,],["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","[23][3-7]|[7-9]",,],["(2\\d{2})(\\d{3})","$1 $2","2[3-6]",,]]]',
 "232": '["SL","00","0",,,"($NP$FG)","\\d{6,8}","[2-578]\\d{7}",[["(\\d{2})(\\d{6})","$1 $2",,,]]]',
 "594": '["GF","00","0",,,"$NP$FG","\\d{9}","[56]\\d{8}",[["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
 "976": '["MN","001","0",,,"$NP$FG","\\d{6,10}","[12]\\d{7,9}|[57-9]\\d{7}",[["([12]\\d)(\\d{2})(\\d{4})","$1 $2 $3","[12]1",,],["([12]2\\d)(\\d{5,6})","$1 $2","[12]2[1-3]",,],["([12]\\d{3})(\\d{5})","$1 $2","[12](?:27|[3-5])",,],["(\\d{4})(\\d{4})","$1 $2","[57-9]","$FG",],["([12]\\d{4})(\\d{4,5})","$1 $2","[12](?:27|[3-5])",,]]]',
-"20": '["EG","00","0",,,"$NP$FG","\\d{5,10}","1\\d{4,9}|[2456]\\d{8}|3\\d{7}|[89]\\d{8,9}",[["(\\d)(\\d{7,8})","$1 $2","[23]",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","1[012]|[89]00",,],["(\\d{2})(\\d{6,7})","$1 $2","1(?:3|5[23])|[4-6]|[89][2-9]",,]]]',
+"20": '["EG","00","0",,,"$NP$FG","\\d{5,10}","1\\d{4,9}|[2456]\\d{8}|3\\d{7}|[89]\\d{8,9}",[["(\\d)(\\d{7,8})","$1 $2","[23]",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","1[012]|[89]00",,],["(\\d{2})(\\d{6,7})","$1 $2","1[35]|[4-6]|[89][2-9]",,]]]',
 "689": '["PF","00",,,,,"\\d{6}(?:\\d{2})?","[2-79]\\d{5}|8\\d{5,7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","89",,],["(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3",,,]]]',
-"56": '["CL","(?:0|1(?:1[0-69]|2[0-57]|5[13-58]|69|7[0167]|8[018]))0","0","0|(1(?:1[0-69]|2[0-57]|5[13-58]|69|7[0167]|8[018]))",,"$NP$FG","\\d{6,11}","(?:[2-9]|600|123)\\d{7,8}",[["(2)(\\d{3,4})(\\d{4})","$1 $2 $3","2","($FG)",],["(\\d{2})(\\d{2,3})(\\d{4})","$1 $2 $3","[357]|4[1-35]|6[13-57]","($FG)",],["(9)([5-9]\\d{3})(\\d{4})","$1 $2 $3","9",,],["(44)(\\d{3})(\\d{4})","$1 $2 $3","44",,],["([68]00)(\\d{3})(\\d{3,4})","$1 $2 $3","60|8","$FG",],["(600)(\\d{3})(\\d{2})(\\d{3})","$1 $2 $3 $4","60","$FG",],["(1230)(\\d{3})(\\d{4})","$1 $2 $3","1","$FG",],["(\\d{4,5})","$1","[1-9]","$FG","NA"]]]',
+"56": '["CL","(?:0|1(?:1[0-69]|2[0-57]|5[13-58]|69|7[0167]|8[018]))0","0","0|(1(?:1[0-69]|2[0-57]|5[13-58]|69|7[0167]|8[018]))",,"$NP$FG","\\d{6,11}","(?:[2-9]|600|123)\\d{7,8}",[["(\\d)(\\d{4})(\\d{4})","$1 $2 $3","2","($FG)",],["(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","[357]|4[1-35]|6[13-57]","($FG)",],["(\\d{2})(\\d{2})(\\d{4})","$1 $2 $3","65","($FG)",],["(9)([5-9]\\d{3})(\\d{4})","$1 $2 $3","9",,],["(44)(\\d{3})(\\d{4})","$1 $2 $3","44",,],["([68]00)(\\d{3})(\\d{3,4})","$1 $2 $3","60|8","$FG",],["(600)(\\d{3})(\\d{2})(\\d{3})","$1 $2 $3 $4","60","$FG",],["(1230)(\\d{3})(\\d{4})","$1 $2 $3","1","$FG",],["(\\d{4,5})","$1","[1-9]","$FG","NA"]]]',
 "596": '["MQ","00","0",,,"$NP$FG","\\d{9}","[56]\\d{8}",[["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
 "508": '["PM","00","0",,,"$NP$FG","\\d{6}","[45]\\d{5}",[["([45]\\d)(\\d{2})(\\d{2})","$1 $2 $3",,,]]]',
 "269": '["KM","00",,,,,"\\d{7}","[379]\\d{6}",[["(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3",,,]]]',
 "358": ['["FI","00|99[049]","0",,,"$NP$FG","\\d{5,12}","1\\d{4,11}|[2-9]\\d{4,10}",[["(\\d{3})(\\d{3,7})","$1 $2","(?:[1-3]00|[6-8]0)",,],["(\\d{2})(\\d{4,10})","$1 $2","[14]|2[09]|50|7[135]",,],["(\\d)(\\d{4,11})","$1 $2","[25689][1-8]|3",,]]]','["AX","00|99[049]","0",,,"$NP$FG","\\d{5,12}","[135]\\d{5,9}|[27]\\d{4,9}|4\\d{5,10}|6\\d{7,8}|8\\d{6,9}",]'],
 "251": '["ET","00","0",,,"$NP$FG","\\d{7,9}","[1-59]\\d{8}",[["([1-59]\\d)(\\d{3})(\\d{4})","$1 $2 $3",,,]]]',
 "681": '["WF","00",,,,,"\\d{6}","[5-7]\\d{5}",[["(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3",,,]]]',
 "853": '["MO","00",,,,,"\\d{8}","[268]\\d{7}",[["([268]\\d{3})(\\d{4})","$1 $2",,,]]]',
 "44": ['["GB","00","0",,,"$NP$FG","\\d{4,10}","\\d{7,10}",[["(\\d{2})(\\d{4})(\\d{4})","$1 $2 $3","2|5[56]|7(?:0|6[013-9])",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","1(?:1|\\d1)|3|9[018]",,],["(\\d{5})(\\d{4,5})","$1 $2","1(?:38|5[23]|69|76|94)",,],["(1\\d{3})(\\d{5,6})","$1 $2","1",,],["(7\\d{3})(\\d{6})","$1 $2","7(?:[1-5789]|62)",,],["(800)(\\d{4})","$1 $2","800",,],["(845)(46)(4\\d)","$1 $2 $3","845",,],["(8\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","8(?:4[2-5]|7[0-3])",,],["(80\\d)(\\d{3})(\\d{4})","$1 $2 $3","80",,],["([58]00)(\\d{6})","$1 $2","[58]00",,]]]','["GG","00","0",,,"$NP$FG","\\d{6,10}","[135789]\\d{6,9}",]','["IM","00","0",,,"$NP$FG","\\d{6,10}","[135789]\\d{6,9}",]','["JE","00","0",,,"$NP$FG","\\d{6,10}","[135789]\\d{6,9}",]'],
@@ -210,13 +210,13 @@ this.PHONE_NUMBER_META_DATA = {
 "211": '["SS","00","0",,,,"\\d{9}","[19]\\d{8}",[["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3",,"$NP$FG",]]]',
 "373": '["MD","00","0",,,"$NP$FG","\\d{8}","[235-9]\\d{7}",[["(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3","22|3",,],["([25-7]\\d{2})(\\d{2})(\\d{3})","$1 $2 $3","2[13-79]|[5-7]",,],["([89]\\d{2})(\\d{5})","$1 $2","[89]",,]]]',
 "996": '["KG","00","0",,,"$NP$FG","\\d{5,10}","[35-8]\\d{8,9}",[["(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3","31[25]|[5-7]",,],["(\\d{4})(\\d{5})","$1 $2","3(?:1[36]|[2-9])",,],["(\\d{3})(\\d{3})(\\d)(\\d{3})","$1 $2 $3 $4","8",,]]]',
 "93": '["AF","00","0",,,"$NP$FG","\\d{7,9}","[2-7]\\d{8}",[["([2-7]\\d)(\\d{3})(\\d{4})","$1 $2 $3",,,]]]',
 "260": '["ZM","00","0",,,"$NP$FG","\\d{9}","[289]\\d{8}",[["([29]\\d)(\\d{7})","$1 $2","[29]",,],["(800)(\\d{3})(\\d{3})","$1 $2 $3","8",,]]]',
 "378": '["SM","00",,"(?:0549)?([89]\\d{5})","0549$1",,"\\d{6,10}","[05-7]\\d{7,9}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","[5-7]",,],["(0549)(\\d{6})","$1 $2","0",,"($1) $2"],["(\\d{6})","0549 $1","[89]",,"(0549) $1"]]]',
 "235": '["TD","00|16",,,,,"\\d{8}","[2679]\\d{7}",[["(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
 "960": '["MV","0(?:0|19)",,,,,"\\d{7,10}","[3467]\\d{6}|9(?:00\\d{7}|\\d{6})",[["(\\d{3})(\\d{4})","$1-$2","[3467]|9(?:[1-9]|0[1-9])",,],["(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3","900",,]]]',
-"221": '["SN","00",,,,,"\\d{9}","[37]\\d{8}",[["(\\d{2})(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4",,,]]]',
+"221": '["SN","00",,,,,"\\d{9}","[378]\\d{8}",[["(\\d{2})(\\d{3})(\\d{2})(\\d{2})","$1 $2 $3 $4","[37]",,],["(\\d{3})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4","8",,]]]',
 "595": '["PY","00","0",,,,"\\d{5,9}","5[0-5]\\d{4,7}|[2-46-9]\\d{5,8}",[["(\\d{2})(\\d{5,7})","$1 $2","(?:[26]1|3[289]|4[124678]|7[123]|8[1236])","($FG)",],["(\\d{3})(\\d{3,6})","$1 $2","[2-9]0","$NP$FG",],["(\\d{3})(\\d{6})","$1 $2","9[1-9]","$NP$FG",],["(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3","8700",,],["(\\d{3})(\\d{4,6})","$1 $2","[2-8][1-9]","($FG)",]]]',
 "977": '["NP","00","0",,,"$NP$FG","\\d{6,10}","[1-8]\\d{7}|9(?:[1-69]\\d{6}|7[2-6]\\d{5,7}|8\\d{8})",[["(1)(\\d{7})","$1-$2","1[2-6]",,],["(\\d{2})(\\d{6})","$1-$2","1[01]|[2-8]|9(?:[1-69]|7[15-9])",,],["(9\\d{2})(\\d{7})","$1-$2","9(?:7[45]|8)",,]]]',
 "36": '["HU","00","06",,,"($FG)","\\d{6,9}","[1-9]\\d{7,8}",[["(1)(\\d{3})(\\d{4})","$1 $2 $3","1",,],["(\\d{2})(\\d{3})(\\d{3,4})","$1 $2 $3","[2-9]",,]]]',
 };
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -81,17 +81,18 @@ class nsGeolocationRequest
   bool WantsHighAccuracy() {return !mShutdown && mOptions && mOptions->mEnableHighAccuracy;}
   void SetTimeoutTimer();
   void StopTimeoutTimer();
   void NotifyErrorAndShutdown(uint16_t);
   nsIPrincipal* GetPrincipal();
 
   ~nsGeolocationRequest();
 
-  virtual bool Recv__delete__(const bool& allow) MOZ_OVERRIDE;
+  virtual bool Recv__delete__(const bool& allow,
+                              const InfallibleTArray<PermissionChoice>& choices) MOZ_OVERRIDE;
   virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
 
   bool IsWatch() { return mIsWatchPositionRequest; }
   int32_t WatchId() { return mWatchId; }
  private:
   bool mIsWatchPositionRequest;
 
   nsCOMPtr<nsITimer> mTimeoutTimer;
@@ -190,17 +191,17 @@ public:
   RequestAllowEvent(int allow, nsGeolocationRequest* request)
     : mAllow(allow),
       mRequest(request)
   {
   }
 
   NS_IMETHOD Run() {
     if (mAllow) {
-      mRequest->Allow();
+      mRequest->Allow(JS::UndefinedHandleValue);
     } else {
       mRequest->Cancel();
     }
     return NS_OK;
   }
 
 private:
   bool mAllow;
@@ -376,18 +377,20 @@ nsGeolocationRequest::GetPrincipal(nsIPr
   principal.forget(aRequestingPrincipal);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGeolocationRequest::GetTypes(nsIArray** aTypes)
 {
+  nsTArray<nsString> emptyOptions;
   return CreatePermissionArray(NS_LITERAL_CSTRING("geolocation"),
                                NS_LITERAL_CSTRING("unused"),
+                               emptyOptions,
                                aTypes);
 }
 
 NS_IMETHODIMP
 nsGeolocationRequest::GetWindow(nsIDOMWindow * *aRequestingWindow)
 {
   NS_ENSURE_ARG_POINTER(aRequestingWindow);
 
@@ -408,18 +411,20 @@ nsGeolocationRequest::GetElement(nsIDOME
 NS_IMETHODIMP
 nsGeolocationRequest::Cancel()
 {
   NotifyError(nsIDOMGeoPositionError::PERMISSION_DENIED);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsGeolocationRequest::Allow()
+nsGeolocationRequest::Allow(JS::HandleValue aChoices)
 {
+  MOZ_ASSERT(aChoices.isUndefined());
+
   // Kick off the geo device, if it isn't already running
   nsRefPtr<nsGeolocationService> gs = nsGeolocationService::GetGeolocationService();
   nsresult rv = gs->StartDevice(GetPrincipal());
 
   if (NS_FAILED(rv)) {
     // Location provider error
     NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE);
     return NS_OK;
@@ -595,20 +600,23 @@ nsGeolocationRequest::Shutdown()
   if (mOptions && mOptions->mEnableHighAccuracy) {
     nsRefPtr<nsGeolocationService> gs = nsGeolocationService::GetGeolocationService();
     if (gs) {
       gs->UpdateAccuracy();
     }
   }
 }
 
-bool nsGeolocationRequest::Recv__delete__(const bool& allow)
+bool nsGeolocationRequest::Recv__delete__(const bool& allow,
+                                          const InfallibleTArray<PermissionChoice>& choices)
 {
+  MOZ_ASSERT(choices.IsEmpty(), "Geolocation doesn't support permission choice");
+
   if (allow) {
-    (void) Allow();
+    (void) Allow(JS::UndefinedHandleValue);
   } else {
     (void) Cancel();
   }
   return true;
 }
 ////////////////////////////////////////////////////
 // nsGeolocationService
 ////////////////////////////////////////////////////
@@ -1356,17 +1364,17 @@ Geolocation::WatchPositionReady(nsGeoloc
 
     return NS_OK;
   }
 
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_FAILURE;
   }
 
-  aRequest->Allow();
+  aRequest->Allow(JS::UndefinedHandleValue);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Geolocation::ClearWatch(int32_t aWatchId)
 {
   if (aWatchId < 0) {
@@ -1467,18 +1475,20 @@ Geolocation::RegisterRequestWithPrompt(n
     // because owner implements nsITabChild, we can assume that it is
     // the one and only TabChild.
     TabChild* child = TabChild::GetFrom(window->GetDocShell());
     if (!child) {
       return false;
     }
 
     nsTArray<PermissionRequest> permArray;
+    nsTArray<nsString> emptyOptions;
     permArray.AppendElement(PermissionRequest(NS_LITERAL_CSTRING("geolocation"),
-                                              NS_LITERAL_CSTRING("unused")));
+                                              NS_LITERAL_CSTRING("unused"),
+                                              emptyOptions));
 
     // Retain a reference so the object isn't deleted without IPDL's knowledge.
     // Corresponding release occurs in DeallocPContentPermissionRequest.
     request->AddRef();
     child->SendPContentPermissionRequestConstructor(request,
                                                     permArray,
                                                     IPC::Principal(mPrincipal));
 
--- a/dom/src/notification/DesktopNotification.cpp
+++ b/dom/src/notification/DesktopNotification.cpp
@@ -44,20 +44,22 @@ public:
     }
     return NS_OK;
   }
 
   ~DesktopNotificationRequest()
   {
   }
 
-  virtual bool Recv__delete__(const bool& aAllow) MOZ_OVERRIDE
+  virtual bool Recv__delete__(const bool& aAllow,
+                              const InfallibleTArray<PermissionChoice>& choices) MOZ_OVERRIDE
   {
+    MOZ_ASSERT(choices.IsEmpty(), "DesktopNotification doesn't support permission choice");
     if (aAllow) {
-      (void) Allow();
+      (void) Allow(JS::UndefinedHandleValue);
     } else {
      (void) Cancel();
     }
    return true;
   }
   virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
 
   nsRefPtr<DesktopNotification> mDesktopNotification;
@@ -174,19 +176,21 @@ DesktopNotification::Init()
     // the one and only TabChild for this docshell.
     TabChild* child = TabChild::GetFrom(GetOwner()->GetDocShell());
 
     // Retain a reference so the object isn't deleted without IPDL's knowledge.
     // Corresponding release occurs in DeallocPContentPermissionRequest.
     nsRefPtr<DesktopNotificationRequest> copy = request;
 
     nsTArray<PermissionRequest> permArray;
+    nsTArray<nsString> emptyOptions;
     permArray.AppendElement(PermissionRequest(
                             NS_LITERAL_CSTRING("desktop-notification"),
-                            NS_LITERAL_CSTRING("unused")));
+                            NS_LITERAL_CSTRING("unused"),
+                            emptyOptions));
     child->SendPContentPermissionRequestConstructor(copy.forget().get(),
                                                     permArray,
                                                     IPC::Principal(mPrincipal));
 
     request->Sendprompt();
     return;
   }
 
@@ -342,25 +346,28 @@ NS_IMETHODIMP
 DesktopNotificationRequest::Cancel()
 {
   nsresult rv = mDesktopNotification->SetAllow(false);
   mDesktopNotification = nullptr;
   return rv;
 }
 
 NS_IMETHODIMP
-DesktopNotificationRequest::Allow()
+DesktopNotificationRequest::Allow(JS::HandleValue aChoices)
 {
+  MOZ_ASSERT(aChoices.isUndefined());
   nsresult rv = mDesktopNotification->SetAllow(true);
   mDesktopNotification = nullptr;
   return rv;
 }
 
 NS_IMETHODIMP
 DesktopNotificationRequest::GetTypes(nsIArray** aTypes)
 {
+  nsTArray<nsString> emptyOptions;
   return CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
                                NS_LITERAL_CSTRING("unused"),
+                               emptyOptions,
                                aTypes);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/src/notification/Notification.cpp
+++ b/dom/src/notification/Notification.cpp
@@ -158,17 +158,18 @@ public:
   NotificationPermissionRequest(nsIPrincipal* aPrincipal, nsPIDOMWindow* aWindow,
                                 NotificationPermissionCallback* aCallback)
     : mPrincipal(aPrincipal), mWindow(aWindow),
       mPermission(NotificationPermission::Default),
       mCallback(aCallback) {}
 
   virtual ~NotificationPermissionRequest() {}
 
-  bool Recv__delete__(const bool& aAllow);
+  bool Recv__delete__(const bool& aAllow,
+                      const InfallibleTArray<PermissionChoice>& choices);
   void IPDLRelease() { Release(); }
 
 protected:
   nsresult CallCallback();
   nsresult DispatchCallback();
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsPIDOMWindow> mWindow;
   NotificationPermission mPermission;
@@ -264,19 +265,21 @@ NotificationPermissionRequest::Run()
       return NS_ERROR_NOT_AVAILABLE;
     }
 
     // Retain a reference so the object isn't deleted without IPDL's knowledge.
     // Corresponding release occurs in DeallocPContentPermissionRequest.
     AddRef();
 
     nsTArray<PermissionRequest> permArray;
+    nsTArray<nsString> emptyOptions;
     permArray.AppendElement(PermissionRequest(
                             NS_LITERAL_CSTRING("desktop-notification"),
-                            NS_LITERAL_CSTRING("unused")));
+                            NS_LITERAL_CSTRING("unused"),
+                            emptyOptions));
     child->SendPContentPermissionRequestConstructor(this, permArray,
                                                     IPC::Principal(mPrincipal));
 
     Sendprompt();
     return NS_OK;
   }
 
   nsCOMPtr<nsIContentPermissionPrompt> prompt =
@@ -313,18 +316,20 @@ NotificationPermissionRequest::GetElemen
 NS_IMETHODIMP
 NotificationPermissionRequest::Cancel()
 {
   mPermission = NotificationPermission::Denied;
   return DispatchCallback();
 }
 
 NS_IMETHODIMP
-NotificationPermissionRequest::Allow()
+NotificationPermissionRequest::Allow(JS::HandleValue aChoices)
 {
+  MOZ_ASSERT(aChoices.isUndefined());
+
   mPermission = NotificationPermission::Granted;
   return DispatchCallback();
 }
 
 inline nsresult
 NotificationPermissionRequest::DispatchCallback()
 {
   if (!mCallback) {
@@ -342,26 +347,31 @@ NotificationPermissionRequest::CallCallb
   ErrorResult rv;
   mCallback->Call(mPermission, rv);
   return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 NotificationPermissionRequest::GetTypes(nsIArray** aTypes)
 {
+  nsTArray<nsString> emptyOptions;
   return CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
                                NS_LITERAL_CSTRING("unused"),
+                               emptyOptions,
                                aTypes);
 }
 
 bool
-NotificationPermissionRequest::Recv__delete__(const bool& aAllow)
+NotificationPermissionRequest::Recv__delete__(const bool& aAllow,
+                                              const InfallibleTArray<PermissionChoice>& choices)
 {
+  MOZ_ASSERT(choices.IsEmpty(), "Notification doesn't support permission choice");
+
   if (aAllow) {
-    (void) Allow();
+    (void) Allow(JS::UndefinedHandleValue);
   } else {
     (void) Cancel();
   }
   return true;
 }
 
 NS_IMPL_ISUPPORTS1(NotificationTask, nsIRunnable)
 
--- a/dom/tests/mochitest/bugs/test_bug370098.html
+++ b/dom/tests/mochitest/bugs/test_bug370098.html
@@ -19,17 +19,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 /** Test for Bug 370098 **/
 function test_constructor(dom_proto, shouldthrow) {
     var threw = false;
     try {
         window[dom_proto]();
     } catch (e) {
         threw = true;
     }
-    is(threw, shouldthrow, "Calling |" + dom_proto + "()| should" + (shouldthrow ? " " : " not ") + "throw");
+    if (shouldthrow)
+      ok(threw, "Calling |" + dom_proto + "()| should throw");
+    else
+      todo(threw, "Calling |" + dom_proto + "()| should throw");
 
     threw = false;
     try {
         new window[dom_proto]();
     } catch (e) {
         threw = true;
     }
     is(threw, shouldthrow, "Calling |new " + dom_proto + "()| should" + (shouldthrow ? " " : " not ") + "throw");
--- a/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
+++ b/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
@@ -102,26 +102,26 @@ https://bugzilla.mozilla.org/show_bug.cg
         isnot(Object.getOwnPropertyNames(xhr).indexOf("DONE"), -1,
               "We should claim to have a DONE constant");
         isnot(Object.getOwnPropertyDescriptor(xhr, "prototype"), undefined,
               "We should claim to have 'prototype' property");
       } catch (e) {
         ok(false, "'XMLHttpRequest' shouldn't throw in a sandbox");
       }
       try {
-        var xhr = Components.utils.evalInSandbox("XMLHttpRequest()", sandbox);
+        var xhr = Components.utils.evalInSandbox("new XMLHttpRequest()", sandbox);
         is("" + xhr, "[object XrayWrapper " + XMLHttpRequest() + "]", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
       } catch (e) {
-        ok(false, "'XMLHttpRequest()' shouldn't throw in a sandbox");
+        ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox (1)");
       }
       try {
-        var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype.toString = function () { return 'Failed'; }; XMLHttpRequest();", sandbox);
+        var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype.toString = function () { return 'Failed'; }; new XMLHttpRequest();", sandbox);
         is(xhr.toString(), "[object XrayWrapper " + XMLHttpRequest() + "]", "XMLHttpRequest.prototype.toString in the sandbox should not override the native toString behaviour");
       } catch (e) {
-        ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox");
+        ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox (2)");
       }
 
       try {
         // have to run this test before document.defaultView.XMLHttpRequest
         // gets munged in the sandbox.
         var proto = Components.utils.evalInSandbox("XMLHttpRequest.prototype", sandbox);
         props = [];
         for (var i in proto) {
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1181,26 +1181,26 @@ public:
     if (!filename) {
       return false;
     }
 
     // We should not fire error events for warnings but instead make sure that
     // they show up in the error console.
     if (!JSREPORT_IS_WARNING(aFlags)) {
       // First fire an ErrorEvent at the worker.
+      ErrorEventInit init;
+      init.mMessage = aMessage;
+      init.mFilename = aFilename;
+      init.mLineno = aLineNumber;
+      init.mCancelable = true;
+      init.mBubbles = true;
+
       if (aTarget) {
-        ErrorEventInit init;
-        init.mMessage = aMessage;
-        init.mFilename = aFilename;
-        init.mLineno = aLineNumber;
-        init.mCancelable = true;
-
         nsRefPtr<ErrorEvent> event =
           ErrorEvent::Constructor(aTarget, NS_LITERAL_STRING("error"), init);
-
         event->SetTrusted(true);
 
         nsEventStatus status = nsEventStatus_eIgnore;
         aTarget->DispatchDOMEvent(nullptr, event, nullptr, &status);
 
         if (status == nsEventStatus_eConsumeNoDefault) {
           return true;
         }
@@ -1214,40 +1214,32 @@ public:
 
         nsEventStatus status = nsEventStatus_eIgnore;
         nsIScriptGlobalObject* sgo;
 
         if (aWorkerPrivate) {
           WorkerGlobalScope* globalTarget = aWorkerPrivate->GlobalScope();
           MOZ_ASSERT(target == globalTarget->GetWrapperPreserveColor());
 
-          // Icky, we have to fire an InternalScriptErrorEvent...
-          MOZ_ASSERT(!NS_IsMainThread());
-          InternalScriptErrorEvent event(true, NS_USER_DEFINED_EVENT);
-          event.lineNr = aLineNumber;
-          event.errorMsg = aMessage.get();
-          event.fileName = aFilename.get();
-          event.typeString = NS_LITERAL_STRING("error");
+          nsRefPtr<ErrorEvent> event =
+            ErrorEvent::Constructor(aTarget, NS_LITERAL_STRING("error"), init);
+          event->SetTrusted(true);
 
           nsIDOMEventTarget* target = static_cast<nsIDOMEventTarget*>(globalTarget);
-          if (NS_FAILED(nsEventDispatcher::Dispatch(target, nullptr, &event,
-                                                    nullptr, &status))) {
+          if (NS_FAILED(nsEventDispatcher::DispatchDOMEvent(target, nullptr,
+                                                            event, nullptr,
+                                                            &status))) {
             NS_WARNING("Failed to dispatch worker thread error event!");
             status = nsEventStatus_eIgnore;
           }
         }
         else if ((sgo = nsJSUtils::GetStaticScriptGlobal(target))) {
-          // Icky, we have to fire an InternalScriptErrorEvent...
           MOZ_ASSERT(NS_IsMainThread());
-          InternalScriptErrorEvent event(true, NS_LOAD_ERROR);
-          event.lineNr = aLineNumber;
-          event.errorMsg = aMessage.get();
-          event.fileName = aFilename.get();
-
-          if (NS_FAILED(sgo->HandleScriptError(&event, &status))) {
+
+          if (NS_FAILED(sgo->HandleScriptError(init, &status))) {
             NS_WARNING("Failed to dispatch main thread error event!");
             status = nsEventStatus_eIgnore;
           }
         }
 
         // Was preventDefault() called?
         if (status == nsEventStatus_eConsumeNoDefault) {
           return true;
@@ -3188,23 +3180,25 @@ WorkerPrivateParent<Derived>::BroadcastE
 
     AutoCxPusher autoPush(cx);
 
     nsCOMPtr<nsIScriptGlobalObject> sgo =
       do_QueryInterface(windowAction.mWindow);
     MOZ_ASSERT(sgo);
 
     MOZ_ASSERT(NS_IsMainThread());
-    InternalScriptErrorEvent event(true, NS_LOAD_ERROR);
-    event.lineNr = aLineNumber;
-    event.errorMsg = aMessage.BeginReading();
-    event.fileName = aFilename.BeginReading();
+    ErrorEventInit init;
+    init.mLineno = aLineNumber;
+    init.mFilename = aFilename;
+    init.mMessage = aMessage;
+    init.mCancelable = true;
+    init.mBubbles = true;
 
     nsEventStatus status = nsEventStatus_eIgnore;
-    rv = sgo->HandleScriptError(&event, &status);
+    rv = sgo->HandleScriptError(init, &status);
     if (NS_FAILED(rv)) {
       Throw(cx, rv);
       JS_ReportPendingException(cx);
       continue;
     }
 
     if (status == nsEventStatus_eConsumeNoDefault) {
       shouldLogErrorToConsole = false;
--- a/dom/workers/test/mochitest.ini
+++ b/dom/workers/test/mochitest.ini
@@ -56,16 +56,18 @@ support-files =
   transferable_worker.js
   urlApi_worker.js
   url_worker.js
   workersDisabled_worker.js
   xhr2_worker.js
   xhrAbort_worker.js
   xhr_implicit_cancel_worker.js
   xhr_worker.js
+  xhr_headers_worker.js
+  xhr_headers_server.sjs
   url_exceptions_worker.js
   urlSearchParams_worker.js
   subdir/relativeLoad_sub_worker.js
   subdir/relativeLoad_sub_worker2.js
   subdir/relativeLoad_sub_import.js
 
 [test_404.html]
 [test_atob.html]
@@ -118,16 +120,17 @@ skip-if = toolkit == 'android' #bug 8814
 [test_timeoutTracing.html]
 [test_transferable.html]
 [test_url.html]
 [test_urlApi.html]
 [test_workersDisabled.html]
 [test_xhr.html]
 [test_xhr2.html]
 [test_xhrAbort.html]
+[test_xhr_headers.html]
 [test_xhr_implicit_cancel.html]
 [test_xhr_parameters.html]
 [test_xhr_parameters.js]
 [test_xhr_system.html]
 [test_xhr_system.js]
 [test_xhr_timeout.html]
 skip-if = (os == "win") || (os == "mac") || toolkit == 'android' #bug 798220
 [test_url_exceptions.html]
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_xhr_headers.html
@@ -0,0 +1,85 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <title>Test for XHR Headers</title>
+    <script src="/tests/SimpleTest/SimpleTest.js">
+    </script>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+  </head>
+  <body>
+    <p id="display"></p>
+    <div id="content" style="display: none"></div>
+    <pre id="test">
+      <script class="testbody">
+"use strict";
+
+SimpleTest.waitForExplicitFinish();
+
+var path =
+  location.pathname.substring(0, location.pathname.lastIndexOf("/") + 1);
+var filenamePrefix = "xhr_headers_";
+var serverFilename = filenamePrefix + "server.sjs";
+var workerFilename = filenamePrefix + "worker.js";
+var otherHost = "example.com";
+
+info("Informing server about the current host");
+
+var xhr = new XMLHttpRequest();
+xhr.open("POST", path + serverFilename);
+xhr.setRequestHeader("options-host", otherHost);
+xhr.onreadystatechange = function() {
+  if (xhr.readyState == 4) {
+    info("Launching worker");
+
+    var worker = new Worker(path + workerFilename);
+    worker.postMessage("http://" + otherHost + path + serverFilename);
+
+    worker.onmessage = function(event) {
+      ok(event.data.response === "", "Worker responded, saw no response");
+
+      var loopCount = 0;
+
+      function checkServer() {
+        var xhr2 = new XMLHttpRequest();
+        xhr2.open("GET", path + serverFilename);
+        xhr2.onreadystatechange = function() {
+          if (xhr2.readyState == 4) {
+            if (xhr2.responseText) {
+              is(xhr2.responseText,
+                 "Success: expected OPTIONS request with '" +
+                 event.data.header + "' header",
+                 "Server saw expected requests");
+              SimpleTest.finish();
+            } else if (++loopCount < 30) {
+              setTimeout(checkServer, 1000);
+            } else {
+              ok(false, "Server never saw any requests");
+              SimpleTest.finish();
+            }
+          }
+        };
+
+        info("Checking server status (" + loopCount + ")");
+        xhr2.send();
+      }
+
+      checkServer();
+    };
+
+    worker.onerror = function(event) {
+      ok(false, "Worker had an error: '" + event.message + "'");
+      event.preventDefault();
+      SimpleTest.finish();
+    };
+  }
+};
+xhr.send();
+
+      </script>
+    </pre>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/xhr_headers_server.sjs
@@ -0,0 +1,51 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+"use strict";
+
+function handleRequest(request, response) {
+  switch (request.method) {
+    case "POST":
+      try {
+        var optionsHost = request.getHeader("options-host");
+      } catch(e) { }
+
+      if (optionsHost) {
+        setState("postHost", request.host);
+        setState("optionsHost", optionsHost);
+        return;
+      }
+      break;
+
+    case "OPTIONS":
+      if (getState("optionsHost") == request.host) {
+        try {
+          var optionsHeader =
+            request.getHeader("Access-Control-Request-Headers");
+        } catch(e) { }
+        setState("optionsHeader", "'" + optionsHeader + "'");
+      }
+      break;
+
+    case "GET":
+      response.setHeader("Cache-Control", "no-cache", false);
+      response.setHeader("Content-Type", "text/plain", false);
+
+      if (getState("postHost") == request.host) {
+        var result = getState("optionsHeader");
+        if (result) {
+          response.write("Success: expected OPTIONS request with " + result +
+                         " header");
+        } else if (getState("badGet") == 1) {
+          response.write("Error: unexpected GET request");
+        }
+      } else {
+        setState("badGet", "1");
+        response.write("Error: this response should never be seen");
+      }
+      return;
+  }
+
+  response.setStatusLine(request.httpVersion, 501, "Not Implemented");
+}
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/xhr_headers_worker.js
@@ -0,0 +1,16 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+"use strict";
+
+var customHeader = "custom-key";
+var customHeaderValue = "custom-key-value";
+
+self.onmessage = function(event) {
+  var xhr = new XMLHttpRequest();
+  xhr.open("GET", event.data, false);
+  xhr.setRequestHeader(customHeader, customHeaderValue);
+  xhr.send();
+  postMessage({ response: xhr.responseText, header: customHeader });
+}
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -654,16 +654,21 @@ CreateConfig(EGLConfig* aConfig)
     int32_t depth = gfxPlatform::GetPlatform()->GetScreenDepth();
     if (!CreateConfig(aConfig, depth)) {
 #ifdef MOZ_WIDGET_ANDROID
         // Bug 736005
         // Android doesn't always support 16 bit so also try 24 bit
         if (depth == 16) {
             return CreateConfig(aConfig, 24);
         }
+        // Bug 970096
+        // Some devices that have 24 bit screens only support 16 bit OpenGL?
+        if (depth == 24) {
+            return CreateConfig(aConfig, 16);
+        }
 #endif
         return false;
     } else {
         return true;
     }
 }
 
 already_AddRefed<GLContext>
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -396,55 +396,66 @@ GLXLibrary::CreatePixmap(gfxASurface* aS
                                         cfgs[matchIndex],
                                         xs->XDrawable(),
                                         pixmapAttribs);
 
     return glxpixmap;
 }
 
 void
-GLXLibrary::DestroyPixmap(GLXPixmap aPixmap)
+GLXLibrary::DestroyPixmap(Display* aDisplay, GLXPixmap aPixmap)
 {
     if (!mUseTextureFromPixmap) {
         return;
     }
 
-    Display *display = DefaultXDisplay();
-    xDestroyPixmap(display, aPixmap);
+    xDestroyPixmap(aDisplay, aPixmap);
 }
 
 void
-GLXLibrary::BindTexImage(GLXPixmap aPixmap)
+GLXLibrary::BindTexImage(Display* aDisplay, GLXPixmap aPixmap)
 {
     if (!mUseTextureFromPixmap) {
         return;
     }
 
-    Display *display = DefaultXDisplay();
     // Make sure all X drawing to the surface has finished before binding to a texture.
     if (mClientIsMesa) {
         // Using XSync instead of Mesa's glXWaitX, because its glxWaitX is a
         // noop when direct rendering unless the current drawable is a
         // single-buffer window.
-        FinishX(display);
+        FinishX(aDisplay);
     } else {
         xWaitX();
     }
-    xBindTexImage(display, aPixmap, LOCAL_GLX_FRONT_LEFT_EXT, nullptr);
+    xBindTexImage(aDisplay, aPixmap, LOCAL_GLX_FRONT_LEFT_EXT, nullptr);
 }
 
 void
-GLXLibrary::ReleaseTexImage(GLXPixmap aPixmap)
+GLXLibrary::ReleaseTexImage(Display* aDisplay, GLXPixmap aPixmap)
 {
     if (!mUseTextureFromPixmap) {
         return;
     }
 
-    Display *display = DefaultXDisplay();
-    xReleaseTexImage(display, aPixmap, LOCAL_GLX_FRONT_LEFT_EXT);
+    xReleaseTexImage(aDisplay, aPixmap, LOCAL_GLX_FRONT_LEFT_EXT);
+}
+
+void
+GLXLibrary::UpdateTexImage(Display* aDisplay, GLXPixmap aPixmap)
+{
+    // NVIDIA drivers don't require a rebind of the pixmap in order
+    // to display an updated image, and it's faster not to do it.
+    if (mIsNVIDIA) {
+        xWaitX();
+        return;
+    }
+
+    ReleaseTexImage(aDisplay, aPixmap);
+    BindTexImage(aDisplay, aPixmap);
 }
 
 #ifdef DEBUG
 
 static int (*sOldErrorHandler)(Display *, XErrorEvent *);
 ScopedXErrorHandler::ErrorEvent sErrorEvent;
 static int GLXErrorHandler(Display *display, XErrorEvent *ev)
 {
--- a/gfx/gl/GLXLibrary.h
+++ b/gfx/gl/GLXLibrary.h
@@ -93,19 +93,20 @@ public:
                                      GLXFBConfig config, 
                                      GLXContext share_list, 
                                      Bool direct,
                                      const int* attrib_list);
 
     bool EnsureInitialized();
 
     GLXPixmap CreatePixmap(gfxASurface* aSurface);
-    void DestroyPixmap(GLXPixmap aPixmap);
-    void BindTexImage(GLXPixmap aPixmap);
-    void ReleaseTexImage(GLXPixmap aPixmap);
+    void DestroyPixmap(Display* aDisplay, GLXPixmap aPixmap);
+    void BindTexImage(Display* aDisplay, GLXPixmap aPixmap);
+    void ReleaseTexImage(Display* aDisplay, GLXPixmap aPixmap);
+    void UpdateTexImage(Display* aDisplay, GLXPixmap aPixmap);
 
     bool UseTextureFromPixmap() { return mUseTextureFromPixmap; }
     bool HasRobustness() { return mHasRobustness; }
     bool SupportsTextureFromPixmap(gfxASurface* aSurface);
     bool IsATI() { return mIsATI; }
     bool GLXVersionCheck(int aMajor, int aMinor);
 
 private:
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -728,23 +728,25 @@ struct ParamTraits<mozilla::layers::Scro
 template <>
 struct ParamTraits<mozilla::layers::ZoomConstraints>
 {
   typedef mozilla::layers::ZoomConstraints paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mAllowZoom);
+    WriteParam(aMsg, aParam.mAllowDoubleTapZoom);
     WriteParam(aMsg, aParam.mMinZoom);
     WriteParam(aMsg, aParam.mMaxZoom);
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mAllowZoom) &&
+            ReadParam(aMsg, aIter, &aResult->mAllowDoubleTapZoom) &&
             ReadParam(aMsg, aIter, &aResult->mMinZoom) &&
             ReadParam(aMsg, aIter, &aResult->mMaxZoom));
   }
 };
 
 template <>
 struct ParamTraits<mozilla::layers::EventRegions>
 {
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -405,43 +405,48 @@ struct ScrollableLayerGuid {
   bool operator!=(const ScrollableLayerGuid& other) const
   {
     return !(*this == other);
   }
 };
 
 struct ZoomConstraints {
   bool mAllowZoom;
+  bool mAllowDoubleTapZoom;
   CSSToScreenScale mMinZoom;
   CSSToScreenScale mMaxZoom;
 
   ZoomConstraints()
     : mAllowZoom(true)
+    , mAllowDoubleTapZoom(true)
   {
     MOZ_COUNT_CTOR(ZoomConstraints);
   }
 
   ZoomConstraints(bool aAllowZoom,
+                  bool aAllowDoubleTapZoom,
                   const CSSToScreenScale& aMinZoom,
                   const CSSToScreenScale& aMaxZoom)
     : mAllowZoom(aAllowZoom)
+    , mAllowDoubleTapZoom(aAllowDoubleTapZoom)
     , mMinZoom(aMinZoom)
     , mMaxZoom(aMaxZoom)
   {
     MOZ_COUNT_CTOR(ZoomConstraints);
   }
 
   ~ZoomConstraints()
   {
     MOZ_COUNT_DTOR(ZoomConstraints);
   }
 
   bool operator==(const ZoomConstraints& other) const
   {
     return mAllowZoom == other.mAllowZoom
+        && mAllowDoubleTapZoom == other.mAllowDoubleTapZoom
         && mMinZoom == other.mMinZoom
         && mMaxZoom == other.mMaxZoom;
   }
 
   bool operator!=(const ZoomConstraints& other) const
   {
     return !(*this == other);
   }
--- a/gfx/layers/GrallocImages.h
+++ b/gfx/layers/GrallocImages.h
@@ -3,21 +3,22 @@
  * 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 GRALLOCIMAGES_H
 #define GRALLOCIMAGES_H
 
 #ifdef MOZ_WIDGET_GONK
 
-#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
-#include "mozilla/layers/LayersSurfaces.h"
-#include "mozilla/gfx/Point.h"
 #include "ImageLayers.h"
 #include "ImageContainer.h"
+#include "mozilla/gfx/Point.h"
+#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
+#include "mozilla/layers/FenceUtils.h"
+#include "mozilla/layers/LayersSurfaces.h"
 
 #include <ui/GraphicBuffer.h>
 
 namespace mozilla {
 namespace layers {
 
 class GrallocTextureClientOGL;
 
@@ -41,16 +42,26 @@ public:
 
   virtual ~GraphicBufferLocked() {}
 
   SurfaceDescriptor GetSurfaceDescriptor()
   {
     return mSurfaceDescriptor;
   }
 
+  void SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle)
+  {
+    mReleaseFenceHandle = aReleaseFenceHandle;
+  }
+
+  const FenceHandle& GetReleaseFenceHandle() const
+  {
+    return mReleaseFenceHandle;
+  }
+
 protected:
   virtual void Unlock() {}
 
 private:
   /**
    * Called once, just before the destructor.
    *
    * Here goes the shut-down code that uses virtual methods.
@@ -60,16 +71,17 @@ private:
   {
     Unlock();
   }
 
   friend class AtomicRefCountedWithFinalize<GraphicBufferLocked>;
 
 protected:
   SurfaceDescriptor mSurfaceDescriptor;
+  FenceHandle mReleaseFenceHandle;
 };
 
 /**
  * The YUV format supported by Android HAL
  *
  * 4:2:0 - CbCr width and height is half that of Y.
  *
  * This format assumes
--- a/gfx/layers/LayersTypes.h
+++ b/gfx/layers/LayersTypes.h
@@ -33,16 +33,17 @@ struct PRLogModuleInfo;
 
 namespace android {
 class GraphicBuffer;
 }
 
 namespace mozilla {
 namespace layers {
 
+class TextureHost;
 
 typedef uint32_t TextureFlags;
 
 #undef NONE
 #undef OPAQUE
 
 MOZ_BEGIN_ENUM_CLASS(LayersBackend, int8_t)
   LAYERS_NONE = 0,
@@ -83,28 +84,30 @@ enum LayerRenderStateFlags {
   LAYER_RENDER_STATE_FORMAT_RB_SWAP = 1 << 2
 };
 
 // The 'ifdef MOZ_WIDGET_GONK' sadness here is because we don't want to include
 // android::sp unless we have to.
 struct LayerRenderState {
   LayerRenderState()
 #ifdef MOZ_WIDGET_GONK
-    : mSurface(nullptr), mFlags(0), mHasOwnOffset(false)
+    : mSurface(nullptr), mFlags(0), mHasOwnOffset(false), mTexture(nullptr)
 #endif
   {}
 
 #ifdef MOZ_WIDGET_GONK
   LayerRenderState(android::GraphicBuffer* aSurface,
                    const nsIntSize& aSize,
-                   uint32_t aFlags)
+                   uint32_t aFlags,
+                   TextureHost* aTexture)
     : mSurface(aSurface)
     , mSize(aSize)
     , mFlags(aFlags)
     , mHasOwnOffset(false)
+    , mTexture(aTexture)
   {}
 
   bool YFlipped() const
   { return mFlags & LAYER_RENDER_STATE_Y_FLIPPED; }
 
   bool BufferRotated() const
   { return mFlags & LAYER_RENDER_STATE_BUFFER_ROTATION; }
 
@@ -118,16 +121,17 @@ struct LayerRenderState {
     mHasOwnOffset = true;
   }
 
 #ifdef MOZ_WIDGET_GONK
   // surface to render
   android::sp<android::GraphicBuffer> mSurface;
   // size of mSurface 
   nsIntSize mSize;
+  TextureHost* mTexture;
 #endif
   // see LayerRenderStateFlags
   uint32_t mFlags;
   // the location of the layer's origin on mSurface
   nsIntPoint mOffset;
   // true if mOffset is applicable
   bool mHasOwnOffset;
 };
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -373,16 +373,30 @@ ClientLayerManager::ForwardTransaction(b
         CompositableChild* compositableChild =
           static_cast<CompositableChild*>(ots.compositableChild());
         MOZ_ASSERT(compositableChild);
 
         compositableChild->GetCompositableClient()
           ->SetDescriptorFromReply(ots.textureId(), ots.image());
         break;
       }
+      case EditReply::TReturnReleaseFence: {
+        const ReturnReleaseFence& rep = reply.get_ReturnReleaseFence();
+        FenceHandle fence = rep.fence();
+        PTextureChild* child = rep.textureChild();
+
+        if (!fence.IsValid() || !child) {
+          break;
+        }
+        RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child);
+        if (texture) {
+          texture->SetReleaseFenceHandle(fence);
+        }
+        break;
+      }
 
       default:
         NS_RUNTIMEABORT("not reached");
       }
     }
 
     if (sent) {
       mNeedsComposite = false;
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -15,17 +15,16 @@
 #include "mozilla/ipc/SharedMemory.h"   // for SharedMemory, etc
 #include "mozilla/layers/CompositableClient.h"  // for CompositableClient
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/ShadowLayers.h"  // for ShadowLayerForwarder
 #include "mozilla/layers/SharedPlanarYCbCrImage.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
-#include "mozilla/layers/PTextureChild.h"
 #include "nsDebug.h"                    // for NS_ASSERTION, NS_WARNING, etc
 #include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "ImageContainer.h"             // for PlanarYCbCrImage, etc
 #include "mozilla/gfx/2D.h"
 
 #ifdef MOZ_ANDROID_OMTC
 #  include "gfxReusableImageSurfaceWrapper.h"
 #  include "gfxImageSurface.h"
@@ -154,16 +153,23 @@ TextureClient::CreateIPDLActor()
 // static
 bool
 TextureClient::DestroyIPDLActor(PTextureChild* actor)
 {
   static_cast<TextureChild*>(actor)->ReleaseIPDLReference();
   return true;
 }
 
+// static
+TextureClient*
+TextureClient::AsTextureClient(PTextureChild* actor)
+{
+  return actor? static_cast<TextureChild*>(actor)->mTextureClient : nullptr;
+}
+
 bool
 TextureClient::InitIPDLActor(CompositableForwarder* aForwarder)
 {
   MOZ_ASSERT(aForwarder);
   if (mActor && mActor->GetForwarder() == aForwarder) {
     return true;
   }
   MOZ_ASSERT(!mActor, "Cannot use a texture on several IPC channels.");
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -12,20 +12,22 @@
 #include "GLTextureImage.h"             // for TextureImage
 #include "ImageTypes.h"                 // for StereoMode
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/RefPtr.h"             // for RefPtr, RefCounted
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat
+#include "mozilla/layers/FenceUtils.h"  // for FenceHandle
 #include "mozilla/ipc/Shmem.h"          // for Shmem
 #include "mozilla/layers/AtomicRefCountedWithFinalize.h"
 #include "mozilla/layers/CompositorTypes.h"  // for TextureFlags, etc
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
+#include "mozilla/layers/PTextureChild.h" // for PTextureChild
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsISupportsImpl.h"            // for TextureImage::AddRef, etc
 
 class gfxReusableSurfaceWrapper;
 class gfxASurface;
 class gfxImageSurface;
@@ -225,16 +227,21 @@ public:
    * TextureChild is an implementation detail of TextureHost that is not
    * exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor
    * are for use with the maging IPDL protocols only (so that they can
    * implement AllocPextureChild and DeallocPTextureChild).
    */
   static PTextureChild* CreateIPDLActor();
   static bool DestroyIPDLActor(PTextureChild* actor);
 
+  /**
+   * Get the TextureClient corresponding to the actor passed in parameter.
+   */
+  static TextureClient* AsTextureClient(PTextureChild* actor);
+
   virtual bool IsAllocated() const = 0;
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
 
   virtual gfx::IntSize GetSize() const = 0;
 
   /**
    * TextureFlags contain important information about various aspects
@@ -282,16 +289,23 @@ public:
    * Triggers the destruction of the shared data and the corresponding TextureHost.
    *
    * If the texture flags contain TEXTURE_DEALLOCATE_CLIENT, the destruction
    * will be synchronously coordinated with the compositor side, otherwise it
    * will be done asynchronously.
    */
   void ForceRemove();
 
+  virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle) {}
+
+  const FenceHandle& GetReleaseFenceHandle() const
+  {
+    return mReleaseFenceHandle;
+  }
+
 private:
   /**
    * Called once, just before the destructor.
    *
    * Here goes the shut-down code that uses virtual methods.
    * Must only be called by Release().
    */
   void Finalize();
@@ -320,16 +334,17 @@ protected:
     MOZ_ASSERT(!IsSharedWithCompositor());
     mFlags |= aFlags;
   }
 
   RefPtr<TextureChild> mActor;
   TextureFlags mFlags;
   bool mShared;
   bool mValid;
+  FenceHandle mReleaseFenceHandle;
 
   friend class TextureChild;
 };
 
 /**
  * TextureClient that wraps a random access buffer such as a Shmem or raw memory.
  * This class must be inherited to implement the memory allocation and access bits.
  * (see ShmemTextureClient and MemoryTextureClient)
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -31,16 +31,19 @@ CompositableHost::CompositableHost(const
   , mKeepAttached(false)
 {
   MOZ_COUNT_CTOR(CompositableHost);
 }
 
 CompositableHost::~CompositableHost()
 {
   MOZ_COUNT_DTOR(CompositableHost);
+  if (mBackendData) {
+    mBackendData->ClearData();
+  }
 }
 
 void
 CompositableHost::UseTextureHost(TextureHost* aTexture)
 {
   if (!aTexture) {
     return;
   }
@@ -57,16 +60,18 @@ CompositableHost::UseComponentAlphaTextu
   aTextureOnBlack->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
   aTextureOnWhite->SetCompositor(GetCompositor());
   aTextureOnWhite->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
 }
 
 void
 CompositableHost::RemoveTextureHost(TextureHost* aTexture)
 {
+  // Clear strong refrence to CompositableBackendSpecificData
+  aTexture->SetCompositableBackendSpecificData(nullptr);
 }
 
 void
 CompositableHost::SetCompositor(Compositor* aCompositor)
 {
   mCompositor = aCompositor;
 }
 
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -14,16 +14,17 @@
 #include "mozilla/RefPtr.h"             // for RefPtr, RefCounted, etc
 #include "mozilla/gfx/Point.h"          // for Point
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/gfx/Types.h"          // for Filter
 #include "mozilla/ipc/ProtocolUtils.h"
 #include "mozilla/layers/CompositorTypes.h"  // for TextureInfo, etc
 #include "mozilla/layers/LayersTypes.h"  // for LayerRenderState, etc
 #include "mozilla/layers/PCompositableParent.h"
+#include "mozilla/layers/TextureHost.h" // for TextureHost
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nscore.h"                     // for nsACString
 #include "Units.h"                      // for CSSToScreenScale
 
 struct nsIntPoint;
 struct nsIntRect;
@@ -41,17 +42,16 @@ struct TiledLayerProperties
 {
   nsIntRegion mVisibleRegion;
   nsIntRegion mValidRegion;
   CSSToScreenScale mEffectiveResolution;
 };
 
 class Layer;
 class DeprecatedTextureHost;
-class TextureHost;
 class SurfaceDescriptor;
 class Compositor;
 class ISurfaceAllocator;
 class ThebesBufferData;
 class TiledLayerComposer;
 struct EffectChain;
 
 /**
@@ -65,17 +65,55 @@ public:
   {
     MOZ_COUNT_CTOR(CompositableBackendSpecificData);
   }
   virtual ~CompositableBackendSpecificData()
   {
     MOZ_COUNT_DTOR(CompositableBackendSpecificData);
   }
   virtual void SetCompositor(Compositor* aCompositor) {}
-  virtual void ClearData() {}
+  virtual void ClearData()
+  {
+    mCurrentReleaseFenceTexture = nullptr;
+    ClearPendingReleaseFenceTextureList();
+  }
+
+  /**
+   * Store a texture currently used for Composition.
+   * This function is called when the texutre might receive ReleaseFence
+   * as a result of Composition.
+   */
+  void SetCurrentReleaseFenceTexture(TextureHost* aTexture)
+  {
+    if (mCurrentReleaseFenceTexture) {
+      mPendingReleaseFenceTextures.push_back(mCurrentReleaseFenceTexture);
+    }
+    mCurrentReleaseFenceTexture = aTexture;
+  }
+
+  virtual std::vector< RefPtr<TextureHost> >& GetPendingReleaseFenceTextureList()
+  {
+    return mPendingReleaseFenceTextures;
+  }
+
+  virtual void ClearPendingReleaseFenceTextureList()
+  {
+    return mPendingReleaseFenceTextures.clear();
+  }
+protected:
+  /**
+   * Store a TextureHost currently used for Composition
+   * and it might receive ReleaseFence for the texutre.
+   */
+  RefPtr<TextureHost> mCurrentReleaseFenceTexture;
+  /**
+   * Store TextureHosts that might have ReleaseFence to be delivered
+   * to TextureClient by CompositableHost.
+   */
+  std::vector< RefPtr<TextureHost> > mPendingReleaseFenceTextures;
 };
 
 /**
  * The compositor-side counterpart to CompositableClient. Responsible for
  * updating textures and data about textures from IPC and how textures are
  * composited (tiling, double buffering, etc.).
  *
  * Update (for images/canvases) and UpdateThebes (for Thebes) are called during
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -84,16 +84,22 @@ TextureHost::SendDeleteIPDLActor(PTextur
 
 // static
 TextureHost*
 TextureHost::AsTextureHost(PTextureParent* actor)
 {
   return actor? static_cast<TextureParent*>(actor)->mTextureHost : nullptr;
 }
 
+PTextureParent*
+TextureHost::GetIPDLActor()
+{
+  return mActor;
+}
+
 // implemented in TextureOGL.cpp
 TemporaryRef<DeprecatedTextureHost> CreateDeprecatedTextureHostOGL(SurfaceDescriptorType aDescriptorType,
                                                            uint32_t aDeprecatedTextureHostFlags,
                                                            uint32_t aTextureFlags);
 // implemented in BasicCompositor.cpp
 TemporaryRef<DeprecatedTextureHost> CreateBasicDeprecatedTextureHost(SurfaceDescriptorType aDescriptorType,
                                                              uint32_t aDeprecatedTextureHostFlags,
                                                              uint32_t aTextureFlags);
@@ -237,17 +243,18 @@ CreateBackendIndependentTextureHost(cons
 void
 TextureHost::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
 {
     mCompositableBackendData = aBackendData;
 }
 
 
 TextureHost::TextureHost(TextureFlags aFlags)
-    : mFlags(aFlags)
+    : mActor(nullptr)
+    , mFlags(aFlags)
 {}
 
 TextureHost::~TextureHost()
 {
 }
 
 void TextureHost::Finalize()
 {
@@ -718,16 +725,17 @@ TextureParent::~TextureParent()
 
 bool
 TextureParent::Init(const SurfaceDescriptor& aSharedData,
                     const TextureFlags& aFlags)
 {
   mTextureHost = TextureHost::Create(aSharedData,
                                      mAllocator,
                                      aFlags);
+  mTextureHost->mActor = this;
   return !!mTextureHost;
 }
 
 bool
 TextureParent::RecvRemoveTexture()
 {
   return PTextureParent::Send__delete__(this);
 }
@@ -755,13 +763,15 @@ TextureParent::ActorDestroy(ActorDestroy
     break;
   case FailedConstructor:
     NS_RUNTIMEABORT("FailedConstructor isn't possible in PTexture");
   }
 
   if (mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
     mTextureHost->ForgetSharedData();
   }
+
+  mTextureHost->mActor = nullptr;
   mTextureHost = nullptr;
 }
 
 } // namespace
 } // namespace
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -38,16 +38,17 @@ class Shmem;
 
 namespace layers {
 
 class Compositor;
 class CompositableHost;
 class CompositableBackendSpecificData;
 class SurfaceDescriptor;
 class ISurfaceAllocator;
+class TextureHostOGL;
 class TextureSourceOGL;
 class TextureSourceD3D9;
 class TextureSourceD3D11;
 class TextureSourceBasic;
 class DataTextureSource;
 class PTextureParent;
 class TextureParent;
 
@@ -268,17 +269,16 @@ class TextureHost
    * Called once, just before the destructor.
    *
    * Here goes the shut-down code that uses virtual methods.
    * Must only be called by Release().
    */
   void Finalize();
 
   friend class AtomicRefCountedWithFinalize<TextureHost>;
-
 public:
   TextureHost(TextureFlags aFlags);
 
   virtual ~TextureHost();
 
   /**
    * Factory method.
    */
@@ -391,16 +391,24 @@ public:
   static bool SendDeleteIPDLActor(PTextureParent* actor);
 
   /**
    * Get the TextureHost corresponding to the actor passed in parameter.
    */
   static TextureHost* AsTextureHost(PTextureParent* actor);
 
   /**
+   * Return a pointer to the IPDLActor.
+   *
+   * This is to be used with IPDL messages only. Do not store the returned
+   * pointer.
+   */
+  PTextureParent* GetIPDLActor();
+
+  /**
    * Specific to B2G's Composer2D
    * XXX - more doc here
    */
   virtual LayerRenderState GetRenderState()
   {
     // By default we return an empty render state, this should be overridden
     // by the TextureHost implementations that are used on B2G with Composer2D
     return LayerRenderState();
@@ -413,19 +421,27 @@ public:
   virtual void OnShutdown() {}
 
   // Forget buffer actor. Used only for hacky fix for bug 966446. 
   virtual void ForgetBufferActor() {}
 
   virtual const char *Name() { return "TextureHost"; }
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 
+  /**
+   * Cast to a TextureHost for each backend.
+   */
+  virtual TextureHostOGL* AsHostOGL() { return nullptr; }
+
 protected:
+  PTextureParent* mActor;
   TextureFlags mFlags;
   RefPtr<CompositableBackendSpecificData> mCompositableBackendData;
+
+  friend class TextureParent;
 };
 
 /**
  * TextureHost that wraps a random access buffer such as a Shmem or some raw
  * memory.
  *
  * This TextureHost is backend-independent and the backend-specific bits are
  * in the TextureSource.
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -445,17 +445,17 @@ AsyncPanZoomController::AsyncPanZoomCont
      mGeckoContentController(aGeckoContentController),
      mRefPtrMonitor("RefPtrMonitor"),
      mMonitor("AsyncPanZoomController"),
      mTouchActionPropertyEnabled(gTouchActionPropertyEnabled),
      mContentResponseTimeoutTask(nullptr),
      mX(MOZ_THIS_IN_INITIALIZER_LIST()),
      mY(MOZ_THIS_IN_INITIALIZER_LIST()),
      mPanDirRestricted(false),
-     mZoomConstraints(false, MIN_ZOOM, MAX_ZOOM),
+     mZoomConstraints(false, false, MIN_ZOOM, MAX_ZOOM),
      mLastSampleTime(GetFrameTime()),
      mState(NOTHING),
      mLastAsyncScrollTime(GetFrameTime()),
      mLastAsyncScrollOffset(0, 0),
      mCurrentAsyncScrollOffset(0, 0),
      mAsyncScrollTimeoutTask(nullptr),
      mHandlingTouchQueue(false),
      mAllowedTouchBehaviorSet(false),
@@ -952,19 +952,19 @@ nsEventStatus AsyncPanZoomController::On
     }
   }
   return nsEventStatus_eIgnore;
 }
 
 nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a single-tap-up in state %d\n", this, mState);
   nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
-  // If mZoomConstraints.mAllowZoom is true we wait for a call to OnSingleTapConfirmed before
+  // If mZoomConstraints.mAllowDoubleTapZoom is true we wait for a call to OnSingleTapConfirmed before
   // sending event to content
-  if (controller && !AllowZoom()) {
+  if (controller && !AllowDoubleTapZoom()) {
     int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
     CSSIntPoint geckoScreenPoint;
     if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
       // Because this may be being running as part of APZCTreeManager::ReceiveInputEvent,
       // calling controller->HandleSingleTap directly might mean that content receives
       // the single tap message before the corresponding touch-up. To avoid that we
       // schedule the singletap message to run on the next spin of the event loop.
       // See bug 965381 for the issue this was causing.
@@ -995,17 +995,17 @@ nsEventStatus AsyncPanZoomController::On
   }
   return nsEventStatus_eIgnore;
 }
 
 nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a double-tap in state %d\n", this, mState);
   nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (controller) {
-    if (AllowZoom()) {
+    if (AllowDoubleTapZoom()) {
       int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
       CSSIntPoint geckoScreenPoint;
       if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
         controller->HandleDoubleTap(geckoScreenPoint, modifiers, GetGuid());
       }
     }
 
     return nsEventStatus_eConsumeNoDefault;
@@ -1956,39 +1956,45 @@ bool AsyncPanZoomController::IsPanningSt
 bool AsyncPanZoomController::AllowZoom() {
   // In addition to looking at the zoom constraints, which comes from the meta
   // viewport tag, disallow zooming if we are overflow:hidden in either direction.
   ReentrantMonitorAutoEnter lock(mMonitor);
   return mZoomConstraints.mAllowZoom
       && !(mFrameMetrics.GetDisableScrollingX() || mFrameMetrics.GetDisableScrollingY());
 }
 
+bool AsyncPanZoomController::AllowDoubleTapZoom() {
+  ReentrantMonitorAutoEnter lock(mMonitor);
+  return mZoomConstraints.mAllowDoubleTapZoom && AllowZoom();
+}
+
 void AsyncPanZoomController::SetContentResponseTimer() {
   if (!mContentResponseTimeoutTask) {
     mContentResponseTimeoutTask =
       NewRunnableMethod(this, &AsyncPanZoomController::TimeoutContentResponse);
 
     PostDelayedTask(mContentResponseTimeoutTask, gContentResponseTimeout);
   }
 }
 
 void AsyncPanZoomController::TimeoutContentResponse() {
   mContentResponseTimeoutTask = nullptr;
   ContentReceivedTouch(false);
 }
 
 void AsyncPanZoomController::UpdateZoomConstraints(const ZoomConstraints& aConstraints) {
-  APZC_LOG("%p updating zoom constraints to %d %f %f\n", this, aConstraints.mAllowZoom,
-    aConstraints.mMinZoom.scale, aConstraints.mMaxZoom.scale);
+  APZC_LOG("%p updating zoom constraints to %d %d %f %f\n", this, aConstraints.mAllowZoom,
+    aConstraints.mAllowDoubleTapZoom, aConstraints.mMinZoom.scale, aConstraints.mMaxZoom.scale);
   if (IsFloatNaN(aConstraints.mMinZoom.scale) || IsFloatNaN(aConstraints.mMaxZoom.scale)) {
     NS_WARNING("APZC received zoom constraints with NaN values; dropping...\n");
     return;
   }
   // inf float values and other bad cases should be sanitized by the code below.
   mZoomConstraints.mAllowZoom = aConstraints.mAllowZoom;
+  mZoomConstraints.mAllowDoubleTapZoom = aConstraints.mAllowDoubleTapZoom;
   mZoomConstraints.mMinZoom = (MIN_ZOOM > aConstraints.mMinZoom ? MIN_ZOOM : aConstraints.mMinZoom);
   mZoomConstraints.mMaxZoom = (MAX_ZOOM > aConstraints.mMaxZoom ? aConstraints.mMaxZoom : MAX_ZOOM);
   if (mZoomConstraints.mMaxZoom < mZoomConstraints.mMinZoom) {
     mZoomConstraints.mMaxZoom = mZoomConstraints.mMinZoom;
   }
 }
 
 ZoomConstraints
--- a/gfx/layers/ipc/AsyncPanZoomController.h
+++ b/gfx/layers/ipc/AsyncPanZoomController.h
@@ -595,16 +595,17 @@ private:
 
   /**
    * Internal helpers for checking general state of this apzc.
    */
   bool IsTransformingState(PanZoomState aState);
   bool IsPanningState(PanZoomState mState);
 
   bool AllowZoom();
+  bool AllowDoubleTapZoom();
 
   enum AxisLockMode {
     FREE,     /* No locking at all */
     STANDARD, /* Default axis locking mode that remains locked until pan ends*/
     STICKY,   /* Allow lock to be broken, with hysteresis */
   };
 
   static AxisLockMode GetAxisLockMode();
--- a/gfx/layers/ipc/Axis.cpp
+++ b/gfx/layers/ipc/Axis.cpp
@@ -42,22 +42,29 @@ static float gFlingStoppedThreshold = 0.
 
 /**
  * Maximum size of velocity queue. The queue contains last N velocity records.
  * On touch end we calculate the average velocity in order to compensate
  * touch/mouse drivers misbehaviour.
  */
 static uint32_t gMaxVelocityQueueSize = 5;
 
+/**
+ * Maximum velocity in pixels per millisecond.  Velocity will be capped at this
+ * value if a faster fling occurs.  Negative values indicate unlimited velocity.
+ */
+static float gMaxVelocity = -1.0f;
+
 static void ReadAxisPrefs()
 {
   Preferences::AddFloatVarCache(&gMaxEventAcceleration, "apz.max_event_acceleration", gMaxEventAcceleration);
   Preferences::AddFloatVarCache(&gFlingFriction, "apz.fling_friction", gFlingFriction);
   Preferences::AddFloatVarCache(&gFlingStoppedThreshold, "apz.fling_stopped_threshold", gFlingStoppedThreshold);
   Preferences::AddUintVarCache(&gMaxVelocityQueueSize, "apz.max_velocity_queue_size", gMaxVelocityQueueSize);
+  Preferences::AddFloatVarCache(&gMaxVelocity, "apz.max_velocity_pixels_per_ms", gMaxVelocity);
 }
 
 class ReadAxisPref MOZ_FINAL : public nsRunnable {
 public:
   NS_IMETHOD Run()
   {
     ReadAxisPrefs();
     return NS_OK;
@@ -85,16 +92,19 @@ Axis::Axis(AsyncPanZoomController* aAsyn
     mAxisLocked(false),
     mAsyncPanZoomController(aAsyncPanZoomController)
 {
   InitAxisPrefs();
 }
 
 void Axis::UpdateWithTouchAtDevicePoint(int32_t aPos, const TimeDuration& aTimeDelta) {
   float newVelocity = mAxisLocked ? 0 : (mPos - aPos) / aTimeDelta.ToMilliseconds();
+  if (gMaxVelocity > 0.0f) {
+    newVelocity = std::min(newVelocity, gMaxVelocity);
+  }
 
   mVelocity = newVelocity;
   mPos = aPos;
 
   // Keep last gMaxVelocityQueueSize or less velocities in the queue.
   mVelocityQueue.AppendElement(mVelocity);
   if (mVelocityQueue.Length() > gMaxVelocityQueueSize) {
     mVelocityQueue.RemoveElementAt(0);
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -3,27 +3,29 @@
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CompositableTransactionParent.h"
 #include "CompositableHost.h"           // for CompositableParent, etc
 #include "CompositorParent.h"           // for CompositorParent
+#include "GLContext.h"                  // for GLContext
 #include "Layers.h"                     // for Layer
 #include "RenderTrace.h"                // for RenderTraceInvalidateEnd, etc
 #include "TiledLayerBuffer.h"           // for TiledLayerComposer
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/ContentHost.h"  // for ContentHostBase
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/LayersTypes.h"  // for MOZ_LAYERS_LOG
 #include "mozilla/layers/TextureHost.h"  // for TextureHost
+#include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
 #include "mozilla/layers/ThebesLayerComposite.h"
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsDebug.h"                    // for NS_WARNING, NS_ASSERTION
 #include "nsRegion.h"                   // for nsIntRegion
 
 namespace mozilla {
 namespace layers {
 
@@ -154,16 +156,18 @@ CompositableParentManager::ReceiveCompos
           ScheduleComposition(op);
         }
       }
 
       if (layer) {
         RenderTraceInvalidateEnd(layer, "FF00FF");
       }
 
+      // return texure data to client if necessary
+      ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
       break;
     }
     case CompositableOperation::TOpPaintTextureRegion: {
       MOZ_LAYERS_LOG(("[ParentSide] Paint ThebesLayer"));
 
       const OpPaintTextureRegion& op = aEdit.get_OpPaintTextureRegion();
       CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent());
       CompositableHost* compositable =
@@ -185,16 +189,18 @@ CompositableParentManager::ReceiveCompos
                                       &frontUpdatedRegion))
       {
         return false;
       }
       replyv.push_back(
         OpContentBufferSwap(compositableParent, nullptr, frontUpdatedRegion));
 
       RenderTraceInvalidateEnd(thebes, "FF00FF");
+      // return texure data to client if necessary
+      ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
       break;
     }
     case CompositableOperation::TOpPaintTextureIncremental: {
       MOZ_LAYERS_LOG(("[ParentSide] Paint ThebesLayer"));
 
       const OpPaintTextureIncremental& op = aEdit.get_OpPaintTextureIncremental();
 
       CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent());
@@ -234,16 +240,18 @@ CompositableParentManager::ReceiveCompos
     }
     case CompositableOperation::TOpRemoveTexture: {
       const OpRemoveTexture& op = aEdit.get_OpRemoveTexture();
       CompositableHost* compositable = AsCompositable(op);
       RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
 
       MOZ_ASSERT(tex.get());
       compositable->RemoveTextureHost(tex);
+      // return texure data to client if necessary
+      ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
       break;
     }
     case CompositableOperation::TOpUseTexture: {
       const OpUseTexture& op = aEdit.get_OpUseTexture();
       CompositableHost* compositable = AsCompositable(op);
       RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
 
       MOZ_ASSERT(tex.get());
@@ -252,47 +260,98 @@ CompositableParentManager::ReceiveCompos
       if (IsAsync()) {
         ScheduleComposition(op);
         // Async layer updates don't trigger invalidation, manually tell the layer
         // that its content have changed.
         if (compositable->GetLayer()) {
           compositable->GetLayer()->SetInvalidRectToVisibleRegion();
         }
       }
+      // return texure data to client if necessary
+      ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
       break;
     }
     case CompositableOperation::TOpUseComponentAlphaTextures: {
       const OpUseComponentAlphaTextures& op = aEdit.get_OpUseComponentAlphaTextures();
       CompositableHost* compositable = AsCompositable(op);
       RefPtr<TextureHost> texOnBlack = TextureHost::AsTextureHost(op.textureOnBlackParent());
       RefPtr<TextureHost> texOnWhite = TextureHost::AsTextureHost(op.textureOnWhiteParent());
 
       MOZ_ASSERT(texOnBlack && texOnWhite);
       compositable->UseComponentAlphaTextures(texOnBlack, texOnWhite);
 
       if (IsAsync()) {
         ScheduleComposition(op);
       }
+      // return texure data to client if necessary
+      ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
       break;
     }
     case CompositableOperation::TOpUpdateTexture: {
       const OpUpdateTexture& op = aEdit.get_OpUpdateTexture();
       RefPtr<TextureHost> texture = TextureHost::AsTextureHost(op.textureParent());
       MOZ_ASSERT(texture);
 
       texture->Updated(op.region().type() == MaybeRegion::TnsIntRegion
                        ? &op.region().get_nsIntRegion()
                        : nullptr); // no region means invalidate the entire surface
-
       break;
     }
 
     default: {
       MOZ_ASSERT(false, "bad type");
     }
   }
 
   return true;
 }
 
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+void
+CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable,
+                                                        EditReplyVector& replyv,
+                                                        PCompositableParent* aParent)
+{
+  if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) {
+    return;
+  }
+
+  const std::vector< RefPtr<TextureHost> > textureList =
+        aCompositable->GetCompositableBackendSpecificData()->GetPendingReleaseFenceTextureList();
+  // Return pending Texture data
+  for (size_t i = 0; i < textureList.size(); i++) {
+    TextureHostOGL* hostOGL = textureList[i]->AsHostOGL();
+    PTextureParent* actor = textureList[i]->GetIPDLActor();
+    if (!hostOGL || !actor) {
+      continue;
+    }
+    android::sp<android::Fence> fence = hostOGL->GetAndResetReleaseFence();
+    if (fence.get() && fence->isValid()) {
+      FenceHandle handle = FenceHandle(fence);
+      replyv.push_back(ReturnReleaseFence(aParent, nullptr, actor, nullptr, handle));
+      // Hold fence handle to prevent fence's file descriptor is closed before IPC happens.
+      mPrevFenceHandles.push_back(handle);
+    }
+  }
+  aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList();
+}
+#else
+void
+CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable,
+                                                       EditReplyVector& replyv,
+                                                       PCompositableParent* aParent)
+{
+  if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) {
+    return;
+  }
+  aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList();
+}
+#endif
+
+void
+CompositableParentManager::ClearPrevFenceHandles()
+{
+  mPrevFenceHandles.clear();
+}
+
 } // namespace
 } // namespace
 
--- a/gfx/layers/ipc/CompositableTransactionParent.h
+++ b/gfx/layers/ipc/CompositableTransactionParent.h
@@ -11,16 +11,18 @@
 #include <vector>                       // for vector
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
 #include "mozilla/layers/LayersMessages.h"  // for EditReply, etc
 
 namespace mozilla {
 namespace layers {
 
+class CompositableHost;
+
 typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
 
 // Since PCompositble has two potential manager protocols, we can't just call
 // the Manager() method usually generated when there's one manager protocol,
 // so both manager protocols implement this and we keep a reference to them
 // through this interface.
 class CompositableParentManager : public ISurfaceAllocator
 {
@@ -32,14 +34,22 @@ protected:
                                  EditReplyVector& replyv);
   bool IsOnCompositorSide() const MOZ_OVERRIDE { return true; }
 
   /**
    * Return true if this protocol is asynchronous with respect to the content
    * thread (ImageBridge for instance).
    */
   virtual bool IsAsync() const { return false; }
+
+  void ReturnTextureDataIfNecessary(CompositableHost* aCompositable,
+                                    EditReplyVector& replyv,
+                                    PCompositableParent* aParent);
+  void ClearPrevFenceHandles();
+
+protected:
+  std::vector<FenceHandle> mPrevFenceHandles;
 };
 
 } // namespace
 } // namespace
 
 #endif
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/FenceUtils.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* 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 IPC_FencerUtils_h
+#define IPC_FencerUtils_h
+
+#include "ipc/IPCMessageUtils.h"
+
+/**
+ * FenceHandle is used for delivering Fence object via ipc.
+ */
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+# include "mozilla/layers/FenceUtilsGonk.h"
+#else
+namespace mozilla {
+namespace layers {
+struct FenceHandle {
+  bool operator==(const FenceHandle&) const { return false; }
+  bool IsValid() const { return false; }
+};
+} // namespace layers
+} // namespace mozilla
+#endif // MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+
+namespace IPC {
+
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#else
+template <>
+struct ParamTraits<mozilla::layers::FenceHandle> {
+  typedef mozilla::layers::FenceHandle paramType;
+  static void Write(Message*, const paramType&) {}
+  static bool Read(const Message*, void**, paramType*) { return false; }
+};
+#endif // MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+
+} // namespace IPC
+
+#endif // IPC_FencerUtils_h
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/FenceUtilsGonk.cpp
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLContext.h"
+#include "mozilla/unused.h"
+#include "nsXULAppAPI.h"
+
+#include "FenceUtilsGonk.h"
+
+using namespace android;
+using namespace base;
+using namespace mozilla::layers;
+
+namespace IPC {
+
+void
+ParamTraits<FenceHandle>::Write(Message* aMsg,
+                                const paramType& aParam)
+{
+  Flattenable *flattenable = aParam.mFence.get();
+  size_t nbytes = flattenable->getFlattenedSize();
+  size_t nfds = flattenable->getFdCount();
+
+  char data[nbytes];
+  int fds[nfds];
+  flattenable->flatten(data, nbytes, fds, nfds);
+
+  aMsg->WriteSize(nbytes);
+  aMsg->WriteSize(nfds);
+
+  aMsg->WriteBytes(data, nbytes);
+  for (size_t n = 0; n < nfds; ++n) {
+    // These buffers can't die in transit because they're created
+    // synchonously and the parent-side buffer can only be dropped if
+    // there's a crash.
+    aMsg->WriteFileDescriptor(FileDescriptor(fds[n], false));
+  }
+}
+
+bool
+ParamTraits<FenceHandle>::Read(const Message* aMsg,
+                               void** aIter, paramType* aResult)
+{
+  size_t nbytes;
+  size_t nfds;
+  const char* data;
+
+  if (!aMsg->ReadSize(aIter, &nbytes) ||
+      !aMsg->ReadSize(aIter, &nfds) ||
+      !aMsg->ReadBytes(aIter, &data, nbytes)) {
+    return false;
+  }
+
+  int fds[nfds];
+
+  for (size_t n = 0; n < nfds; ++n) {
+    FileDescriptor fd;
+    if (!aMsg->ReadFileDescriptor(aIter, &fd)) {
+      return false;
+    }
+    // If the GraphicBuffer was shared cross-process, SCM_RIGHTS does
+    // the right thing and dup's the fd.  If it's shared cross-thread,
+    // SCM_RIGHTS doesn't dup the fd.  That's surprising, but we just
+    // deal with it here.  NB: only the "default" (master) process can
+    // alloc gralloc buffers.
+    bool sameProcess = (XRE_GetProcessType() == GeckoProcessType_Default);
+    int dupFd = sameProcess ? dup(fd.fd) : fd.fd;
+    fds[n] = dupFd;
+  }
+
+  sp<Fence> buffer(new Fence());
+  Flattenable *flattenable = buffer.get();
+
+  if (NO_ERROR == flattenable->unflatten(data, nbytes, fds, nfds)) {
+    aResult->mFence = buffer;
+    return true;
+  }
+  return false;
+}
+
+} // namespace IPC
+
+namespace mozilla {
+namespace layers {
+
+FenceHandle::FenceHandle(const sp<Fence>& aFence)
+  : mFence(aFence)
+{
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/FenceUtilsGonk.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layers_FenceUtilsGonk_h
+#define mozilla_layers_FenceUtilsGonk_h
+
+#include <unistd.h>
+#include <ui/Fence.h>
+
+#include "ipc/IPCMessageUtils.h"
+
+namespace mozilla {
+namespace layers {
+
+struct FenceHandle {
+  typedef android::Fence Fence;
+
+  FenceHandle()
+  { }
+  FenceHandle(const android::sp<Fence>& aFence);
+
+  bool operator==(const FenceHandle& aOther) const {
+    return mFence.get() == aOther.mFence.get();
+  }
+
+  bool IsValid() const
+  {
+    return mFence.get() && mFence->isValid();
+  }
+
+  android::sp<Fence> mFence;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+namespace IPC {
+
+template <>
+struct ParamTraits<mozilla::layers::FenceHandle> {
+  typedef mozilla::layers::FenceHandle paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam);
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
+};
+
+} // namespace IPC
+
+#endif  // mozilla_layers_FenceUtilsGonk_h
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -511,16 +511,30 @@ ImageBridgeChild::EndTransaction()
           static_cast<CompositableChild*>(ots.compositableChild());
 
       MOZ_ASSERT(compositableChild);
 
       compositableChild->GetCompositableClient()
         ->SetDescriptorFromReply(ots.textureId(), ots.image());
       break;
     }
+    case EditReply::TReturnReleaseFence: {
+      const ReturnReleaseFence& rep = reply.get_ReturnReleaseFence();
+      FenceHandle fence = rep.fence();
+      PTextureChild* child = rep.textureChild();
+
+      if (!fence.IsValid() || !child) {
+        break;
+      }
+      RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child);
+      if (texture) {
+        texture->SetReleaseFenceHandle(fence);
+      }
+      break;
+    }
     default:
       NS_RUNTIMEABORT("not reached");
     }
   }
 }
 
 
 PImageBridgeChild*
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -70,16 +70,19 @@ bool
 ImageBridgeParent::RecvUpdate(const EditArray& aEdits, EditReplyArray* aReply)
 {
   // If we don't actually have a compositor, then don't bother
   // creating any textures.
   if (Compositor::GetBackend() == LayersBackend::LAYERS_NONE) {
     return true;
   }
 
+  // Clear fence handles used in previsou transaction.
+  ClearPrevFenceHandles();
+
   EditReplyVector replyv;
   for (EditArray::index_type i = 0; i < aEdits.Length(); ++i) {
     ReceiveCompositableUpdate(aEdits[i], replyv);
   }
 
   aReply->SetCapacity(replyv.size());
   if (replyv.size() > 0) {
     aReply->AppendElements(&replyv.front(), replyv.size());
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -199,16 +199,19 @@ LayerTransactionParent::RecvUpdate(const
 #endif
 
   MOZ_LAYERS_LOG(("[ParentSide] received txn with %d edits", cset.Length()));
 
   if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
     return true;
   }
 
+  // Clear fence handles used in previsou transaction.
+  ClearPrevFenceHandles();
+
   EditReplyVector replyv;
 
   {
     AutoResolveRefLayers resolve(mShadowLayersManager->GetCompositionManager());
     layer_manager()->BeginTransaction();
   }
 
   for (EditArray::index_type i = 0; i < cset.Length(); ++i) {
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -34,16 +34,17 @@ using mozilla::dom::ScreenOrientation fr
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 using mozilla::LayerMargin from "Units.h";
 using mozilla::LayerPoint from "Units.h";
 using mozilla::LayerRect from "Units.h";
 using mozilla::layers::ScaleMode from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::EventRegions from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::DiagnosticTypes from "mozilla/layers/CompositorTypes.h";
 using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
+using struct mozilla::layers::FenceHandle from "mozilla/layers/FenceUtils.h";
 
 namespace mozilla {
 namespace layers {
 
 struct TargetConfig {
   nsIntRect naturalBounds;
   ScreenRotation rotation;
   nsIntRect clientBounds;
@@ -391,17 +392,25 @@ struct OpContentBufferSwap {
 };
 
 struct OpTextureSwap {
   PCompositable compositable;
   uint32_t textureId;
   SurfaceDescriptor image;
 };
 
+struct ReturnReleaseFence {
+  PCompositable compositable;
+  PTexture texture;
+  FenceHandle fence;
+};
+
 // Unit of a "changeset reply".  This is a weird abstraction, probably
 // only to be used for buffer swapping.
 union EditReply {
   OpContentBufferSwap;
   OpTextureSwap;
+
+  ReturnReleaseFence;
 };
 
 } // namespace
 } // namespace
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -124,16 +124,17 @@ EXPORTS.mozilla.layers += [
     'Effects.h',
     'ImageDataSerializer.h',
     'ipc/AsyncPanZoomController.h',
     'ipc/Axis.h',
     'ipc/CompositableForwarder.h',
     'ipc/CompositableTransactionParent.h',
     'ipc/CompositorChild.h',
     'ipc/CompositorParent.h',
+    'ipc/FenceUtils.h',
     'ipc/GeckoContentController.h',
     'ipc/GestureEventListener.h',
     'ipc/ImageBridgeChild.h',
     'ipc/ImageBridgeParent.h',
     'ipc/ISurfaceAllocator.h',
     'ipc/LayerTransactionChild.h',
     'ipc/LayerTransactionParent.h',
     'ipc/ShadowLayers.h',
@@ -197,16 +198,24 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
         'opengl/EGLImageHelpers.cpp',
         'opengl/GrallocTextureClient.cpp',
         'opengl/GrallocTextureHost.cpp',
     ]
     SOURCES += [
         'ipc/ShadowLayerUtilsGralloc.cpp',
     ]
 
+    if CONFIG['ANDROID_VERSION'] in ('18'):
+        EXPORTS.mozilla.layers += [
+            'ipc/FenceUtilsGonk.h',
+        ]
+        SOURCES += [
+            'ipc/FenceUtilsGonk.cpp',
+        ]
+
 UNIFIED_SOURCES += [
     'basic/BasicCanvasLayer.cpp',
     'basic/BasicColorLayer.cpp',
     'basic/BasicCompositor.cpp',
     'basic/BasicContainerLayer.cpp',
     'basic/BasicImages.cpp',
     'basic/BasicLayerManager.cpp',
     'basic/BasicLayersImpl.cpp',
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -191,27 +191,46 @@ GrallocTextureClientOGL::UpdateSurface(g
     tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
     tmpCtx->DrawSurface(aSurface, gfxSize(GetSize().width,
                                           GetSize().height));
   }
 
   return true;
 }
 
+void
+GrallocTextureClientOGL::SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle)
+{
+  if (mBufferLocked) {
+    mBufferLocked->SetReleaseFenceHandle(aReleaseFenceHandle);
+  } else {
+    mReleaseFenceHandle = aReleaseFenceHandle;
+  }
+}
+
 bool
 GrallocTextureClientOGL::Lock(OpenMode aMode)
 {
   MOZ_ASSERT(IsValid());
   if (!IsValid() || !IsAllocated()) {
     return false;
   }
 
   if (mMappedBuffer) {
     return true;
   }
+
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+  if (mReleaseFenceHandle.IsValid()) {
+    android::sp<Fence> fence = mReleaseFenceHandle.mFence;
+    fence->waitForever("GrallocTextureClientOGL::Lock");
+    mReleaseFenceHandle = FenceHandle();
+  }
+#endif
+
   uint32_t usage = 0;
   if (aMode & OPEN_READ) {
     usage |= GRALLOC_USAGE_SW_READ_OFTEN;
   }
   if (aMode & OPEN_WRITE) {
     usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
   }
   int32_t rv = mGraphicBuffer->lock(usage, reinterpret_cast<void**>(&mMappedBuffer));
--- a/gfx/layers/opengl/GrallocTextureClient.h
+++ b/gfx/layers/opengl/GrallocTextureClient.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_GRALLOCTEXTURECLIENT_H
 #define MOZILLA_GFX_GRALLOCTEXTURECLIENT_H
 #ifdef MOZ_WIDGET_GONK
 
 #include "mozilla/layers/TextureClient.h"
 #include "ISurfaceAllocator.h" // For IsSurfaceDescriptorValid
+#include "mozilla/layers/FenceUtils.h" // for FenceHandle
 #include "mozilla/layers/ShadowLayerUtilsGralloc.h"
 #include <ui/GraphicBuffer.h>
 
 namespace mozilla {
 namespace layers {
 
 class GraphicBufferLocked;
 
@@ -54,16 +55,23 @@ public:
   virtual bool IsAllocated() const MOZ_OVERRIDE;
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
 
   virtual bool UpdateSurface(gfxASurface* aSurface) MOZ_OVERRIDE;
 
   virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
 
+  virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle) MOZ_OVERRIDE;
+
+  const FenceHandle& GetReleaseFenceHandle() const
+  {
+    return mReleaseFenceHandle;
+  }
+
   void InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize);
 
   void SetTextureFlags(TextureFlags aFlags) { AddFlags(aFlags); }
 
   gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
 
   android::GraphicBuffer* GetGraphicBuffer()
   {
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -327,17 +327,18 @@ GrallocTextureHostOGL::GetRenderState()
     if (mFlags & TEXTURE_NEEDS_Y_FLIP) {
       flags |= LAYER_RENDER_STATE_Y_FLIPPED;
     }
     if (mFlags & TEXTURE_RB_SWAPPED) {
       flags |= LAYER_RENDER_STATE_FORMAT_RB_SWAP;
     }
     return LayerRenderState(mTextureSource->mGraphicBuffer.get(),
                             gfx::ThebesIntSize(mSize),
-                            flags);
+                            flags,
+                            this);
   }
 
   return LayerRenderState();
 }
 
 TemporaryRef<gfx::DataSourceSurface>
 GrallocTextureHostOGL::GetAsSurface() {
   return mTextureSource ? mTextureSource->GetAsSurface()
@@ -374,12 +375,17 @@ GrallocTextureSourceOGL::GetGLTexture()
 
 void
 GrallocTextureHostOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
 {
   mCompositableBackendData = aBackendData;
   if (mTextureSource) {
     mTextureSource->SetCompositableBackendSpecificData(aBackendData);
   }
+  // Register this object to CompositableBackendSpecificData
+  // as current TextureHost.
+  if (aBackendData) {
+    aBackendData->SetCurrentReleaseFenceTexture(this);
+  }
 }
 
 } // namepsace layers
 } // namepsace mozilla
--- a/gfx/layers/opengl/GrallocTextureHost.h
+++ b/gfx/layers/opengl/GrallocTextureHost.h
@@ -66,16 +66,19 @@ protected:
   CompositorOGL* mCompositor;
   android::sp<android::GraphicBuffer> mGraphicBuffer;
   EGLImage mEGLImage;
   gfx::SurfaceFormat mFormat;
   bool mNeedsReset;
 };
 
 class GrallocTextureHostOGL : public TextureHost
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+                            , public TextureHostOGL
+#endif
 {
   friend class GrallocBufferActor;
 public:
   GrallocTextureHostOGL(TextureFlags aFlags,
                         const NewSurfaceDescriptorGralloc& aDescriptor);
 
   virtual ~GrallocTextureHostOGL();
 
@@ -99,16 +102,23 @@ public:
 
   virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
 
   virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE
   {
     return mTextureSource;
   }
 
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+  virtual TextureHostOGL* AsHostOGL() MOZ_OVERRIDE
+  {
+    return this;
+  }
+#endif
+
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
 
   virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) MOZ_OVERRIDE;
 
   bool IsValid() const;
 
   virtual const char* Name() MOZ_OVERRIDE { return "GrallocTextureHostOGL"; }
 
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -171,16 +171,17 @@ CompositableDataGonkOGL::gl() const
 
 void CompositableDataGonkOGL::SetCompositor(Compositor* aCompositor)
 {
   mCompositor = static_cast<CompositorOGL*>(aCompositor);
 }
 
 void CompositableDataGonkOGL::ClearData()
 {
+  CompositableBackendSpecificData::ClearData();
   DeleteTextureIfPresent();
 }
 
 GLuint CompositableDataGonkOGL::GetTexture()
 {
   if (!mTexture) {
     if (gl()->MakeCurrent()) {
       gl()->fGenTextures(1, &mTexture);
@@ -195,16 +196,51 @@ CompositableDataGonkOGL::DeleteTextureIf
   if (mTexture) {
     if (gl()->MakeCurrent()) {
       gl()->fDeleteTextures(1, &mTexture);
     }
     mTexture = 0;
   }
 }
 
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+bool
+TextureHostOGL::SetReleaseFence(const android::sp<android::Fence>& aReleaseFence)
+{
+  if (!aReleaseFence.get() || !aReleaseFence->isValid()) {
+    return false;
+  }
+
+  if (!mReleaseFence.get()) {
+    mReleaseFence = aReleaseFence;
+  } else {
+    android::sp<android::Fence> mergedFence = android::Fence::merge(
+                  android::String8::format("TextureHostOGL"),
+                  mReleaseFence, aReleaseFence);
+    if (!mergedFence.get()) {
+      // synchronization is broken, the best we can do is hope fences
+      // signal in order so the new fence will act like a union.
+      // This error handling is same as android::ConsumerBase does.
+      mReleaseFence = aReleaseFence;
+      return false;
+    }
+    mReleaseFence = mergedFence;
+  }
+  return true;
+}
+
+android::sp<android::Fence>
+TextureHostOGL::GetAndResetReleaseFence()
+{
+  android::sp<android::Fence> fence = mReleaseFence;
+  mReleaseFence = android::Fence::NO_FENCE;
+  return fence;
+}
+#endif
+
 bool
 TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface,
                                      nsIntRegion* aDestRegion,
                                      gfx::IntPoint* aSrcOffset)
 {
   MOZ_ASSERT(mGL);
   if (!mGL) {
     NS_WARNING("trying to update TextureImageTextureSourceOGL without a GLContext");
@@ -1150,17 +1186,18 @@ GrallocDeprecatedTextureHostOGL::GetRend
     if (mIsRBSwapped) {
       flags |= LAYER_RENDER_STATE_FORMAT_RB_SWAP;
     }
 
     nsIntSize bufferSize(mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight());
 
     return LayerRenderState(mGraphicBuffer.get(),
                             bufferSize,
-                            flags);
+                            flags,
+                            nullptr);
   }
 
   return LayerRenderState();
 }
 
 GLuint
 GrallocDeprecatedTextureHostOGL::GetGLTexture()
 {
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -27,16 +27,19 @@
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_WARNING
 #include "nsISupportsImpl.h"            // for TextureImage::Release, etc
 #include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "OGLShaderProgram.h"           // for ShaderProgramType, etc
 #ifdef MOZ_WIDGET_GONK
 #include <ui/GraphicBuffer.h>
+#if ANDROID_VERSION >= 18
+#include <ui/Fence.h>
+#endif
 #endif
 
 class gfxImageSurface;
 class gfxReusableSurfaceWrapper;
 class nsIntRegion;
 struct nsIntPoint;
 struct nsIntRect;
 struct nsIntSize;
@@ -113,16 +116,39 @@ public:
   virtual GLenum GetWrapMode() const = 0;
 
   virtual gfx::Matrix4x4 GetTextureTransform() { return gfx::Matrix4x4(); }
 
   virtual TextureImageDeprecatedTextureHostOGL* AsTextureImageDeprecatedTextureHost() { return nullptr; }
 };
 
 /**
+ * TextureHostOGL provides the necessary API for platform specific composition.
+ */
+class TextureHostOGL
+{
+public:
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+
+  /**
+   * Store a fence that will signal when the current buffer is no longer being read.
+   * Similar to android's GLConsumer::setReleaseFence()
+   */
+  virtual bool SetReleaseFence(const android::sp<android::Fence>& aReleaseFence);
+
+  /**
+   * Return a releaseFence's Fence and clear a reference to the Fence.
+   */
+  virtual android::sp<android::Fence> GetAndResetReleaseFence();
+protected:
+  android::sp<android::Fence> mReleaseFence;
+#endif
+};
+
+/**
  * A TextureSource backed by a TextureImage.
  *
  * Depending on the underlying TextureImage, may support texture tiling, so
  * make sure to check AsTileIterator() and use the texture accordingly.
  *
  * This TextureSource can be used without a TextureHost and manage it's own
  * GL texture(s).
  */
--- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp
+++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp
@@ -326,17 +326,17 @@ TEST(AsyncPanZoomController, Pinch) {
 
   FrameMetrics fm;
   fm.mViewport = CSSRect(0, 0, 980, 480);
   fm.mCompositionBounds = ScreenIntRect(200, 200, 100, 200);
   fm.mScrollableRect = CSSRect(0, 0, 980, 1000);
   fm.mScrollOffset = CSSPoint(300, 300);
   fm.mZoom = CSSToScreenScale(2.0);
   apzc->SetFrameMetrics(fm);
-  apzc->UpdateZoomConstraints(ZoomConstraints(true, CSSToScreenScale(0.25), CSSToScreenScale(4.0)));
+  apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToScreenScale(0.25), CSSToScreenScale(4.0)));
   // the visible area of the document in CSS pixels is x=300 y=300 w=50 h=100
 
   EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
   EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
 
   ApzcPinch(apzc, 250, 300, 1.25);
 
   // the visible area of the document in CSS pixels is now x=305 y=310 w=40 h=80
@@ -403,17 +403,17 @@ TEST(AsyncPanZoomController, Overzoom) {
 
   FrameMetrics fm;
   fm.mViewport = CSSRect(0, 0, 100, 100);
   fm.mCompositionBounds = ScreenIntRect(0, 0, 100, 100);
   fm.mScrollableRect = CSSRect(0, 0, 125, 150);
   fm.mScrollOffset = CSSPoint(10, 0);
   fm.mZoom = CSSToScreenScale(1.0);
   apzc->SetFrameMetrics(fm);
-  apzc->UpdateZoomConstraints(ZoomConstraints(true, CSSToScreenScale(0.25), CSSToScreenScale(4.0)));
+  apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToScreenScale(0.25), CSSToScreenScale(4.0)));
   // the visible area of the document in CSS pixels is x=10 y=0 w=100 h=100
 
   EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
   EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
 
   ApzcPinch(apzc, 50, 50, 0.5);
 
   fm = apzc->GetFrameMetrics();
@@ -668,17 +668,17 @@ TEST(AsyncPanZoomController, OverScrollP
 TEST(AsyncPanZoomController, ShortPress) {
   nsRefPtr<MockContentControllerDelayed> mcc = new NiceMock<MockContentControllerDelayed>();
   nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
   nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
     0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
 
   apzc->SetFrameMetrics(TestFrameMetrics());
   apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
-  apzc->UpdateZoomConstraints(ZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
+  apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
 
   int time = 0;
   nsEventStatus status = ApzcTap(apzc, 10, 10, time, 100, mcc.get());
   EXPECT_EQ(nsEventStatus_eIgnore, status);
 
   // This verifies that the single tap notification is sent after the
   // touchdown is fully processed. The ordering here is important.
   mcc->CheckHasDelayedTask();
@@ -692,17 +692,17 @@ TEST(AsyncPanZoomController, ShortPress)
 TEST(AsyncPanZoomController, MediumPress) {
   nsRefPtr<MockContentControllerDelayed> mcc = new NiceMock<MockContentControllerDelayed>();
   nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
   nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
     0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
 
   apzc->SetFrameMetrics(TestFrameMetrics());
   apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
-  apzc->UpdateZoomConstraints(ZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
+  apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
 
   int time = 0;
   nsEventStatus status = ApzcTap(apzc, 10, 10, time, 400, mcc.get());
   EXPECT_EQ(nsEventStatus_eIgnore, status);
 
   // This verifies that the single tap notification is sent after the
   // touchdown is fully processed. The ordering here is important.
   mcc->CheckHasDelayedTask();
@@ -717,17 +717,17 @@ void
 DoLongPressTest(bool aShouldUseTouchAction, uint32_t aBehavior) {
   nsRefPtr<MockContentControllerDelayed> mcc = new MockContentControllerDelayed();
   nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
   nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
     0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
 
   apzc->SetFrameMetrics(TestFrameMetrics());
   apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
-  apzc->UpdateZoomConstraints(ZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
+  apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
 
   nsTArray<uint32_t> values;
   values.AppendElement(aBehavior);
   apzc->SetTouchActionEnabled(aShouldUseTouchAction);
   apzc->SetAllowedTouchBehavior(values);
 
   int time = 0;
 
@@ -780,17 +780,17 @@ TEST(AsyncPanZoomController, LongPressPr
 
   nsRefPtr<MockContentControllerDelayed> mcc = new MockContentControllerDelayed();
   nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
   nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
     0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
 
   apzc->SetFrameMetrics(TestFrameMetrics());
   apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
-  apzc->UpdateZoomConstraints(ZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
+  apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
 
   EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(0);
   EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
 
   int touchX = 10,
       touchStartY = 10,
       touchEndY = 50;
 
--- a/gfx/thebes/gfxImageSurface.cpp
+++ b/gfx/thebes/gfxImageSurface.cpp
@@ -10,16 +10,17 @@
 #endif
 #include "gfxImageSurface.h"
 
 #include "cairo.h"
 #include "mozilla/gfx/2D.h"
 #include "gfx2DGlue.h"
 #include <algorithm>
 
+using namespace mozilla;
 using namespace mozilla::gfx;
 
 gfxImageSurface::gfxImageSurface()
   : mSize(0, 0),
     mOwnsData(false),
     mFormat(gfxImageFormat::Unknown),
     mStride(0)
 {
@@ -312,16 +313,28 @@ gfxImageSurface::CopyTo(SourceSurface *a
         return false;
     }
 
     CopyForStride(data->GetData(), mData, size, data->Stride(), mStride);
 
     return true;
 }
 
+TemporaryRef<DataSourceSurface>
+gfxImageSurface::CopyToB8G8R8A8DataSourceSurface()
+{
+  RefPtr<DataSourceSurface> dataSurface =
+    Factory::CreateDataSourceSurface(IntSize(GetSize().width, GetSize().height),
+                                     SurfaceFormat::B8G8R8A8);
+  if (dataSurface) {
+    CopyTo(dataSurface);
+  }
+  return dataSurface.forget();
+}
+
 already_AddRefed<gfxSubimageSurface>
 gfxImageSurface::GetSubimage(const gfxRect& aRect)
 {
     gfxRect r(aRect);
     r.Round();
     MOZ_ASSERT(gfxRect(0, 0, mSize.width, mSize.height).Contains(r));
 
     gfxImageFormat format = Format();
--- a/gfx/thebes/gfxImageSurface.h
+++ b/gfx/thebes/gfxImageSurface.h
@@ -2,26 +2,28 @@
  * 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 GFX_IMAGESURFACE_H
 #define GFX_IMAGESURFACE_H
 
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/RefPtr.h"
 #include "gfxASurface.h"
 #include "nsAutoPtr.h"
 #include "nsSize.h"
 
 // ARGB -- raw buffer.. wont be changed.. good for storing data.
 
 class gfxSubimageSurface;
 
 namespace mozilla {
 namespace gfx {
+class DataSourceSurface;
 class SourceSurface;
 }
 }
 
 /**
  * A raw image buffer. The format can be set in the constructor. Its main
  * purpose is for storing read-only images and using it as a source surface,
  * but it can also be drawn to.
@@ -103,16 +105,21 @@ public:
     bool CopyFrom (mozilla::gfx::SourceSurface *aSurface);
 
     /**
      * Fast copy to a source surface; returns TRUE if successful, FALSE otherwise
      * Assumes that the format of this surface is compatible with aSurface
      */
     bool CopyTo (mozilla::gfx::SourceSurface *aSurface);
 
+    /**
+     * Copy to a Moz2D DataSourceSurface.
+     */
+    mozilla::TemporaryRef<mozilla::gfx::DataSourceSurface> CopyToB8G8R8A8DataSourceSurface();
+
     /* return new Subimage with pointing to original image starting from aRect.pos
      * and size of aRect.size. New subimage keeping current image reference
      */
     already_AddRefed<gfxSubimageSurface> GetSubimage(const gfxRect& aRect);
 
     virtual already_AddRefed<gfxImageSurface> GetAsImageSurface();
 
     /** See gfxASurface.h. */
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -1073,16 +1073,20 @@ MacFontInfo::LoadFontFamilyData(const ns
 
         CTFontDescriptorRef faceDesc =
             (CTFontDescriptorRef)CFArrayGetValueAtIndex(matchingFonts, f);
         if (!faceDesc) {
             continue;
         }
         CTFontRef fontRef = CTFontCreateWithFontDescriptor(faceDesc,
                                                            0.0, nullptr);
+        if (!fontRef) {
+            NS_WARNING("failed to create a CTFontRef");
+            continue;
+        }
 
         if (mLoadCmaps) {
             // face name
             CFStringRef faceName = (CFStringRef)
                 CTFontDescriptorCopyAttribute(faceDesc, kCTFontNameAttribute);
 
             nsAutoTArray<UniChar, 1024> buffer;
             CFIndex len = CFStringGetLength(faceName);
--- a/gfx/thebes/gfxXlibSurface.cpp
+++ b/gfx/thebes/gfxXlibSurface.cpp
@@ -84,17 +84,17 @@ gfxXlibSurface::gfxXlibSurface(cairo_sur
 
     Init(csurf, true);
 }
 
 gfxXlibSurface::~gfxXlibSurface()
 {
 #if defined(GL_PROVIDER_GLX)
     if (mGLXPixmap) {
-        gl::sGLXLibrary.DestroyPixmap(mGLXPixmap);
+        gl::sGLXLibrary.DestroyPixmap(mDisplay, mGLXPixmap);
     }
 #endif
     // gfxASurface's destructor calls RecordMemoryFreed().
     if (mPixmapTaken) {
         XFreePixmap (mDisplay, mDrawable);
     }
 }
 
@@ -273,17 +273,17 @@ gfxXlibSurface::CreateSimilarSurface(gfx
     return gfxASurface::CreateSimilarSurface(aContent, aSize);
 }
 
 void
 gfxXlibSurface::Finish()
 {
 #if defined(GL_PROVIDER_GLX)
     if (mGLXPixmap) {
-        gl::sGLXLibrary.DestroyPixmap(mGLXPixmap);
+        gl::sGLXLibrary.DestroyPixmap(mDisplay, mGLXPixmap);
         mGLXPixmap = None;
     }
 #endif
     gfxASurface::Finish();
 }
 
 void
 gfxXlibSurface::DoSizeQuery()
--- a/image/src/imgTools.cpp
+++ b/image/src/imgTools.cpp
@@ -1,28 +1,27 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "imgTools.h"
 
+#include "mozilla/gfx/2D.h"
+#include "mozilla/RefPtr.h"
 #include "nsCOMPtr.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsError.h"
 #include "imgLoader.h"
 #include "imgICache.h"
 #include "imgIContainer.h"
 #include "imgIEncoder.h"
-#include "gfxContext.h"
-#include "nsComponentManagerUtils.h"
 #include "nsStreamUtils.h"
-#include "nsNetUtil.h"
 #include "nsContentUtils.h"
 #include "ImageFactory.h"
 #include "Image.h"
 #include "ScriptedNotificationObserver.h"
 #include "imgIScriptedNotificationObserver.h"
 #include "gfxPlatform.h"
 
 using namespace mozilla;
@@ -93,30 +92,87 @@ NS_IMETHODIMP imgTools::DecodeImage(nsII
   rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // All done.
   NS_ADDREF(*aContainer = image.get());
   return NS_OK;
 }
 
+static TemporaryRef<SourceSurface>
+GetFirstImageFrame(imgIContainer *aContainer)
+{
+  nsRefPtr<gfxASurface> frame =
+    aContainer->GetFrame(imgIContainer::FRAME_FIRST,
+                         imgIContainer::FLAG_SYNC_DECODE);
+  NS_ENSURE_TRUE(frame, nullptr);
+
+  nsRefPtr<gfxImageSurface> imageSurface = frame->CopyToARGB32ImageSurface();
+  NS_ENSURE_TRUE(imageSurface, nullptr);
+
+  return imageSurface->CopyToB8G8R8A8DataSourceSurface();
+}
+
+/**
+ * This takes a DataSourceSurface rather than a SourceSurface because some
+ * of the callers have a DataSourceSurface and we don't want to call
+ * GetDataSurface on such surfaces since that may incure a conversion to
+ * SurfaceType::DATA which we don't need.
+ */
+static nsresult EncodeImageData(DataSourceSurface* aDataSurface,
+                                const nsACString& aMimeType,
+                                const nsAString& aOutputOptions,
+                                nsIInputStream **aStream)
+{
+  MOZ_ASSERT(aDataSurface->GetFormat() ==  SurfaceFormat::B8G8R8A8,
+             "We're assuming B8G8R8A8");
+
+  // Get an image encoder for the media type
+  nsAutoCString encoderCID(
+    NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type=") + aMimeType);
+
+  nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(encoderCID.get());
+  if (!encoder)
+    return NS_IMAGELIB_ERROR_NO_ENCODER;
+
+  DataSourceSurface::MappedSurface map;
+  aDataSurface->Map(DataSourceSurface::MapType::READ, &map);
+  if (!map.mData)
+    return NS_ERROR_FAILURE;
+
+  IntSize size = aDataSurface->GetSize();
+  uint32_t dataLength = map.mStride * size.height;
+
+  // Encode the bitmap
+  nsresult rv = encoder->InitFromData(map.mData,
+                                      dataLength,
+                                      size.width,
+                                      size.height,
+                                      map.mStride,
+                                      imgIEncoder::INPUT_FORMAT_HOSTARGB,
+                                      aOutputOptions);
+
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return CallQueryInterface(encoder, aStream);
+}
 
 NS_IMETHODIMP imgTools::EncodeImage(imgIContainer *aContainer,
                                     const nsACString& aMimeType,
                                     const nsAString& aOutputOptions,
                                     nsIInputStream **aStream)
 {
-  nsresult rv;
+  // Use frame 0 from the image container.
+  RefPtr<SourceSurface> frame = GetFirstImageFrame(aContainer);
+  NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
-  // Use frame 0 from the image container.
-  nsRefPtr<gfxImageSurface> frame;
-  rv = GetFirstImageFrame(aContainer, getter_AddRefs(frame));
-  NS_ENSURE_SUCCESS(rv, rv);
+  RefPtr<DataSourceSurface> dataSurface = frame->GetDataSurface();
+  NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
 
-  return EncodeImageData(frame, aMimeType, aOutputOptions, aStream);
+  return EncodeImageData(dataSurface, aMimeType, aOutputOptions, aStream);
 }
 
 NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer,
                                           const nsACString& aMimeType,
                                           int32_t aScaledWidth,
                                           int32_t aScaledHeight,
                                           const nsAString& aOutputOptions,
                                           nsIInputStream **aStream)
@@ -125,62 +181,51 @@ NS_IMETHODIMP imgTools::EncodeScaledImag
 
   // If no scaled size is specified, we'll just encode the image at its
   // original size (no scaling).
   if (aScaledWidth == 0 && aScaledHeight == 0) {
     return EncodeImage(aContainer, aMimeType, aOutputOptions, aStream);
   }
 
   // Use frame 0 from the image container.
-  nsRefPtr<gfxImageSurface> frame;
-  nsresult rv = GetFirstImageFrame(aContainer, getter_AddRefs(frame));
-  NS_ENSURE_SUCCESS(rv, rv);
+  RefPtr<SourceSurface> frame = GetFirstImageFrame(aContainer);
+  NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
-  int32_t frameWidth = frame->Width(), frameHeight = frame->Height();
+  int32_t frameWidth = frame->GetSize().width;
+  int32_t frameHeight = frame->GetSize().height;
 
   // If the given width or height is zero we'll replace it with the image's
   // original dimensions.
   if (aScaledWidth == 0) {
     aScaledWidth = frameWidth;
   } else if (aScaledHeight == 0) {
     aScaledHeight = frameHeight;
   }
 
-  // Create a temporary image surface
-  nsRefPtr<gfxImageSurface> dest = new gfxImageSurface(gfxIntSize(aScaledWidth, aScaledHeight),
-                                                       gfxImageFormat::ARGB32);
-  if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
-    RefPtr<DrawTarget> dt =
-      gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(dest, IntSize(aScaledWidth, aScaledHeight));
-    RefPtr<SourceSurface> source = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, frame);
-
-    dt->DrawSurface(source,
-                    Rect(0, 0, aScaledWidth, aScaledHeight),
-                    Rect(0, 0, frameWidth, frameHeight),
-                    DrawSurfaceOptions(),
-                    DrawOptions(1.0f, CompositionOp::OP_SOURCE));
-  } else {
-    gfxContext ctx(dest);
+  RefPtr<DataSourceSurface> dataSurface =
+    Factory::CreateDataSourceSurface(IntSize(aScaledWidth, aScaledHeight),
+                                     SurfaceFormat::B8G8R8A8);
+  DataSourceSurface::MappedSurface map;
+  dataSurface->Map(DataSourceSurface::MapType::WRITE, &map);
+  if (!map.mData)
+    return NS_ERROR_FAILURE;
 
-    // Set scaling
-    gfxFloat sw = (double) aScaledWidth / frameWidth;
-    gfxFloat sh = (double) aScaledHeight / frameHeight;
-    ctx.Scale(sw, sh);
-
-    // Paint a scaled image
-    ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
+  RefPtr<DrawTarget> dt =
+    Factory::CreateDrawTargetForData(BackendType::CAIRO,
+                                     map.mData,
+                                     dataSurface->GetSize(),
+                                     map.mStride,
+                                     SurfaceFormat::B8G8R8A8);
+  dt->DrawSurface(frame,
+                  Rect(0, 0, aScaledWidth, aScaledHeight),
+                  Rect(0, 0, frameWidth, frameHeight),
+                  DrawSurfaceOptions(),
+                  DrawOptions(1.0f, CompositionOp::OP_SOURCE));
 
-    nsRefPtr<gfxPattern> pat = new gfxPattern(frame);
-    pat->SetExtend(gfxPattern::EXTEND_PAD);
-    ctx.SetPattern(pat);
-    ctx.Paint();
-  }
-
-
-  return EncodeImageData(dest, aMimeType, aOutputOptions, aStream);
+  return EncodeImageData(dataSurface, aMimeType, aOutputOptions, aStream);
 }
 
 NS_IMETHODIMP imgTools::EncodeCroppedImage(imgIContainer *aContainer,
                                            const nsACString& aMimeType,
                                            int32_t aOffsetX,
                                            int32_t aOffsetY,
                                            int32_t aWidth,
                                            int32_t aHeight,
@@ -195,103 +240,53 @@ NS_IMETHODIMP imgTools::EncodeCroppedIma
 
   // If no size is specified then we'll preserve the image's original dimensions
   // and don't need to crop.
   if (aWidth == 0 && aHeight == 0) {
     return EncodeImage(aContainer, aMimeType, aOutputOptions, aStream);
   }
 
   // Use frame 0 from the image container.
-  nsRefPtr<gfxImageSurface> frame;
-  nsresult rv = GetFirstImageFrame(aContainer, getter_AddRefs(frame));
-  NS_ENSURE_SUCCESS(rv, rv);
+  RefPtr<SourceSurface> frame = GetFirstImageFrame(aContainer);
+  NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
-  int32_t frameWidth = frame->Width(), frameHeight = frame->Height();
+  int32_t frameWidth = frame->GetSize().width;
+  int32_t frameHeight = frame->GetSize().height;
 
   // If the given width or height is zero we'll replace it with the image's
   // original dimensions.
   if (aWidth == 0) {
     aWidth = frameWidth;
   } else if (aHeight == 0) {
     aHeight = frameHeight;
   }
 
   // Check that the given crop rectangle is within image bounds.
   NS_ENSURE_ARG(frameWidth >= aOffsetX + aWidth &&
                 frameHeight >= aOffsetY + aHeight);
 
-  // Create a temporary image surface
-  nsRefPtr<gfxImageSurface> dest = new gfxImageSurface(gfxIntSize(aWidth, aHeight),
-                                                       gfxImageFormat::ARGB32);
-  gfxContext ctx(dest);
-
-  // Set translate
-  ctx.Translate(gfxPoint(-aOffsetX, -aOffsetY));
-
-  // Paint a scaled image
-  ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
-  ctx.SetSource(frame);
-  ctx.Paint();
-
-  return EncodeImageData(dest, aMimeType, aOutputOptions, aStream);
-}
-
-NS_IMETHODIMP imgTools::EncodeImageData(gfxImageSurface *aSurface,
-                                        const nsACString& aMimeType,
-                                        const nsAString& aOutputOptions,
-                                        nsIInputStream **aStream)
-{
-  uint8_t *bitmapData;
-  uint32_t bitmapDataLength, strideSize;
-
-  // Get an image encoder for the media type
-  nsAutoCString encoderCID(
-    NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type=") + aMimeType);
-
-  nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(encoderCID.get());
-  if (!encoder)
-    return NS_IMAGELIB_ERROR_NO_ENCODER;
-
-  bitmapData = aSurface->Data();
-  if (!bitmapData)
+  RefPtr<DataSourceSurface> dataSurface =
+    Factory::CreateDataSourceSurface(IntSize(aWidth, aHeight),
+                                     SurfaceFormat::B8G8R8A8);
+  DataSourceSurface::MappedSurface map;
+  dataSurface->Map(DataSourceSurface::MapType::WRITE, &map);
+  if (!map.mData)
     return NS_ERROR_FAILURE;
 
-  strideSize = aSurface->Stride();
-
-  int32_t width = aSurface->Width(), height = aSurface->Height();
-  bitmapDataLength = height * strideSize;
-
-  // Encode the bitmap
-  nsresult rv = encoder->InitFromData(bitmapData,
-                                      bitmapDataLength,
-                                      width,
-                                      height,
-                                      strideSize,
-                                      imgIEncoder::INPUT_FORMAT_HOSTARGB,
-                                      aOutputOptions);
-
-  NS_ENSURE_SUCCESS(rv, rv);
+  RefPtr<DrawTarget> dt =
+    Factory::CreateDrawTargetForData(BackendType::CAIRO,
+                                     map.mData,
+                                     dataSurface->GetSize(),
+                                     map.mStride,
+                                     SurfaceFormat::B8G8R8A8);
+  dt->CopySurface(frame,
+                  IntRect(aOffsetX, aOffsetY, aWidth, aHeight),
+                  IntPoint(0, 0));
 
-  return CallQueryInterface(encoder, aStream);
-}
-
-NS_IMETHODIMP imgTools::GetFirstImageFrame(imgIContainer *aContainer,