merge b2g-inbound to mozilla-central
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 25 Feb 2014 14:30:13 +0100
changeset 170748 1507f021ac93c1d27cfd00e389fba1c9421b3201
parent 170686 8c1eb349d342d617e50e44d50e75b4f041613fe8 (current diff)
parent 170747 b743b07c10f88a41bb5d1543503b0dfcc87e0c62 (diff)
child 170749 465f58380970aca163a54566e9d46cc1c7046bec
child 170812 66aa08862214a637715d9a095d50aa1278061cc2
child 170885 5d020fa8466104695256e47f43ecd373812c3832
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone30.0a1
merge b2g-inbound to mozilla-central
content/base/src/nsDocument.cpp
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
gfx/layers/client/ClientLayerManager.cpp
--- 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/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/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -11318,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();
@@ -11363,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) {
@@ -11409,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/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/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/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/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/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/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/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/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/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/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/widget/gonk/HwcComposer2D.cpp
+++ b/widget/gonk/HwcComposer2D.cpp
@@ -14,21 +14,23 @@
  * limitations under the License.
  */
 
 #include <android/log.h>
 #include <string.h>
 
 #include "libdisplay/GonkDisplay.h"
 #include "Framebuffer.h"
+#include "GLContext.h"                  // for GLContext
 #include "HwcUtils.h"
 #include "HwcComposer2D.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/layers/PLayerTransaction.h"
 #include "mozilla/layers/ShadowLayerUtilsGralloc.h"
+#include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
 #include "mozilla/StaticPtr.h"
 #include "cutils/properties.h"
 #include "gfx2DGlue.h"
 
 #if ANDROID_VERSION >= 17
 #include "libdisplay/FramebufferSurface.h"
 #ifndef HWC_BLIT
 #define HWC_BLIT (HWC_FRAMEBUFFER_TARGET + 1)
@@ -62,17 +64,20 @@ namespace mozilla {
 static StaticRefPtr<HwcComposer2D> sInstance;
 
 HwcComposer2D::HwcComposer2D()
     : mMaxLayerCount(0)
     , mList(nullptr)
     , mHwc(nullptr)
     , mColorFill(false)
     , mRBSwapSupport(false)
-    , mPrevRetireFence(-1)
+#if ANDROID_VERSION >= 18
+    , mPrevRetireFence(Fence::NO_FENCE)
+    , mPrevDisplayFence(Fence::NO_FENCE)
+#endif
     , mPrepared(false)
 {
 }
 
 HwcComposer2D::~HwcComposer2D() {
     free(mList);
 }
 
@@ -644,46 +649,39 @@ HwcComposer2D::Prepare(buffer_handle_t f
 bool
 HwcComposer2D::Commit()
 {
     hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
     displays[HWC_DISPLAY_PRIMARY] = mList;
 
     int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
 
-    // To avoid tearing, workaround for missing releaseFenceFd
-    // waits in Gecko layers, see Bug 925444.
-    if (!mPrevReleaseFds.IsEmpty()) {
-        // Wait for previous retire Fence to signal.
-        // Denotes contents on display have been replaced.
-        // For buffer-sync, framework should not over-write
-        // prev buffers until we close prev releaseFenceFds
-        sp<Fence> fence = new Fence(mPrevRetireFence);
-        if (fence->wait(1000) == -ETIME) {
-            LOGE("Wait timed-out for retireFenceFd %d", mPrevRetireFence);
-        }
-        for (int i = 0; i < mPrevReleaseFds.Length(); i++) {
-            close(mPrevReleaseFds[i]);
-        }
-        close(mPrevRetireFence);
-        mPrevReleaseFds.Clear();
-    }
+    mPrevDisplayFence = mPrevRetireFence;
+    mPrevRetireFence = Fence::NO_FENCE;
 
     for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) {
         if (mList->hwLayers[j].releaseFenceFd >= 0) {
-            mPrevReleaseFds.AppendElement(mList->hwLayers[j].releaseFenceFd);
-        }
-    }
+            int fd = mList->hwLayers[j].releaseFenceFd;
+            mList->hwLayers[j].releaseFenceFd = -1;
+            sp<Fence> fence = new Fence(fd);
+
+            LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState();
+            if (!state.mTexture) {
+                continue;
+            }
+            TextureHostOGL* texture = state.mTexture->AsHostOGL();
+            if (!texture) {
+                continue;
+            }
+            texture->SetReleaseFence(fence);
+       }
+   }
 
     if (mList->retireFenceFd >= 0) {
-        if (!mPrevReleaseFds.IsEmpty()) {
-            mPrevRetireFence = mList->retireFenceFd;
-        } else { // GPU Composition
-            close(mList->retireFenceFd);
-        }
+        mPrevRetireFence = new Fence(mList->retireFenceFd);
     }
 
     mPrepared = false;
     return !err;
 }
 
 void
 HwcComposer2D::Reset()
--- a/widget/gonk/HwcComposer2D.h
+++ b/widget/gonk/HwcComposer2D.h
@@ -18,16 +18,19 @@
 #define mozilla_HwcComposer2D
 
 #include "Composer2D.h"
 #include "Layers.h"
 #include <vector>
 #include <list>
 
 #include <hardware/hwcomposer.h>
+#if ANDROID_VERSION >= 18
+#include <ui/Fence.h>
+#endif
 
 namespace mozilla {
 
 namespace layers {
 class ContainerLayer;
 class Layer;
 }
 
@@ -78,17 +81,19 @@ private:
     hwc_surface_t           mSur;
     nsIntRect               mScreenRect;
     int                     mMaxLayerCount;
     bool                    mColorFill;
     bool                    mRBSwapSupport;
     //Holds all the dynamically allocated RectVectors needed
     //to render the current frame
     std::list<RectVector>   mVisibleRegions;
-    nsTArray<int>           mPrevReleaseFds;
-    int                     mPrevRetireFence;
+#if ANDROID_VERSION >= 18
+    android::sp<android::Fence> mPrevRetireFence;
+    android::sp<android::Fence> mPrevDisplayFence;
+#endif
     nsTArray<layers::LayerComposite*> mHwcLayerMap;
     bool                    mPrepared;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_HwcComposer2D
--- a/widget/gonk/nativewindow/GonkNativeWindowJB.cpp
+++ b/widget/gonk/nativewindow/GonkNativeWindowJB.cpp
@@ -100,54 +100,55 @@ status_t GonkNativeWindow::setDefaultBuf
 }
 
 status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) {
     Mutex::Autolock _l(mMutex);
     return mBufferQueue->setDefaultBufferFormat(defaultFormat);
 }
 
 already_AddRefed<GraphicBufferLocked>
-GonkNativeWindow::getCurrentBuffer()
-{
+GonkNativeWindow::getCurrentBuffer() {
     Mutex::Autolock _l(mMutex);
     GonkBufferQueue::BufferItem item;
 
     // In asynchronous mode the list is guaranteed to be one buffer
     // deep, while in synchronous mode we use the oldest buffer.
     status_t err = acquireBufferLocked(&item);
     if (err != NO_ERROR) {
         return NULL;
     }
 
   nsRefPtr<GraphicBufferLocked> ret =
     new CameraGraphicBuffer(this, item.mBuf, mBufferQueue->getGeneration(), item.mSurfaceDescriptor);
   return ret.forget();
 }
 
 bool
-GonkNativeWindow::returnBuffer(uint32_t aIndex, uint32_t aGeneration) {
-    BI_LOGD("GonkNativeWindow::returnBuffer: slot=%d (generation=%d)", aIndex, aGeneration);
+GonkNativeWindow::returnBuffer(uint32_t index, uint32_t generation, const sp<Fence>& fence) {
+    BI_LOGD("GonkNativeWindow::returnBuffer: slot=%d (generation=%d)", index, generation);
     Mutex::Autolock lock(mMutex);
 
-    if (aGeneration != mBufferQueue->getGeneration()) {
+    if (generation != mBufferQueue->getGeneration()) {
         BI_LOGD("returnBuffer: buffer is from generation %d (current is %d)",
-          aGeneration, mBufferQueue->getGeneration());
+          generation, mBufferQueue->getGeneration());
         return false;
     }
 
-    status_t err = releaseBufferLocked(aIndex);
+    status_t err;
+    err = addReleaseFenceLocked(index, fence);
+
+    err = releaseBufferLocked(index);
     if (err != NO_ERROR) {
         return false;
     }
   return true;
 }
 
 mozilla::layers::SurfaceDescriptor *
-GonkNativeWindow::getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer)
-{
+GonkNativeWindow::getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer) {
     Mutex::Autolock lock(mMutex);
     return mBufferQueue->getSurfaceDescriptorFromBuffer(buffer);
 }
 void GonkNativeWindow::setNewFrameCallback(
         GonkNativeWindowNewFrameCallback* aCallback) {
     BI_LOGD("setNewFrameCallback");
     Mutex::Autolock lock(mMutex);
     mNewFrameCallback = aCallback;
@@ -156,9 +157,27 @@ void GonkNativeWindow::setNewFrameCallba
 void GonkNativeWindow::onFrameAvailable() {
     GonkConsumerBase::onFrameAvailable();
 
     if (mNewFrameCallback) {
       mNewFrameCallback->OnNewFrame();
     }
 }
 
+void CameraGraphicBuffer::Unlock() {
+    if (mLocked) {
+        android::sp<android::Fence> fence;
+        fence = mReleaseFenceHandle.IsValid() ? mReleaseFenceHandle.mFence : Fence::NO_FENCE;
+        // The window might have been destroyed. The buffer is no longer
+        // valid at that point.
+        sp<GonkNativeWindow> window = mNativeWindow.promote();
+        if (window.get() && window->returnBuffer(mIndex, mGeneration, fence)) {
+            mLocked = false;
+        } else {
+            // If the window doesn't exist any more, release the buffer
+            // directly.
+            ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
+            ibc->DeallocSurfaceDescriptorGralloc(mSurfaceDescriptor);
+        }
+    }
+}
+
 } // namespace android
--- a/widget/gonk/nativewindow/GonkNativeWindowJB.h
+++ b/widget/gonk/nativewindow/GonkNativeWindowJB.h
@@ -111,17 +111,17 @@ class GonkNativeWindow: public GonkConsu
     // in dequeueBuffer
     status_t setDefaultBufferFormat(uint32_t defaultFormat);
 
     // Get next frame from the queue, caller owns the returned buffer.
     already_AddRefed<GraphicBufferLocked> getCurrentBuffer();
 
     // Return the buffer to the queue and mark it as FREE. After that
     // the buffer is useable again for the decoder.
-    bool returnBuffer(uint32_t index, uint32_t generation);
+    bool returnBuffer(uint32_t index, uint32_t generation, const sp<Fence>& fence);
 
     SurfaceDescriptor* getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer);
 
     void setNewFrameCallback(GonkNativeWindowNewFrameCallback* aCallback);
 
 protected:
     virtual void onFrameAvailable();
 
@@ -152,32 +152,17 @@ public:
     virtual ~CameraGraphicBuffer()
     {
         DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
     }
 
 protected:
     // Unlock either returns the buffer to the native window or
     // destroys the buffer if the window is already released.
-    virtual void Unlock() MOZ_OVERRIDE
-    {
-        if (mLocked) {
-            // The window might have been destroyed. The buffer is no longer
-            // valid at that point.
-            sp<GonkNativeWindow> window = mNativeWindow.promote();
-            if (window.get() && window->returnBuffer(mIndex, mGeneration)) {
-                mLocked = false;
-            } else {
-                // If the window doesn't exist any more, release the buffer
-                // directly.
-                ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
-                ibc->DeallocSurfaceDescriptorGralloc(mSurfaceDescriptor);
-            } 
-        }
-    }
+    virtual void Unlock() MOZ_OVERRIDE;
 
 protected:
     wp<GonkNativeWindow> mNativeWindow;
     uint32_t mIndex;
     uint32_t mGeneration;
     bool mLocked;
 };