Merge b2g-inbound to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 13 Feb 2015 12:24:27 -0500
changeset 256120 fd12875a8a48eba1591c0a70e17a142953161218
parent 256083 aa339e258ccddadc378f942a8e0d6d3e3bd48c0a (current diff)
parent 256119 5f83e77bfb403c1b4b6776cd3fe55c764c705f2e (diff)
child 256121 992cf3981ca81ea65fb13cfca3f1906b7857b922
child 256131 1cd0ddc21eecca0546c28310be0544bbfc414492
child 256141 9fd93e84a01d943107d150fbd9afe90304bf7be4
child 256228 af230f02ff2aad10368ef98422d8113975eeebd2
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge b2g-inbound to m-c. a=merge CLOSED TREE
b2g/chrome/content/shell.js
b2g/installer/package-manifest.in
configure.in
dom/telephony/test/marionette/test_incoming_connecting_hangup.js
modules/libpref/init/all.js
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-bug 832837 removes nsISecurityWarningDialogs.idl, which requires a clobber according to bug 1114669
+Bug 879861 - Touch CLOBBER because adding a new IDL is a crapshoot these days.
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -335,20 +335,36 @@ pref("image.onload.decode.limit", 24); /
 // we don't really have a better one at the moment.
 // enable touch events interfaces
 pref("dom.w3c_touch_events.enabled", 1);
 pref("dom.w3c_touch_events.safetyX", 0); // escape borders in units of 1/240"
 pref("dom.w3c_touch_events.safetyY", 120); // escape borders in units of 1/240"
 
 #ifdef MOZ_SAFE_BROWSING
 // Safe browsing does nothing unless this pref is set
-pref("browser.safebrowsing.enabled", true);
+pref("browser.safebrowsing.enabled", false);
 
 // Prevent loading of pages identified as malware
-pref("browser.safebrowsing.malware.enabled", true);
+pref("browser.safebrowsing.malware.enabled", false);
+
+pref("browser.safebrowsing.debug", false);
+pref("browser.safebrowsing.updateURL", "https://safebrowsing.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2&key=%GOOGLE_API_KEY%");
+pref("browser.safebrowsing.gethashURL", "https://safebrowsing.google.com/safebrowsing/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
+pref("browser.safebrowsing.reportURL", "https://safebrowsing.google.com/safebrowsing/report?");
+pref("browser.safebrowsing.reportGenericURL", "http://%LOCALE%.phish-generic.mozilla.com/?hl=%LOCALE%");
+pref("browser.safebrowsing.reportErrorURL", "http://%LOCALE%.phish-error.mozilla.com/?hl=%LOCALE%");
+pref("browser.safebrowsing.reportPhishURL", "http://%LOCALE%.phish-report.mozilla.com/?hl=%LOCALE%");
+pref("browser.safebrowsing.reportMalwareURL", "http://%LOCALE%.malware-report.mozilla.com/?hl=%LOCALE%");
+pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-error.mozilla.com/?hl=%LOCALE%");
+pref("browser.safebrowsing.appRepURL", "https://sb-ssl.google.com/safebrowsing/clientreport/download?key=%GOOGLE_API_KEY%");
+
+pref("browser.safebrowsing.id", "Firefox");
+
+// Tables for application reputation.
+pref("urlclassifier.downloadBlockTable", "goog-badbinurl-shavar");
 
 // Non-enhanced mode (local url lists) URL list to check for updates
 pref("browser.safebrowsing.provider.0.updateURL", "https://safebrowsing.google.com/safebrowsing/downloads?client={moz:client}&appver={moz:version}&pver=2.2&key=%GOOGLE_API_KEY%");
 
 pref("browser.safebrowsing.dataProvider", 0);
 
 // Does the provider name need to be localizable?
 pref("browser.safebrowsing.provider.0.name", "Google");
@@ -359,20 +375,16 @@ pref("browser.safebrowsing.provider.0.ge
 pref("browser.safebrowsing.provider.0.reportGenericURL", "http://{moz:locale}.phish-generic.mozilla.com/?hl={moz:locale}");
 pref("browser.safebrowsing.provider.0.reportErrorURL", "http://{moz:locale}.phish-error.mozilla.com/?hl={moz:locale}");
 pref("browser.safebrowsing.provider.0.reportPhishURL", "http://{moz:locale}.phish-report.mozilla.com/?hl={moz:locale}");
 pref("browser.safebrowsing.provider.0.reportMalwareURL", "http://{moz:locale}.malware-report.mozilla.com/?hl={moz:locale}");
 pref("browser.safebrowsing.provider.0.reportMalwareErrorURL", "http://{moz:locale}.malware-error.mozilla.com/?hl={moz:locale}");
 
 // FAQ URLs
 
-// Name of the about: page contributed by safebrowsing to handle display of error
-// pages on phishing/malware hits.  (bug 399233)
-pref("urlclassifier.alternate_error_page", "blocked");
-
 // The number of random entries to send with a gethash request.
 pref("urlclassifier.gethashnoise", 4);
 
 // Gethash timeout for Safebrowsing.
 pref("urlclassifier.gethash.timeout_ms", 5000);
 
 // If an urlclassifier table has not been updated in this number of seconds,
 // a gethash request will be forced to check that the result is still in
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -65,16 +65,21 @@ XPCOMUtils.defineLazyGetter(this, "libcu
 #endif
 
 #ifdef MOZ_CAPTIVEDETECT
 XPCOMUtils.defineLazyServiceGetter(Services, 'captivePortalDetector',
                                   '@mozilla.org/toolkit/captive-detector;1',
                                   'nsICaptivePortalDetector');
 #endif
 
+#ifdef MOZ_SAFE_BROWSING
+XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
+              "resource://gre/modules/SafeBrowsing.jsm");
+#endif
+
 function getContentWindow() {
   return shell.contentBrowser.contentWindow;
 }
 
 function debug(str) {
   dump(' -*- Shell.js: ' + str + '\n');
 }
 
@@ -356,16 +361,21 @@ var shell = {
     this.contentBrowser.src = homeURL;
     this.isHomeLoaded = false;
 
     ppmm.addMessageListener("content-handler", this);
     ppmm.addMessageListener("dial-handler", this);
     ppmm.addMessageListener("sms-handler", this);
     ppmm.addMessageListener("mail-handler", this);
     ppmm.addMessageListener("file-picker", this);
+#ifdef MOZ_SAFE_BROWSING
+    setTimeout(function() {
+      SafeBrowsing.init();
+    }, 5000);
+#endif
   },
 
   stop: function shell_stop() {
     window.removeEventListener('unload', this);
     window.removeEventListener('keydown', this, true);
     window.removeEventListener('keyup', this, true);
     window.removeEventListener('MozApplicationManifest', this);
     window.removeEventListener('mozfullscreenchange', this);
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="f47964c89a9c34d9a2e77afa3608d9ec604c3d20">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="2a2b008f9ae957fe19ad540d233d86b5c0b6829e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="71defd569502274e877b56094e3a44d776033120"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
   <!-- Stock Android things -->
   <project groups="linux" 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="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" 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="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="83760d213fb3bec7b4117d266fcfbf6fe2ba14ab"/>
   <project name="device/common" path="device/common" revision="6a2995683de147791e516aae2ccb31fdfbe2ad30"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,23 +14,23 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="6295c4eb38de793159368aa7f745ef3faf7208aa">
     <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="2a2b008f9ae957fe19ad540d233d86b5c0b6829e"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="71defd569502274e877b56094e3a44d776033120"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="2c31ac3a31a340b40ecd9c291df9b9613d3afa72"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ac778ae59be38aea284a04c89640b1a11c26a5de">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="2a2b008f9ae957fe19ad540d233d86b5c0b6829e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="71defd569502274e877b56094e3a44d776033120"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" 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="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" 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="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="f47964c89a9c34d9a2e77afa3608d9ec604c3d20">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="2a2b008f9ae957fe19ad540d233d86b5c0b6829e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="71defd569502274e877b56094e3a44d776033120"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
   <!-- Stock Android things -->
   <project groups="linux" 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="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <project groups="linux" 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="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="1950e4760fa14688b83cdbb5acaa1af9f82ef434"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="ac6eb97a37035c09fb5ede0852f0881e9aadf9ad"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="737f591c5f95477148d26602c7be56cbea0cdeb9"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="51da9b1981be481b92a59a826d4d78dc73d0989a"/>
   <project name="device/common" path="device/common" revision="798a3664597e6041985feab9aef42e98d458bc3d"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,23 +14,23 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="6295c4eb38de793159368aa7f745ef3faf7208aa">
     <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="2a2b008f9ae957fe19ad540d233d86b5c0b6829e"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="71defd569502274e877b56094e3a44d776033120"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="2c31ac3a31a340b40ecd9c291df9b9613d3afa72"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="f47964c89a9c34d9a2e77afa3608d9ec604c3d20">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="2a2b008f9ae957fe19ad540d233d86b5c0b6829e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="71defd569502274e877b56094e3a44d776033120"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
   <!-- Stock Android things -->
   <project groups="linux" 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="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" 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="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="a32003194f707f66a2d8cdb913ed1869f1926c5d"/>
   <project name="device/common" path="device/common" revision="96d4d2006c4fcb2f19a3fa47ab10cb409faa017b"/>
@@ -96,33 +96,33 @@
   <project name="platform/external/tinyxml2" path="external/tinyxml2" revision="ead7a211773b9366466c6512cf945bc9dd1490a5"/>
   <project name="platform/external/tremolo" path="external/tremolo" revision="78772d5dde5a06eefae281b0dde224fcac46c4ff"/>
   <project name="platform/external/webp" path="external/webp" revision="513e97bd307573e2adc776eb5368bd129aceaa4a"/>
   <project name="platform/external/webrtc" path="external/webrtc" revision="446452f84e9cc4c75d8e80f6f05e24793397a19d"/>
   <project name="platform/external/yaffs2" path="external/yaffs2" revision="a2cff2275e1b501ff478b03757d6e4f05fddc2db"/>
   <project name="platform/external/zlib" path="external/zlib" revision="6eb3570ff8fa71bd83bb375b4bf09804c6089fed"/>
   <project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="dbbe673145107e99883f62bafd70c5f43f11065c"/>
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="f0c3b4edf597c40aae4ea311575f39c8bcf203df"/>
-  <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="adb52b35ecb523bd332854945c09828ee887e575"/>
   <project name="platform/libcore" path="libcore" revision="baf7d8068dd501cfa338d3a8b1b87216d6ce0571"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="50c4430e32849530ced32680fd6ee98963b3f7ac"/>
   <project name="platform/ndk" path="ndk" revision="e58ef003be4306bb53a8c11331146f39e4eab31f"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="0e7c060db684b409616fe67ea433ef19f5634c60"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="c792f0bd9fff7aea2887c60bbb3a9bbdb534ffa3"/>
   <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="69d524e80cdf3981006627c65ac85f3a871238a3"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
   <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
   <project name="platform/system/extras" path="system/extras" revision="576f57b6510de59c08568b53c0fb60588be8689e"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="8fcd25d64f0f67d1a6f7037a4c83ce6d95466770"/>
   <project name="platform/system/netd" path="system/netd" revision="a6531f7befb49b1c81bc0de7e51c5482b308e1c5"/>
   <project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
   <project name="platform/system/vold" path="system/vold" revision="42fa2a0f14f965970a4b629a176bbd2666edf017"/>
   <project name="platform/external/curl" path="external/curl" revision="e68addd988448959ea8157c5de637346b4180c33"/>
   <project name="platform/external/icu4c" path="external/icu4c" revision="d3ec7428eb276db43b7ed0544e09344a6014806c"/>
+  <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="76c4bf4bc430a1b8317f2f21ef735867733e50cc"/>
   <project name="platform/system/media" path="system/media" revision="c1332c21c608f4932a6d7e83450411cde53315ef"/>
   <!--original fetch url was git://github.com/t2m-foxfone/-->
   <remote fetch="https://git.mozilla.org/external/t2m-foxfone" name="t2m"/>
   <default remote="caf" revision="LNX.LA.3.5.2.1.1" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="54c32c2ddef066fbdf611d29e4b7c47e0363599e"/>
   <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="e7c90613521145db090dd24147afd5ceb5703190"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ac778ae59be38aea284a04c89640b1a11c26a5de">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="2a2b008f9ae957fe19ad540d233d86b5c0b6829e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="71defd569502274e877b56094e3a44d776033120"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
   <project groups="linux" 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="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" 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="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "2a2b008f9ae957fe19ad540d233d86b5c0b6829e", 
+        "git_revision": "71defd569502274e877b56094e3a44d776033120", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "a37735733273b7cf2aee44ea123195bb610d0a8e", 
+    "revision": "59488903252981b50ff1d73fa5652332a2ca7fc3", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ac778ae59be38aea284a04c89640b1a11c26a5de">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="2a2b008f9ae957fe19ad540d233d86b5c0b6829e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="71defd569502274e877b56094e3a44d776033120"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" 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="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" 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="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="7f2ee9f4cb926684883fc2a2e407045fd9db2199">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="2a2b008f9ae957fe19ad540d233d86b5c0b6829e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="71defd569502274e877b56094e3a44d776033120"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
   <!-- Stock Android things -->
   <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="50d1ca4ab8add54523b7bc692860d57e8ee4c0d1"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="fb3845864573857677f9b500040a8f011eaf5078"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" revision="354496e8eddd28c743d8e02c02eeab02958367e6"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="b37c91354272b7413a0dc058b7445e677921d39e"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" revision="a227c92e0170bcf2296a63386956946b0dd78ca7"/>
   <project groups="pdk,linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" path="prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" revision="29f9b82faa1af9730f52e933dca848546cbea84c"/>
   <project groups="linux" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="0c2ee5a39ca67d5fceeeee4b55baa3e9c01f0dca"/>
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -12,17 +12,17 @@ MOZ_UA_OS_AGNOSTIC=1
 
 MOZ_B2G_VERSION=3.0.0.0-prerelease
 MOZ_B2G_OS_NAME=Boot2Gecko
 
 MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
-MOZ_SAFE_BROWSING=
+MOZ_SAFE_BROWSING=1
 MOZ_SERVICES_COMMON=1
 MOZ_SERVICES_METRICS=1
 MOZ_CAPTIVEDETECT=1
 
 MOZ_WEBSMS_BACKEND=1
 MOZ_NO_SMART_CARDS=1
 MOZ_APP_STATIC_INI=1
 NSS_NO_LIBPKIX=1
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -178,16 +178,19 @@
 @BINPATH@/components/dom_alarm.xpt
 @BINPATH@/components/dom_core.xpt
 @BINPATH@/components/dom_css.xpt
 @BINPATH@/components/dom_devicestorage.xpt
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_geolocation.xpt
 @BINPATH@/components/dom_media.xpt
 @BINPATH@/components/dom_network.xpt
+#ifdef MOZ_SECUREELEMENT
+@BINPATH@/components/dom_secureelement.xpt
+#endif
 #ifdef MOZ_NFC
 @BINPATH@/components/dom_nfc.xpt
 #endif
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
 @BINPATH@/components/dom_offline.xpt
 @BINPATH@/components/dom_payment.xpt
 @BINPATH@/components/dom_json.xpt
@@ -407,16 +410,22 @@
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
 @BINPATH@/components/nsAsyncShutdown.manifest
 @BINPATH@/components/nsAsyncShutdown.js
 @BINPATH@/components/htmlMenuBuilder.js
 @BINPATH@/components/htmlMenuBuilder.manifest
 @BINPATH@/components/PresentationDeviceInfoManager.manifest
 @BINPATH@/components/PresentationDeviceInfoManager.js
+#ifdef MOZ_SECUREELEMENT
+@BINPATH@/components/SecureElement.js
+@BINPATH@/components/SecureElement.manifest
+@BINPATH@/components/UiccConnector.js
+@BINPATH@/components/UiccConnector.manifest
+#endif
 
 ; WiFi, NetworkManager, NetworkStats
 #ifdef MOZ_WIDGET_GONK
 @BINPATH@/components/DOMWifiManager.js
 @BINPATH@/components/DOMWifiManager.manifest
 @BINPATH@/components/DOMWifiP2pManager.js
 @BINPATH@/components/DOMWifiP2pManager.manifest
 @BINPATH@/components/NetworkInterfaceListService.js
@@ -542,16 +551,20 @@
 #ifdef MOZ_NFC
 @BINPATH@/components/nsNfc.manifest
 @BINPATH@/components/nsNfc.js
 @BINPATH@/components/Nfc.manifest
 @BINPATH@/components/Nfc.js
 @BINPATH@/components/NfcContentHelper.manifest
 @BINPATH@/components/NfcContentHelper.js
 #endif
+#ifdef MOZ_SECUREELEMENT
+@BINPATH@/components/DOMSecureElement.manifest
+@BINPATH@/components/DOMSecureElement.js
+#endif
 #ifdef MOZ_ENABLE_DBUS
 @BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@
 #endif
 @BINPATH@/components/nsINIProcessor.manifest
 @BINPATH@/components/nsINIProcessor.js
 @BINPATH@/components/nsPrompter.manifest
 @BINPATH@/components/nsPrompter.js
 #ifdef MOZ_SERVICES_SYNC
--- a/configure.in
+++ b/configure.in
@@ -235,16 +235,17 @@ if test -n "$gonkdir" ; then
         MOZ_B2G_BT=1
         MOZ_B2G_BT_BLUEZ=1
         MOZ_NFC=1
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         MOZ_RTSP=1
         MOZ_FMP4=1
+        MOZ_SECUREELEMENT=1
         ;;
     17|18)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
         if test -d "$gonkdir/external/bluetooth/bluez"; then
           GONK_INCLUDES="$GONK_INCLUDES -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
             MOZ_B2G_BT=1
             MOZ_B2G_BT_BLUEZ=1
         elif test -d "$gonkdir/external/bluetooth/bluedroid"; then
@@ -259,31 +260,33 @@ if test -n "$gonkdir" ; then
         MOZ_NFC=1
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         MOZ_OMX_ENCODER=1
         AC_SUBST(MOZ_OMX_ENCODER)
         AC_DEFINE(MOZ_OMX_ENCODER)
 	MOZ_FMP4=1
+        MOZ_SECUREELEMENT=1
         ;;
     19)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
         MOZ_B2G_CAMERA=1
         MOZ_B2G_BT=1
         MOZ_B2G_BT_BLUEDROID=1
         if test -d "$gonkdir/system/bluetoothd"; then
             MOZ_B2G_BT_DAEMON=1
         fi
         MOZ_NFC=1
         MOZ_RTSP=1
         MOZ_OMX_DECODER=1
         MOZ_OMX_ENCODER=1
         AC_DEFINE(MOZ_OMX_ENCODER)
         MOZ_AUDIO_OFFLOAD=1
+        MOZ_SECUREELEMENT=1
         AC_SUBST(MOZ_AUDIO_OFFLOAD)
         AC_DEFINE(MOZ_AUDIO_OFFLOAD)
         MOZ_FMP4=1
         ;;
     21)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
         MOZ_AUDIO_OFFLOAD=1
         MOZ_OMX_DECODER=1
@@ -7581,16 +7584,25 @@ dnl ====================================
 dnl = Enable Support for AudioChannelManager API
 dnl ========================================================
 if test -n "$MOZ_AUDIO_CHANNEL_MANAGER"; then
     AC_DEFINE(MOZ_AUDIO_CHANNEL_MANAGER)
 fi
 AC_SUBST(MOZ_AUDIO_CHANNEL_MANAGER)
 
 dnl ========================================================
+dnl = Enable Support for Secure Element API
+dnl ========================================================
+   MOZ_SECUREELEMENT=1,
+if test -n "$MOZ_SECUREELEMENT"; then
+   AC_DEFINE(MOZ_SECUREELEMENT)
+fi
+ AC_SUBST(MOZ_SECUREELEMENT)
+
+dnl ========================================================
 dnl = Support for demangling undefined symbols
 dnl ========================================================
 if test -z "$SKIP_LIBRARY_CHECKS"; then
     AC_LANG_SAVE
     AC_LANG_CPLUSPLUS
     AC_CHECK_FUNCS(__cxa_demangle, HAVE_DEMANGLE=1, HAVE_DEMANGLE=)
     AC_LANG_RESTORE
 fi
--- a/dom/apps/PermissionsTable.jsm
+++ b/dom/apps/PermissionsTable.jsm
@@ -525,16 +525,22 @@ this.PermissionsTable =  { geolocation: 
                              privileged: DENY_ACTION,
                              certified: ALLOW_ACTION
                            },
                            "requestsync-manager": {
                              app: DENY_ACTION,
                              trusted: DENY_ACTION,
                              privileged: DENY_ACTION,
                              certified: ALLOW_ACTION
+                           },
+                           "secureelement-manage": {
+                             app: DENY_ACTION,
+                             trusted: DENY_ACTION,
+                             privileged: DENY_ACTION,
+                             certified: ALLOW_ACTION
                            }
                          };
 
 /**
  * Append access modes to the permission name as suffixes.
  *   e.g. permission name 'contacts' with ['read', 'write'] =
  *   ['contacts-read', contacts-write']
  * @param string aPermName
--- a/dom/bluetooth/BluetoothInterface.cpp
+++ b/dom/bluetooth/BluetoothInterface.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* -*- Mode: c++; c-basic-offset: 3; 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 "BluetoothInterface.h"
 #if ANDROID_VERSION >= 17
 #include <cutils/properties.h>
@@ -93,22 +93,22 @@ BluetoothNotificationHandler::~Bluetooth
 
 BluetoothInterface*
 BluetoothInterface::GetInstance()
 {
 #if ANDROID_VERSION >= 17
   /* We pick a default backend from the available ones. The branches
    * are ordered by preference.
    */
+#ifdef MOZ_B2G_BT_BLUEDROID
+  static const char sDefaultBackend[] = "bluedroid";
+#else
 #ifdef MOZ_B2G_BT_DAEMON
   static const char sDefaultBackend[] = "bluetoothd";
 #else
-#ifdef MOZ_B2G_BT_BLUEDROID
-  static const char sDefaultBackend[] = "bluedroid";
-#else
   static const char* const sDefaultBackend = nullptr;
 #endif
 #endif
 
   /* Here's where we decide which implementation to use. Currently
    * there is only Bluedroid and the Bluetooth daemon, but others are
    * possible. Having multiple interfaces built-in and selecting the
    * correct one at runtime is also an option.
--- a/dom/bluetooth2/BluetoothInterface.cpp
+++ b/dom/bluetooth2/BluetoothInterface.cpp
@@ -1,15 +1,18 @@
 /* -*- 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 "BluetoothInterface.h"
+#if ANDROID_VERSION >= 17
+#include <cutils/properties.h>
+#endif
 #ifdef MOZ_B2G_BT_BLUEDROID
 #include "BluetoothHALInterface.h"
 #endif
 #ifdef MOZ_B2G_BT_DAEMON
 #include "BluetoothDaemonInterface.h"
 #endif
 
 BEGIN_BLUETOOTH_NAMESPACE
@@ -121,30 +124,70 @@ BluetoothNotificationHandler::~Bluetooth
 { }
 
 // Interface
 //
 
 BluetoothInterface*
 BluetoothInterface::GetInstance()
 {
+#if ANDROID_VERSION >= 17
+  /* We pick a default backend from the available ones. The branches
+   * are ordered by preference.
+   */
+#ifdef MOZ_B2G_BT_BLUEDROID
+  static const char sDefaultBackend[] = "bluedroid";
+#else
+#ifdef MOZ_B2G_BT_DAEMON
+  static const char sDefaultBackend[] = "bluetoothd";
+#else
+  static const char* const sDefaultBackend = nullptr;
+#endif
+#endif
+
   /* Here's where we decide which implementation to use. Currently
    * there is only Bluedroid and the Bluetooth daemon, but others are
    * possible. Having multiple interfaces built-in and selecting the
-   * correct one at runtime could also be an option.
+   * correct one at runtime is also an option.
    */
+
+  char value[PROPERTY_VALUE_MAX];
+  int len;
+
+  len = property_get("ro.moz.bluetooth.backend", value, sDefaultBackend);
+  if (len < 0) {
+    BT_WARNING("No Bluetooth backend available.");
+    return nullptr;
+  }
+
+  const nsDependentCString backend(value, len);
+
 #ifdef MOZ_B2G_BT_BLUEDROID
-  return BluetoothHALInterface::GetInstance();
+  if (backend.LowerCaseEqualsLiteral("bluedroid")) {
+    return BluetoothHALInterface::GetInstance();
+  } else
+#endif
+#ifdef MOZ_B2G_BT_DAEMON
+  if (backend.LowerCaseEqualsLiteral("bluetoothd")) {
+    return BluetoothDaemonInterface::GetInstance();
+  } else
+#endif
+  {
+    BT_WARNING("Bluetooth backend '%s' is unknown or not available.",
+               backend.get());
+  }
+  return nullptr;
+
 #else
-#ifdef MOZ_B2G_BT_DAEMON
-  return BluetoothDaemonInterface::GetInstance();
-#else
+  /* Anything that's not Android 4.2 or later uses BlueZ instead. The
+   * code should actually never reach this point.
+   */
+  BT_WARNING("No Bluetooth backend available for your system.");
   return nullptr;
 #endif
-#endif
 }
 
 BluetoothInterface::BluetoothInterface()
 { }
 
 BluetoothInterface::~BluetoothInterface()
 { }
 
--- a/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp
@@ -338,16 +338,28 @@ Convert(uint8_t aIn, BluetoothHandsfreeV
   if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sVolumeType))) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
   aOut = sVolumeType[aIn];
   return NS_OK;
 }
 
 nsresult
+Convert(int aIn, int32_t& aOut)
+{
+  if (NS_WARN_IF(aIn < std::numeric_limits<int32_t>::min()) ||
+      NS_WARN_IF(aIn > std::numeric_limits<int32_t>::max())) {
+    aOut = 0; // silences compiler warning
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = static_cast<int32_t>(aIn);
+  return NS_OK;
+}
+
+nsresult
 Convert(int32_t aIn, BluetoothTypeOfDevice& aOut)
 {
   static const BluetoothTypeOfDevice sTypeOfDevice[] = {
     CONVERT(0x00, static_cast<BluetoothTypeOfDevice>(0)), // invalid, required by gcc
     CONVERT(0x01, TYPE_OF_DEVICE_BREDR),
     CONVERT(0x02, TYPE_OF_DEVICE_BLE),
     CONVERT(0x03, TYPE_OF_DEVICE_DUAL)
   };
@@ -655,28 +667,61 @@ Convert(BluetoothAvrcpNotification aIn, 
   if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sValue))) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
   aOut = sValue[aIn];
   return NS_OK;
 }
 
 nsresult
+Convert(BluetoothAvrcpPlayerAttribute aIn, uint8_t& aOut)
+{
+  static const uint8_t sValue[] = {
+    CONVERT(AVRCP_PLAYER_ATTRIBUTE_EQUALIZER, 0x01),
+    CONVERT(AVRCP_PLAYER_ATTRIBUTE_REPEAT, 0x02),
+    CONVERT(AVRCP_PLAYER_ATTRIBUTE_SHUFFLE, 0x03),
+    CONVERT(AVRCP_PLAYER_ATTRIBUTE_SCAN, 0x04)
+  };
+  if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sValue))) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = sValue[aIn];
+  return NS_OK;
+}
+
+nsresult
 Convert(BluetoothAvrcpRemoteFeature aIn, unsigned long& aOut)
 {
   if (NS_WARN_IF(aIn < std::numeric_limits<unsigned long>::min()) ||
       NS_WARN_IF(aIn > std::numeric_limits<unsigned long>::max())) {
     aOut = 0; // silences compiler warning
     return NS_ERROR_ILLEGAL_VALUE;
   }
   aOut = static_cast<unsigned long>(aIn);
   return NS_OK;
 }
 
 nsresult
+Convert(BluetoothAvrcpStatus aIn, uint8_t& aOut)
+{
+  static const uint8_t sValue[] = {
+    CONVERT(AVRCP_STATUS_BAD_COMMAND, 0x00),
+    CONVERT(AVRCP_STATUS_BAD_PARAMETER, 0x01),
+    CONVERT(AVRCP_STATUS_NOT_FOUND, 0x02),
+    CONVERT(AVRCP_STATUS_INTERNAL_ERROR, 0x03),
+    CONVERT(AVRCP_STATUS_SUCCESS, 0x04)
+  };
+  if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sValue))) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = sValue[aIn];
+  return NS_OK;
+}
+
+nsresult
 Convert(BluetoothHandsfreeAtResponse aIn, uint8_t& aOut)
 {
   static const uint8_t sAtResponse[] = {
     CONVERT(HFP_AT_RESPONSE_ERROR, 0x00),
     CONVERT(HFP_AT_RESPONSE_OK, 0x01)
   };
   if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sAtResponse))) {
     aOut = 0x00; // silences compiler warning
@@ -1088,16 +1133,29 @@ PackPDU(const BluetoothAvrcpEventParamPa
 nsresult
 PackPDU(BluetoothAvrcpNotification aIn, BluetoothDaemonPDU& aPDU)
 {
   return PackPDU(
     PackConversion<BluetoothAvrcpNotification, uint8_t>(aIn), aPDU);
 }
 
 nsresult
+PackPDU(BluetoothAvrcpPlayerAttribute aIn, BluetoothDaemonPDU& aPDU)
+{
+  return PackPDU(
+    PackConversion<BluetoothAvrcpPlayerAttribute, uint8_t>(aIn), aPDU);
+}
+
+nsresult
+PackPDU(BluetoothAvrcpStatus aIn, BluetoothDaemonPDU& aPDU)
+{
+  return PackPDU(PackConversion<BluetoothAvrcpStatus, uint8_t>(aIn), aPDU);
+}
+
+nsresult
 PackPDU(const BluetoothConfigurationParameter& aIn, BluetoothDaemonPDU& aPDU)
 {
   return PackPDU(aIn.mType, aIn.mLength,
                  PackArray<uint8_t>(aIn.mValue.get(), aIn.mLength), aPDU);
 }
 
 nsresult
 PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU)
--- a/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.h
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.h
@@ -124,16 +124,19 @@ Convert(bool aIn, BluetoothScanMode& aOu
 
 nsresult
 Convert(int aIn, uint8_t& aOut);
 
 nsresult
 Convert(int aIn, int16_t& aOut);
 
 nsresult
+Convert(int aIn, int32_t& aOut);
+
+nsresult
 Convert(uint8_t aIn, bool& aOut);
 
 nsresult
 Convert(uint8_t aIn, char& aOut);
 
 nsresult
 Convert(uint8_t aIn, int& aOut);
 
@@ -229,19 +232,25 @@ Convert(const BluetoothAddress& aIn, nsA
 
 nsresult
 Convert(BluetoothAvrcpEvent aIn, uint8_t& aOut);
 
 nsresult
 Convert(BluetoothAvrcpNotification aIn, uint8_t& aOut);
 
 nsresult
+Convert(BluetoothAvrcpPlayerAttribute aIn, uint8_t& aOut);
+
+nsresult
 Convert(BluetoothAvrcpRemoteFeature aIn, unsigned long& aOut);
 
 nsresult
+Convert(BluetoothAvrcpStatus aIn, uint8_t& aOut);
+
+nsresult
 Convert(BluetoothHandsfreeAtResponse aIn, uint8_t& aOut);
 
 nsresult
 Convert(BluetoothHandsfreeCallAddressType aIn, uint8_t& aOut);
 
 nsresult
 Convert(BluetoothHandsfreeCallDirection aIn, uint8_t& aOut);
 
@@ -280,16 +289,21 @@ Convert(BluetoothSspVariant aIn, uint8_t
 
 nsresult
 Convert(ControlPlayStatus aIn, uint8_t& aOut);
 
 //
 // Packing
 //
 
+// introduce link errors on non-handled data types
+template <typename T>
+nsresult
+PackPDU(T aIn, BluetoothDaemonPDU& aPDU);
+
 nsresult
 PackPDU(bool aIn, BluetoothDaemonPDU& aPDU);
 
 inline nsresult
 PackPDU(uint8_t aIn, BluetoothDaemonPDU& aPDU)
 {
   return aPDU.Write(aIn);
 }
@@ -331,16 +345,22 @@ PackPDU(BluetoothAvrcpEvent aIn, Bluetoo
 
 nsresult
 PackPDU(const BluetoothAvrcpEventParamPair& aIn, BluetoothDaemonPDU& aPDU);
 
 nsresult
 PackPDU(BluetoothAvrcpNotification aIn, BluetoothDaemonPDU& aPDU);
 
 nsresult
+PackPDU(BluetoothAvrcpPlayerAttribute aIn, BluetoothDaemonPDU& aPDU);
+
+nsresult
+PackPDU(BluetoothAvrcpStatus aIn, BluetoothDaemonPDU& aPDU);
+
+nsresult
 PackPDU(const BluetoothConfigurationParameter& aIn, BluetoothDaemonPDU& aPDU);
 
 nsresult
 PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU);
 
 nsresult
 PackPDU(const BluetoothHandsfreeAtResponse& aIn, BluetoothDaemonPDU& aPDU);
 
@@ -588,16 +608,21 @@ PackPDU(const T1& aIn1, const T2& aIn2, 
   }
   return PackPDU(aIn7, aPDU);
 }
 
 //
 // Unpacking
 //
 
+// introduce link errors on non-handled data types
+template <typename T>
+nsresult
+UnpackPDU(BluetoothDaemonPDU& aPDU, T& aOut);
+
 inline nsresult
 UnpackPDU(BluetoothDaemonPDU& aPDU, int8_t& aOut)
 {
   return aPDU.Read(aOut);
 }
 
 inline nsresult
 UnpackPDU(BluetoothDaemonPDU& aPDU, uint8_t& aOut)
@@ -799,16 +824,29 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, cons
     nsresult rv = UnpackPDU(aPDU, aOut.mData[i]);
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
   return NS_OK;
 }
 
+template<typename T>
+inline nsresult
+UnpackPDU(BluetoothDaemonPDU& aPDU, UnpackArray<T>& aOut)
+{
+  for (size_t i = 0; i < aOut.mLength; ++i) {
+    nsresult rv = UnpackPDU(aPDU, aOut.mData[i]);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  }
+  return NS_OK;
+}
+
 template<>
 inline nsresult
 UnpackPDU<uint8_t>(BluetoothDaemonPDU& aPDU, const UnpackArray<uint8_t>& aOut)
 {
   /* Read raw bytes in one pass */
   return aPDU.Read(aOut.mData, aOut.mLength);
 }
 
--- a/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.cpp
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.cpp
@@ -1,23 +1,29 @@
 /* -*- 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 "BluetoothDaemonInterface.h"
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <stdlib.h>
 #include "BluetoothDaemonA2dpInterface.h"
 #include "BluetoothDaemonAvrcpInterface.h"
 #include "BluetoothDaemonHandsfreeInterface.h"
 #include "BluetoothDaemonHelpers.h"
 #include "BluetoothDaemonSetupInterface.h"
 #include "BluetoothDaemonSocketInterface.h"
 #include "BluetoothInterfaceHelpers.h"
+#include "mozilla/ipc/ListenSocket.h"
+#include "mozilla/ipc/UnixSocketConnector.h"
 #include "mozilla/unused.h"
+#include "prrng.h"
 
 using namespace mozilla::ipc;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 //
 // Protocol initialization and setup
 //
@@ -1507,17 +1513,19 @@ class BluetoothDaemonProtocol MOZ_FINAL
   , public BluetoothDaemonSetupModule
   , public BluetoothDaemonCoreModule
   , public BluetoothDaemonSocketModule
   , public BluetoothDaemonHandsfreeModule
   , public BluetoothDaemonA2dpModule
   , public BluetoothDaemonAvrcpModule
 {
 public:
-  BluetoothDaemonProtocol(BluetoothDaemonConnection* aConnection);
+  BluetoothDaemonProtocol();
+
+  void SetConnection(BluetoothDaemonConnection* aConnection);
 
   nsresult RegisterModule(uint8_t aId, uint8_t aMode,
                           BluetoothSetupResultHandler* aRes) MOZ_OVERRIDE;
 
   nsresult UnregisterModule(uint8_t aId,
                             BluetoothSetupResultHandler* aRes) MOZ_OVERRIDE;
 
   // Outgoing PDUs
@@ -1547,21 +1555,23 @@ private:
                      BluetoothDaemonPDU& aPDU, void* aUserData);
   void HandleAvrcpSvc(const BluetoothDaemonPDUHeader& aHeader,
                       BluetoothDaemonPDU& aPDU, void* aUserData);
 
   BluetoothDaemonConnection* mConnection;
   nsTArray<void*> mUserDataQ;
 };
 
-BluetoothDaemonProtocol::BluetoothDaemonProtocol(
-  BluetoothDaemonConnection* aConnection)
-  : mConnection(aConnection)
+BluetoothDaemonProtocol::BluetoothDaemonProtocol()
+{ }
+
+void
+BluetoothDaemonProtocol::SetConnection(BluetoothDaemonConnection* aConnection)
 {
-  MOZ_ASSERT(mConnection);
+  mConnection = aConnection;
 }
 
 nsresult
 BluetoothDaemonProtocol::RegisterModule(uint8_t aId, uint8_t aMode,
                                         BluetoothSetupResultHandler* aRes)
 {
   return BluetoothDaemonSetupModule::RegisterModuleCmd(aId, aMode, aRes);
 }
@@ -1571,16 +1581,17 @@ BluetoothDaemonProtocol::UnregisterModul
                                           BluetoothSetupResultHandler* aRes)
 {
   return BluetoothDaemonSetupModule::UnregisterModuleCmd(aId, aRes);
 }
 
 nsresult
 BluetoothDaemonProtocol::Send(BluetoothDaemonPDU* aPDU, void* aUserData)
 {
+  MOZ_ASSERT(mConnection);
   MOZ_ASSERT(aPDU);
 
   aPDU->SetUserData(aUserData);
   aPDU->UpdateHeader();
   return mConnection->Send(aPDU); // Forward PDU to command channel
 }
 
 void
@@ -1683,83 +1694,136 @@ BluetoothDaemonProtocol::FetchUserData(c
 
   void* userData = mUserDataQ.ElementAt(0);
   mUserDataQ.RemoveElementAt(0);
 
   return userData;
 }
 
 //
-// Channels
+// Listen socket
 //
 
-class BluetoothDaemonChannel MOZ_FINAL : public BluetoothDaemonConnection
+class BluetoothDaemonListenSocket MOZ_FINAL : public ipc::ListenSocket
 {
 public:
-  BluetoothDaemonChannel(BluetoothDaemonInterface::Channel aChannel);
-
-  nsresult ConnectSocket(BluetoothDaemonInterface* aInterface,
-                         BluetoothDaemonPDUConsumer* aConsumer);
+  BluetoothDaemonListenSocket(BluetoothDaemonInterface* aInterface);
 
   // Connection state
   //
 
   void OnConnectSuccess() MOZ_OVERRIDE;
   void OnConnectError() MOZ_OVERRIDE;
   void OnDisconnect() MOZ_OVERRIDE;
 
 private:
   BluetoothDaemonInterface* mInterface;
+};
+
+BluetoothDaemonListenSocket::BluetoothDaemonListenSocket(
+  BluetoothDaemonInterface* aInterface)
+  : mInterface(aInterface)
+{ }
+
+void
+BluetoothDaemonListenSocket::OnConnectSuccess()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mInterface);
+
+  mInterface->OnConnectSuccess(BluetoothDaemonInterface::LISTEN_SOCKET);
+}
+
+void
+BluetoothDaemonListenSocket::OnConnectError()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mInterface);
+
+  mInterface->OnConnectError(BluetoothDaemonInterface::LISTEN_SOCKET);
+}
+
+void
+BluetoothDaemonListenSocket::OnDisconnect()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mInterface);
+
+  mInterface->OnDisconnect(BluetoothDaemonInterface::LISTEN_SOCKET);
+}
+
+//
+// Channels
+//
+
+class BluetoothDaemonChannel MOZ_FINAL : public BluetoothDaemonConnection
+{
+public:
+  BluetoothDaemonChannel(BluetoothDaemonInterface* aInterface,
+                         BluetoothDaemonInterface::Channel aChannel,
+                         BluetoothDaemonPDUConsumer* aConsumer);
+
+  // SocketBase
+  //
+
+  void OnConnectSuccess() MOZ_OVERRIDE;
+  void OnConnectError() MOZ_OVERRIDE;
+  void OnDisconnect() MOZ_OVERRIDE;
+
+  // ConnectionOrientedSocket
+  //
+
+  ConnectionOrientedSocketIO* GetIO() MOZ_OVERRIDE;
+
+private:
+  BluetoothDaemonInterface* mInterface;
   BluetoothDaemonInterface::Channel mChannel;
+  BluetoothDaemonPDUConsumer* mConsumer;
 };
 
 BluetoothDaemonChannel::BluetoothDaemonChannel(
-  BluetoothDaemonInterface::Channel aChannel)
-: mInterface(nullptr)
-, mChannel(aChannel)
+  BluetoothDaemonInterface* aInterface,
+  BluetoothDaemonInterface::Channel aChannel,
+  BluetoothDaemonPDUConsumer* aConsumer)
+  : mInterface(aInterface)
+  , mChannel(aChannel)
+  , mConsumer(aConsumer)
 { }
 
-nsresult
-BluetoothDaemonChannel::ConnectSocket(BluetoothDaemonInterface* aInterface,
-                                      BluetoothDaemonPDUConsumer* aConsumer)
-{
-  MOZ_ASSERT(aInterface);
-
-  mInterface = aInterface;
-
-  return BluetoothDaemonConnection::ConnectSocket(aConsumer);
-}
-
 void
 BluetoothDaemonChannel::OnConnectSuccess()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mInterface);
 
   mInterface->OnConnectSuccess(mChannel);
 }
 
 void
 BluetoothDaemonChannel::OnConnectError()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mInterface);
 
   mInterface->OnConnectError(mChannel);
-  mInterface = nullptr;
 }
 
 void
 BluetoothDaemonChannel::OnDisconnect()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mInterface);
 
   mInterface->OnDisconnect(mChannel);
-  mInterface = nullptr;
+}
+
+ConnectionOrientedSocketIO*
+BluetoothDaemonChannel::GetIO()
+{
+  return PrepareAccept(mConsumer);
 }
 
 //
 // Interface
 //
 
 /* returns the container structure of a variable; _t is the container's
  * type, _v the name of the variable, and _m is _v's field within _t
@@ -1771,48 +1835,23 @@ BluetoothDaemonInterface*
 BluetoothDaemonInterface::GetInstance()
 {
   static BluetoothDaemonInterface* sBluetoothInterface;
 
   if (sBluetoothInterface) {
     return sBluetoothInterface;
   }
 
-  // Only create channel objects here. The connection will be
-  // established by |BluetoothDaemonInterface::Init|.
-
-  BluetoothDaemonChannel* cmdChannel =
-    new BluetoothDaemonChannel(BluetoothDaemonInterface::CMD_CHANNEL);
-
-  BluetoothDaemonChannel* ntfChannel =
-    new BluetoothDaemonChannel(BluetoothDaemonInterface::NTF_CHANNEL);
-
-  // Create a new interface object with the channels and a
-  // protocol handler.
-
-  sBluetoothInterface =
-    new BluetoothDaemonInterface(cmdChannel,
-                                 ntfChannel,
-                                 new BluetoothDaemonProtocol(cmdChannel));
+  sBluetoothInterface = new BluetoothDaemonInterface();
 
   return sBluetoothInterface;
 }
 
-BluetoothDaemonInterface::BluetoothDaemonInterface(
-  BluetoothDaemonChannel* aCmdChannel,
-  BluetoothDaemonChannel* aNtfChannel,
-  BluetoothDaemonProtocol* aProtocol)
-: mCmdChannel(aCmdChannel)
-, mNtfChannel(aNtfChannel)
-, mProtocol(aProtocol)
-{
-  MOZ_ASSERT(mCmdChannel);
-  MOZ_ASSERT(mNtfChannel);
-  MOZ_ASSERT(mProtocol);
-}
+BluetoothDaemonInterface::BluetoothDaemonInterface()
+{ }
 
 BluetoothDaemonInterface::~BluetoothDaemonInterface()
 { }
 
 class BluetoothDaemonInterface::InitResultHandler MOZ_FINAL
   : public BluetoothSetupResultHandler
 {
 public:
@@ -1840,21 +1879,21 @@ public:
 
   void RegisterModule() MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(mInterface->mProtocol);
 
     if (!mRegisteredSocketModule) {
       mRegisteredSocketModule = true;
-      // Init, step 4: Register Socket module
+      // Init, step 5: Register Socket module
       mInterface->mProtocol->RegisterModuleCmd(
         BluetoothDaemonSocketModule::SERVICE_ID, 0x00, this);
     } else if (mRes) {
-      // Init, step 5: Signal success to caller
+      // Init, step 6: Signal success to caller
       mRes->Init();
     }
   }
 
 private:
   BluetoothDaemonInterface* mInterface;
   nsRefPtr<BluetoothResultHandler> mRes;
   bool mRegisteredSocketModule;
@@ -1862,34 +1901,43 @@ private:
 
 void
 BluetoothDaemonInterface::OnConnectSuccess(enum Channel aChannel)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mResultHandlerQ.IsEmpty());
 
   switch (aChannel) {
-    case CMD_CHANNEL:
-      // Init, step 2: Connect notification channel...
-      if (mNtfChannel->GetConnectionStatus() != SOCKET_CONNECTED) {
-        nsresult rv = mNtfChannel->ConnectSocket(this, mProtocol);
-        if (NS_FAILED(rv)) {
-          OnConnectError(NTF_CHANNEL);
+    case LISTEN_SOCKET: {
+        // Init, step 2: Start Bluetooth daemon */
+        nsCString value("bluetoothd:-a ");
+        value.Append(mListenSocketName);
+        if (NS_WARN_IF(property_set("ctl.start", value.get()) < 0)) {
+          OnConnectError(CMD_CHANNEL);
         }
-      } else {
-        // ...or go to step 3 if channel is already connected.
-        OnConnectSuccess(NTF_CHANNEL);
       }
       break;
-
+    case CMD_CHANNEL:
+      // Init, step 3: Listen for notification channel...
+      if (!mNtfChannel) {
+        mNtfChannel = new BluetoothDaemonChannel(this, NTF_CHANNEL, mProtocol);
+      } else if (
+        NS_WARN_IF(mNtfChannel->GetConnectionStatus() == SOCKET_CONNECTED)) {
+        /* Notification channel should not be open; let's close it. */
+        mNtfChannel->CloseSocket();
+      }
+      if (!mListenSocket->Listen(mNtfChannel)) {
+        OnConnectError(NTF_CHANNEL);
+      }
+      break;
     case NTF_CHANNEL: {
         nsRefPtr<BluetoothResultHandler> res = mResultHandlerQ.ElementAt(0);
         mResultHandlerQ.RemoveElementAt(0);
 
-        // Init, step 3: Register Core module
+        // Init, step 4: Register Core module
         nsresult rv = mProtocol->RegisterModuleCmd(
           BluetoothDaemonCoreModule::SERVICE_ID, 0x00,
           new InitResultHandler(this, res));
         if (NS_FAILED(rv) && res) {
           DispatchError(res, STATUS_FAIL);
         }
       }
       break;
@@ -1902,17 +1950,21 @@ BluetoothDaemonInterface::OnConnectError
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mResultHandlerQ.IsEmpty());
 
   switch (aChannel) {
     case NTF_CHANNEL:
       // Close command channel
       mCmdChannel->CloseSocket();
       /* fall through for cleanup and error signalling */
-    case CMD_CHANNEL: {
+    case CMD_CHANNEL:
+      // Stop daemon and close listen socket
+      unused << NS_WARN_IF(property_set("ctl.stop", "bluetoothd"));
+      mListenSocket->Close();
+    case LISTEN_SOCKET: {
         // Signal error to caller
         nsRefPtr<BluetoothResultHandler> res = mResultHandlerQ.ElementAt(0);
         mResultHandlerQ.RemoveElementAt(0);
 
         if (res) {
           DispatchError(res, STATUS_FAIL);
         }
       }
@@ -1922,52 +1974,238 @@ BluetoothDaemonInterface::OnConnectError
 
 void
 BluetoothDaemonInterface::OnDisconnect(enum Channel aChannel)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mResultHandlerQ.IsEmpty());
 
   switch (aChannel) {
+    case CMD_CHANNEL:
+      // We don't have to do anything here. Step 4 is triggered
+      // by the daemon.
+      break;
     case NTF_CHANNEL:
-      // Cleanup, step 4: Close command channel
-      mCmdChannel->CloseSocket();
+      // Cleanup, step 4: Close listen socket
+      mListenSocket->Close();
       break;
-    case CMD_CHANNEL: {
+    case LISTEN_SOCKET: {
         nsRefPtr<BluetoothResultHandler> res = mResultHandlerQ.ElementAt(0);
         mResultHandlerQ.RemoveElementAt(0);
 
         // Cleanup, step 5: Signal success to caller
         if (res) {
           res->Cleanup();
         }
       }
       break;
   }
 }
 
+class BluetoothDaemonSocketConnector MOZ_FINAL
+  : public mozilla::ipc::UnixSocketConnector
+{
+public:
+  BluetoothDaemonSocketConnector(const nsACString& aSocketName)
+    : mSocketName(aSocketName)
+  { }
+
+  int
+  Create() MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(!NS_IsMainThread());
+
+    int fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+    if (fd < 0) {
+      BT_WARNING("Could not open socket!");
+      return -1;
+    }
+    return fd;
+  }
+
+  bool
+  CreateAddr(bool aIsServer,
+             socklen_t& aAddrSize,
+             sockaddr_any& aAddr,
+             const char* aAddress) MOZ_OVERRIDE
+  {
+    static const size_t sNameOffset = 1;
+
+    size_t namesiz = mSocketName.Length() + 1; /* include trailing '\0' */
+
+    if ((sNameOffset + namesiz) > sizeof(aAddr.un.sun_path)) {
+      BT_WARNING("Address too long for socket struct!");
+      return false;
+    }
+
+    memset(aAddr.un.sun_path, '\0', sNameOffset); // abstract socket
+    memcpy(aAddr.un.sun_path + sNameOffset, mSocketName.get(), namesiz);
+    aAddr.un.sun_family = AF_UNIX;
+
+    aAddrSize = offsetof(struct sockaddr_un, sun_path) + sNameOffset + namesiz;
+
+    return true;
+  }
+
+  bool
+  SetUp(int aFd) MOZ_OVERRIDE
+  {
+    if (TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, O_NONBLOCK)) < 0) {
+      BT_WARNING("Failed to set non-blocking I/O.");
+      return false;
+    }
+    return true;
+  }
+
+  bool
+  SetUpListenSocket(int aFd) MOZ_OVERRIDE
+  {
+    return true;
+  }
+
+  void
+  GetSocketAddr(const sockaddr_any& aAddr, nsAString& aAddrStr) MOZ_OVERRIDE
+  {
+    // Unused.
+    MOZ_CRASH("This should never be called!");
+  }
+
+private:
+  nsCString mSocketName;
+};
+
+nsresult
+BluetoothDaemonInterface::CreateRandomAddressString(
+  const nsACString& aPrefix, unsigned long aPostfixLength,
+  nsACString& aAddress)
+{
+  static const char sHexChar[16] = {
+    [0x0] = '0', [0x1] = '1', [0x2] = '2', [0x3] = '3',
+    [0x4] = '4', [0x5] = '5', [0x6] = '6', [0x7] = '7',
+    [0x8] = '8', [0x9] = '9', [0xa] = 'a', [0xb] = 'b',
+    [0xc] = 'c', [0xd] = 'd', [0xe] = 'e', [0xf] = 'f'
+  };
+
+  unsigned short seed[3];
+
+  if (NS_WARN_IF(!PR_GetRandomNoise(seed, sizeof(seed)))) {
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+
+  aAddress = aPrefix;
+  aAddress.Append('-');
+
+  while (aPostfixLength) {
+
+    // Android doesn't provide rand_r, so we use nrand48 here,
+    // even though it's deprecated.
+    long value = nrand48(seed);
+
+    size_t bits = sizeof(value) * CHAR_BIT;
+
+    while ((bits > 4) && aPostfixLength) {
+      aAddress.Append(sHexChar[value&0xf]);
+      bits -= 4;
+      value >>= 4;
+      --aPostfixLength;
+    }
+  }
+
+  return NS_OK;
+}
+
+/*
+ * The init procedure consists of several steps.
+ *
+ *  (1) Start listening for the command channel's socket connection: We
+ *      do this before anything else, so that we don't miss connection
+ *      requests from the Bluetooth daemon. This step will create a
+ *      listen socket.
+ *
+ *  (2) Start the Bluetooth daemon: When the daemon starts up it will
+ *      open two socket connections to Gecko and thus create the command
+ *      and notification channels. Gecko already opened the listen socket
+ *      in step (1). Step (2) ends with the creation of the command channel.
+ *
+ *  (3) Start listening for the notification channel's socket connection:
+ *      At the end of step (2), the command channel was opened by the
+ *      daemon. In step (3), the daemon immediately tries to open the
+ *      next socket for the notification channel. Gecko will accept the
+ *      incoming connection request for the notification channel. The
+ *      listen socket remained open after step (2), so there's no race
+ *      condition between Gecko and the Bluetooth daemon.
+ *
+ *  (4)(5) Register Core and Socket modules: The Core and Socket modules
+ *      are always available and have to be registered after opening the
+ *      socket connections during the initialization.
+ *
+ *  (6) Signal success to the caller.
+ *
+ * If any step fails, we roll-back the procedure and signal an error to the
+ * caller.
+ */
 void
 BluetoothDaemonInterface::Init(
   BluetoothNotificationHandler* aNotificationHandler,
   BluetoothResultHandler* aRes)
 {
+  static const char BASE_SOCKET_NAME[] = "bluetoothd";
+  static unsigned long POSTFIX_LENGTH = 16;
+
+  // If we could not cleanup properly before and an old
+  // instance of the daemon is still running, we kill it
+  // here.
+  unused << NS_WARN_IF(property_set("ctl.stop", "bluetoothd"));
+
   sNotificationHandler = aNotificationHandler;
 
   mResultHandlerQ.AppendElement(aRes);
 
-  // Init, step 1: Connect command channel...
-  if (mCmdChannel->GetConnectionStatus() != SOCKET_CONNECTED) {
-    nsresult rv = mCmdChannel->ConnectSocket(this, mProtocol);
-    if (NS_FAILED(rv)) {
-      OnConnectError(CMD_CHANNEL);
-    }
-  } else {
-    // ...or go to step 2 if channel is already connected.
-    OnConnectSuccess(CMD_CHANNEL);
+  if (!mProtocol) {
+    mProtocol = new BluetoothDaemonProtocol();
+  }
+
+  if (!mListenSocket) {
+    mListenSocket = new BluetoothDaemonListenSocket(this);
+  }
+
+  // Init, step 1: Listen for command channel... */
+
+  if (!mCmdChannel) {
+    mCmdChannel = new BluetoothDaemonChannel(this, CMD_CHANNEL, mProtocol);
+  } else if (
+    NS_WARN_IF(mCmdChannel->GetConnectionStatus() == SOCKET_CONNECTED)) {
+    // Command channel should not be open; let's close it.
+    mCmdChannel->CloseSocket();
   }
+
+  // The listen socket's name is generated with a random postfix. This
+  // avoids naming collisions if we still have a listen socket from a
+  // previously failed cleanup. It also makes it hard for malicious
+  // external programs to capture the socket name or connect before
+  // the daemon can do so. If no random postfix can be generated, we
+  // simply use the base name as-is.
+  nsresult rv = CreateRandomAddressString(NS_LITERAL_CSTRING(BASE_SOCKET_NAME),
+                                          POSTFIX_LENGTH,
+                                          mListenSocketName);
+  if (NS_FAILED(rv)) {
+    mListenSocketName = BASE_SOCKET_NAME;
+  }
+
+  bool success = mListenSocket->Listen(
+    new BluetoothDaemonSocketConnector(mListenSocketName), mCmdChannel);
+  if (!success) {
+    OnConnectError(CMD_CHANNEL);
+    return;
+  }
+
+  // The protocol implementation needs a command channel for
+  // sending commands to the daemon. We set it here, because
+  // this is the earliest time when it's available.
+  mProtocol->SetConnection(mCmdChannel);
 }
 
 class BluetoothDaemonInterface::CleanupResultHandler MOZ_FINAL
   : public BluetoothSetupResultHandler
 {
 public:
   CleanupResultHandler(BluetoothDaemonInterface* aInterface)
     : mInterface(aInterface)
@@ -1993,25 +2231,50 @@ private:
     MOZ_ASSERT(mInterface->mProtocol);
 
     if (!mUnregisteredCoreModule) {
       mUnregisteredCoreModule = true;
       // Cleanup, step 2: Unregister Core module
       mInterface->mProtocol->UnregisterModuleCmd(
         BluetoothDaemonCoreModule::SERVICE_ID, this);
     } else {
-      // Cleanup, step 3: Close notification channel
-      mInterface->mNtfChannel->CloseSocket();
+      // Cleanup, step 3: Close command channel
+      mInterface->mCmdChannel->CloseSocket();
     }
   }
 
   BluetoothDaemonInterface* mInterface;
   bool mUnregisteredCoreModule;
 };
 
+/*
+ * Cleaning up is inverse to initialization, except for the shutdown
+ * of the socket connections in step (3)
+ *
+ *  (1)(2) Unregister Socket and Core modules: These modules have been
+ *      registered during initialization and need to be unregistered
+ *      here. We assume that all other modules are already unregistered.
+ *
+ *  (3) Close command socket: We only close the command socket. The
+ *      daemon will then send any final notifications and close the
+ *      notification socket on its side. Once we see the notification
+ *      socket's disconnect, we continue with the cleanup.
+ *
+ *  (4) Close listen socket: The listen socket is not active any longer
+ *      and we simply close it.
+ *
+ *  (5) Signal success to the caller.
+ *
+ * We don't have to stop the daemon explicitly. It will cleanup and quit
+ * after it closed the notification socket.
+ *
+ * Rolling-back half-completed cleanups is not possible. In the case of
+ * an error, we simply push forward and try to recover during the next
+ * initialization.
+ */
 void
 BluetoothDaemonInterface::Cleanup(BluetoothResultHandler* aRes)
 {
   sNotificationHandler = nullptr;
 
   mResultHandlerQ.AppendElement(aRes);
 
   // Cleanup, step 1: Unregister Socket module
--- a/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.h
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.h
@@ -6,29 +6,31 @@
 
 #ifndef mozilla_dom_bluetooth_bluedroid_bluetoothdaemoninterface_h__
 #define mozilla_dom_bluetooth_bluedroid_bluetoothdaemoninterface_h__
 
 #include "BluetoothInterface.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
+class BluetoothDaemonListenSocket;
 class BluetoothDaemonChannel;
 class BluetoothDaemonA2dpInterface;
 class BluetoothDaemonAvrcpInterface;
 class BluetoothDaemonHandsfreeInterface;
 class BluetoothDaemonProtocol;
 class BluetoothDaemonSocketInterface;
 
 class BluetoothDaemonInterface MOZ_FINAL : public BluetoothInterface
 {
 public:
   class CleanupResultHandler;
   class InitResultHandler;
 
+  friend class BluetoothDaemonListenSocket;
   friend class BluetoothDaemonChannel;
   friend class CleanupResultHandler;
   friend class InitResultHandler;
 
   static BluetoothDaemonInterface* GetInstance();
 
   void Init(BluetoothNotificationHandler* aNotificationHandler,
             BluetoothResultHandler* aRes);
@@ -101,34 +103,39 @@ public:
   BluetoothSocketInterface* GetBluetoothSocketInterface() MOZ_OVERRIDE;
   BluetoothHandsfreeInterface* GetBluetoothHandsfreeInterface() MOZ_OVERRIDE;
   BluetoothA2dpInterface* GetBluetoothA2dpInterface() MOZ_OVERRIDE;
   BluetoothAvrcpInterface* GetBluetoothAvrcpInterface() MOZ_OVERRIDE;
   BluetoothGattInterface* GetBluetoothGattInterface() MOZ_OVERRIDE;
 
 protected:
   enum Channel {
+    LISTEN_SOCKET,
     CMD_CHANNEL,
     NTF_CHANNEL
   };
 
-  BluetoothDaemonInterface(BluetoothDaemonChannel* aCmdChannel,
-                           BluetoothDaemonChannel* aNtfChannel,
-                           BluetoothDaemonProtocol* aProtocol);
+  BluetoothDaemonInterface();
   ~BluetoothDaemonInterface();
 
   void OnConnectSuccess(enum Channel aChannel);
   void OnConnectError(enum Channel aChannel);
   void OnDisconnect(enum Channel aChannel);
 
+  nsresult CreateRandomAddressString(const nsACString& aPrefix,
+                                     unsigned long aPostfixLength,
+                                     nsACString& aAddress);
+
 private:
   void DispatchError(BluetoothResultHandler* aRes, BluetoothStatus aStatus);
 
-  nsAutoPtr<BluetoothDaemonChannel> mCmdChannel;
-  nsAutoPtr<BluetoothDaemonChannel> mNtfChannel;
+  nsCString mListenSocketName;
+  nsRefPtr<BluetoothDaemonListenSocket> mListenSocket;
+  nsRefPtr<BluetoothDaemonChannel> mCmdChannel;
+  nsRefPtr<BluetoothDaemonChannel> mNtfChannel;
   nsAutoPtr<BluetoothDaemonProtocol> mProtocol;
 
   nsTArray<nsRefPtr<BluetoothResultHandler> > mResultHandlerQ;
 
   nsAutoPtr<BluetoothDaemonSocketInterface> mSocketInterface;
   nsAutoPtr<BluetoothDaemonHandsfreeInterface> mHandsfreeInterface;
   nsAutoPtr<BluetoothDaemonA2dpInterface> mA2dpInterface;
   nsAutoPtr<BluetoothDaemonAvrcpInterface> mAvrcpInterface;
--- a/dom/bluetooth2/bluedroid/BluetoothDaemonSocketInterface.cpp
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonSocketInterface.cpp
@@ -30,17 +30,17 @@ BluetoothDaemonSocketModule::ListenCmd(B
 
   nsAutoPtr<BluetoothDaemonPDU> pdu(new BluetoothDaemonPDU(
     SERVICE_ID, OPCODE_LISTEN, 0));
 
   nsresult rv = PackPDU(
     aType,
     PackConversion<nsAString, BluetoothServiceName>(aServiceName),
     PackArray<uint8_t>(aServiceUuid, 16),
-    PackConversion<int, uint16_t>(aChannel),
+    PackConversion<int, int32_t>(aChannel),
     SocketFlags(aEncrypt, aAuth), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
   rv = Send(pdu, aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
@@ -60,17 +60,17 @@ BluetoothDaemonSocketModule::ConnectCmd(
 
   nsAutoPtr<BluetoothDaemonPDU> pdu(new BluetoothDaemonPDU(
       SERVICE_ID, OPCODE_CONNECT, 0));
 
   nsresult rv = PackPDU(
     PackConversion<nsAString, BluetoothAddress>(aBdAddr),
     aType,
     PackArray<uint8_t>(aUuid, 16),
-    PackConversion<int, int16_t>(aChannel),
+    PackConversion<int, int32_t>(aChannel),
     SocketFlags(aEncrypt, aAuth), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
   rv = Send(pdu, aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
--- a/dom/bluetooth2/moz.build
+++ b/dom/bluetooth2/moz.build
@@ -84,16 +84,18 @@ if CONFIG['MOZ_B2G_BT']:
                 SOURCES += [
                     'bluedroid/hfp-fallback/BluetoothHfpManager.cpp',
                 ]
                 LOCAL_INCLUDES += [
                     'bluedroid/hfp-fallback',
                 ]
 
             DEFINES['MOZ_B2G_BT_BLUEDROID'] = True
+            if CONFIG['MOZ_B2G_BT_DAEMON']:
+                DEFINES['MOZ_B2G_BT_DAEMON'] = True
     elif CONFIG['MOZ_ENABLE_DBUS']:
         CFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
         CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
         CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
         CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
         SOURCES += [
             'bluez/BluetoothDBusService.cpp',
             'bluez/BluetoothHfpManager.cpp',
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -130,16 +130,19 @@ if CONFIG['MOZ_PAY']:
     DIRS += ['payment']
 
 if CONFIG['MOZ_GAMEPAD']:
     DIRS += ['gamepad']
 
 if CONFIG['MOZ_NFC']:
     DIRS += ['nfc']
 
+if CONFIG['MOZ_SECUREELEMENT']:
+    DIRS += ['secureelement']
+
 if CONFIG['MOZ_B2G']:
     DIRS += [
         'downloads',
         'mobileid',
         'engineeringmode'
     ]
 
 if CONFIG['MOZ_B2G_BT_API_V2']:
new file mode 100644
--- /dev/null
+++ b/dom/secureelement/DOMSecureElement.js
@@ -0,0 +1,566 @@
+/* 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/. */
+
+/* Copyright © 2014, Deutsche Telekom, Inc. */
+
+"use strict";
+
+/* globals dump, Components, XPCOMUtils, DOMRequestIpcHelper, cpmm, SE  */
+
+const DEBUG = false;
+function debug(s) {
+  if (DEBUG) {
+    dump("-*- SecureElement DOM: " + s + "\n");
+  }
+}
+
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsISyncMessageSender");
+
+XPCOMUtils.defineLazyGetter(this, "SE", function() {
+  let obj = {};
+  Cu.import("resource://gre/modules/se_consts.js", obj);
+  return obj;
+});
+
+function PromiseHelpersSubclass(win) {
+  this._window = win;
+}
+
+PromiseHelpersSubclass.prototype = {
+  __proto__: DOMRequestIpcHelper.prototype,
+
+  _window: null,
+
+  _context: [],
+
+  createSEPromise: function createSEPromise(callback, /* optional */ ctx) {
+    let ctxCallback = (resolverId) => {
+      if (ctx) {
+        this._context[resolverId] = ctx;
+      }
+
+      callback(resolverId);
+    };
+
+    return this.createPromise((resolve, reject) => {
+      let resolverId = this.getPromiseResolverId({
+        resolve: resolve,
+        reject: reject
+      });
+      ctxCallback(resolverId);
+    });
+  },
+
+  takePromise: function takePromise(resolverId) {
+    let resolver = this.takePromiseResolver(resolverId);
+    if (!resolver) {
+      return;
+    }
+
+    // Get the context associated with this resolverId
+    let context = this._context[resolverId];
+    delete this._context[resolverId];
+
+    return {resolver: resolver, context: context};
+  },
+
+  rejectWithSEError: function rejectWithSEError(reason) {
+    return this.createSEPromise((resolverId) => {
+      debug("rejectWithSEError : " + reason);
+      this.takePromiseResolver(resolverId).reject(new Error(reason));
+    });
+  }
+};
+
+// Helper wrapper class to do promises related chores
+let PromiseHelpers;
+
+/**
+ * Instance of 'SEReaderImpl' class is the connector to a secure element.
+ * A reader may or may not have a secure element present, since some
+ * secure elements are removable in nature (eg:- 'uicc'). These
+ * Readers can be physical devices or virtual devices.
+ */
+function SEReaderImpl() {}
+
+SEReaderImpl.prototype = {
+  _window: null,
+
+  _sessions: [],
+
+  type: null,
+
+  classID: Components.ID("{1c7bdba3-cd35-4f8b-a546-55b3232457d5}"),
+  contractID: "@mozilla.org/secureelement/reader;1",
+  QueryInterface: XPCOMUtils.generateQI([]),
+
+  // Chrome-only function
+  onSessionClose: function onSessionClose(sessionCtx) {
+    let index = this._sessions.indexOf(sessionCtx);
+    if (index != -1) {
+      this._sessions.splice(index, 1);
+    }
+  },
+
+  initialize: function initialize(win, type) {
+    this._window = win;
+    this.type = type;
+  },
+
+  openSession: function openSession() {
+    return PromiseHelpers.createSEPromise((resolverId) => {
+      let chromeObj = new SESessionImpl();
+      chromeObj.initialize(this._window, this);
+      let contentObj = this._window.SESession._create(this._window, chromeObj);
+      this._sessions.push(contentObj);
+      PromiseHelpers.takePromiseResolver(resolverId).resolve(contentObj);
+    });
+  },
+
+  closeAll: function closeAll() {
+    return PromiseHelpers.createSEPromise((resolverId) => {
+      let promises = [];
+      for (let session of this._sessions) {
+        if (!session.isClosed) {
+          promises.push(session.closeAll());
+        }
+      }
+
+      let resolver = PromiseHelpers.takePromiseResolver(resolverId);
+      // Wait till all the promises are resolved
+      Promise.all(promises).then(() => {
+        this._sessions = [];
+        resolver.resolve();
+      }, (reason) => {
+        resolver.reject(new Error(SE.ERROR_BADSTATE +
+          " Unable to close all channels associated with this reader"));
+      });
+    });
+  },
+
+  get isSEPresent() {
+    // TODO: Bug 1119152 - Implement new idl with interfaces to detect
+    //                     secureelement state changes.
+    return true;
+  }
+};
+
+/**
+ * Instance of 'SESessionImpl' object represent a connection session
+ * to one of the secure elements available on the device.
+ * These objects can be used to get a communication channel with an application
+ * hosted by the Secure Element.
+ */
+function SESessionImpl() {}
+
+SESessionImpl.prototype = {
+  _window: null,
+
+  _channels: [],
+
+  _isClosed: false,
+
+  _reader: null,
+
+  classID: Components.ID("{2b1809f8-17bd-4947-abd7-bdef1498561c}"),
+  contractID: "@mozilla.org/secureelement/session;1",
+  QueryInterface: XPCOMUtils.generateQI([]),
+
+  // Private function
+  _checkClosed: function _checkClosed() {
+    if (this._isClosed) {
+      throw new Error(SE.ERROR_BADSTATE + " Session Already Closed!");
+    }
+  },
+
+  // Chrome-only function
+  onChannelOpen: function onChannelOpen(channelCtx) {
+    this._channels.push(channelCtx);
+  },
+
+  // Chrome-only function
+  onChannelClose: function onChannelClose(channelCtx) {
+    let index = this._channels.indexOf(channelCtx);
+    if (index != -1) {
+      this._channels.splice(index, 1);
+    }
+  },
+
+  initialize: function initialize(win, readerCtx) {
+    this._window = win;
+    this._reader = readerCtx;
+  },
+
+  openLogicalChannel: function openLogicalChannel(aid) {
+    this._checkClosed();
+
+    let aidLen = aid ? aid.length : 0;
+    if (aidLen < SE.MIN_AID_LEN || aidLen > SE.MAX_AID_LEN) {
+      return PromiseHelpers.rejectWithSEError(SE.ERROR_GENERIC +
+             " Invalid AID length - " + aidLen);
+    }
+
+    return PromiseHelpers.createSEPromise((resolverId) => {
+      /**
+       * @params for 'SE:OpenChannel'
+       *
+       * resolverId  : ID that identifies this IPC request.
+       * aid         : AID that identifies the applet on SecureElement
+       * type        : Reader type ('uicc' / 'eSE')
+       * appId       : Current appId obtained from 'Principal' obj
+       */
+      cpmm.sendAsyncMessage("SE:OpenChannel", {
+        resolverId: resolverId,
+        aid: aid,
+        type: this.reader.type,
+        appId: this._window.document.nodePrincipal.appId
+      });
+    }, this);
+  },
+
+  closeAll: function closeAll() {
+    this._checkClosed();
+
+    return PromiseHelpers.createSEPromise((resolverId) => {
+      let promises = [];
+      for (let channel of this._channels) {
+        if (!channel.isClosed) {
+          promises.push(channel.close());
+        }
+      }
+
+      let resolver = PromiseHelpers.takePromiseResolver(resolverId);
+      Promise.all(promises).then(() => {
+        this._isClosed = true;
+        this._channels = [];
+        // Notify parent of this session instance's closure, so that its
+        // instance entry can be removed from the parent as well.
+        this._reader.onSessionClose(this.__DOM_IMPL__);
+        resolver.resolve();
+      }, (reason) => {
+        resolver.reject(new Error(SE.ERROR_BADSTATE +
+          " Unable to close all channels associated with this session"));
+      });
+    });
+  },
+
+  get reader() {
+    return this._reader.__DOM_IMPL__;
+  },
+
+  get isClosed() {
+    return this._isClosed;
+  },
+
+  set isClosed(isClosed) {
+    this._isClosed = isClosed;
+  }
+};
+
+/**
+ * Instance of 'SEChannelImpl' object represent an ISO/IEC 7816-4 specification
+ * channel opened to a secure element. It can be either a logical channel
+ * or basic channel.
+ */
+function SEChannelImpl() {}
+
+SEChannelImpl.prototype = {
+  _window: null,
+
+  _channelToken: null,
+
+  _isClosed: false,
+
+  _session: null,
+
+  openResponse: [],
+
+  type: null,
+
+  classID: Components.ID("{181ebcf4-5164-4e28-99f2-877ec6fa83b9}"),
+  contractID: "@mozilla.org/secureelement/channel;1",
+  QueryInterface: XPCOMUtils.generateQI([]),
+
+  _checkClosed: function _checkClosed() {
+    if (this._isClosed) {
+      throw new Error(SE.ERROR_BADSTATE + " Channel Already Closed!");
+    }
+  },
+
+  // Chrome-only function
+  onClose: function onClose() {
+    this._isClosed = true;
+    // Notify the parent
+    this._session.onChannelClose(this.__DOM_IMPL__);
+  },
+
+  initialize: function initialize(win, channelToken, isBasicChannel,
+                                  openResponse, sessionCtx) {
+    this._window = win;
+    // Update the 'channel token' that identifies and represents this
+    // instance of the object
+    this._channelToken = channelToken;
+    // Update 'session' obj
+    this._session = sessionCtx;
+    this.openResponse = Cu.cloneInto(new Uint8Array(openResponse), win);
+    this.type = isBasicChannel ? "basic" : "logical";
+  },
+
+  transmit: function transmit(command) {
+    // TODO remove this once it will be possible to have a non-optional dict
+    // in the WebIDL
+    if (!command) {
+      return PromiseHelpers.rejectWithSEError(SE.ERROR_GENERIC +
+        " SECommand dict must be defined");
+    }
+
+    this._checkClosed();
+
+    let dataLen = command.data ? command.data.length : 0;
+    if (dataLen > SE.MAX_APDU_LEN) {
+      return PromiseHelpers.rejectWithSEError(SE.ERROR_GENERIC +
+             " Command data length exceeds max limit - 255. " +
+             " Extended APDU is not supported!");
+    }
+
+    if ((command.cla & 0x80 === 0) && ((command.cla & 0x60) !== 0x20)) {
+      if (command.ins === SE.INS_MANAGE_CHANNEL) {
+        return PromiseHelpers.rejectWithSEError(SE.ERROR_SECURITY +
+               ", MANAGE CHANNEL command not permitted");
+      }
+      if ((command.ins === SE.INS_SELECT) && (command.p1 == 0x04)) {
+        // SELECT by DF Name (p1=04) is not allowed
+        return PromiseHelpers.rejectWithSEError(SE.ERROR_SECURITY +
+               ", SELECT command not permitted");
+      }
+      debug("Attempting to transmit an ISO command");
+    } else {
+      debug("Attempting to transmit GlobalPlatform command");
+    }
+
+    return PromiseHelpers.createSEPromise((resolverId) => {
+      /**
+       * @params for 'SE:TransmitAPDU'
+       *
+       * resolverId  : Id that identifies this IPC request.
+       * apdu        : Object containing APDU data
+       * channelToken: Token that identifies the current channel over which
+                       'c-apdu' is being sent.
+       * appId       : Current appId obtained from 'Principal' obj
+       */
+      cpmm.sendAsyncMessage("SE:TransmitAPDU", {
+        resolverId: resolverId,
+        apdu: command,
+        channelToken: this._channelToken,
+        appId: this._window.document.nodePrincipal.appId
+      });
+    }, this);
+  },
+
+  close: function close() {
+    this._checkClosed();
+
+    return PromiseHelpers.createSEPromise((resolverId) => {
+      /**
+       * @params for 'SE:CloseChannel'
+       *
+       * resolverId  : Id that identifies this IPC request.
+       * channelToken: Token that identifies the current channel over which
+                       'c-apdu' is being sent.
+       * appId       : Current appId obtained from 'Principal' obj
+       */
+      cpmm.sendAsyncMessage("SE:CloseChannel", {
+        resolverId: resolverId,
+        channelToken: this._channelToken,
+        appId: this._window.document.nodePrincipal.appId
+      });
+    }, this);
+  },
+
+  get session() {
+    return this._session.__DOM_IMPL__;
+  },
+
+  get isClosed() {
+    return this._isClosed;
+  },
+
+  set isClosed(isClosed) {
+    this._isClosed = isClosed;
+  }
+};
+
+function SEResponseImpl() {}
+
+SEResponseImpl.prototype = {
+  sw1: 0x00,
+
+  sw2: 0x00,
+
+  data: null,
+
+  _channel: null,
+
+  classID: Components.ID("{58bc6c7b-686c-47cc-8867-578a6ed23f4e}"),
+  contractID: "@mozilla.org/secureelement/response;1",
+  QueryInterface: XPCOMUtils.generateQI([]),
+
+  initialize: function initialize(sw1, sw2, response, channelCtx) {
+    // Update the status bytes
+    this.sw1 = sw1;
+    this.sw2 = sw2;
+    this.data = response ? response.slice(0) : null;
+    // Update the channel obj
+    this._channel = channelCtx;
+  },
+
+  get channel() {
+    return this._channel.__DOM_IMPL__;
+  }
+};
+
+/**
+ * SEManagerImpl
+ */
+function SEManagerImpl() {}
+
+SEManagerImpl.prototype = {
+  __proto__: DOMRequestIpcHelper.prototype,
+
+  _window: null,
+
+  classID: Components.ID("{4a8b6ec0-4674-11e4-916c-0800200c9a66}"),
+  contractID: "@mozilla.org/secureelement/manager;1",
+  QueryInterface: XPCOMUtils.generateQI([
+    Ci.nsIDOMGlobalPropertyInitializer,
+    Ci.nsISupportsWeakReference,
+    Ci.nsIObserver
+  ]),
+
+  init: function init(win) {
+    this._window = win;
+    PromiseHelpers = new PromiseHelpersSubclass(this._window);
+
+    // Add the messages to be listened to.
+    const messages = ["SE:GetSEReadersResolved",
+                      "SE:OpenChannelResolved",
+                      "SE:CloseChannelResolved",
+                      "SE:TransmitAPDUResolved",
+                      "SE:GetSEReadersRejected",
+                      "SE:OpenChannelRejected",
+                      "SE:CloseChannelRejected",
+                      "SE:TransmitAPDURejected"];
+
+    this.initDOMRequestHelper(win, messages);
+  },
+
+  // This function will be called from DOMRequestIPCHelper.
+  uninit: function uninit() {
+    // All requests that are still pending need to be invalidated
+    // because the context is no longer valid.
+    this.forEachPromiseResolver((k) => {
+      this.takePromiseResolver(k).reject("Window Context got destroyed!");
+    });
+    PromiseHelpers = null;
+    this._window = null;
+  },
+
+  getSEReaders: function getSEReaders() {
+    return PromiseHelpers.createSEPromise((resolverId) => {
+      /**
+       * @params for 'SE:GetSEReaders'
+       *
+       * resolverId  : Id that identifies this IPC request.
+       * appId       : Current appId obtained from 'Principal' obj
+       */
+      cpmm.sendAsyncMessage("SE:GetSEReaders", {
+        resolverId: resolverId,
+        appId: this._window.document.nodePrincipal.appId
+      });
+    });
+  },
+
+  receiveMessage: function receiveMessage(message) {
+    let result = message.data.result;
+    let chromeObj = null;
+    let contentObj = null;
+    let resolver = null;
+    let context = null;
+
+    let promiseResolver = PromiseHelpers.takePromise(result.resolverId);
+    if (promiseResolver) {
+      resolver = promiseResolver.resolver;
+      // This 'context' is the instance that originated this IPC message.
+      context = promiseResolver.context;
+    }
+
+    debug("receiveMessage(): " + message.name);
+    switch (message.name) {
+      case "SE:GetSEReadersResolved":
+        let readers = new this._window.Array();
+        for (let i = 0; i < result.readerTypes.length; i++) {
+          chromeObj = new SEReaderImpl();
+          chromeObj.initialize(this._window, result.readerTypes[i]);
+          contentObj = this._window.SEReader._create(this._window, chromeObj);
+          readers.push(contentObj);
+        }
+        resolver.resolve(readers);
+        break;
+      case "SE:OpenChannelResolved":
+        chromeObj = new SEChannelImpl();
+        chromeObj.initialize(this._window,
+                             result.channelToken,
+                             result.isBasicChannel,
+                             result.openResponse,
+                             context);
+        contentObj = this._window.SEChannel._create(this._window, chromeObj);
+        if (context) {
+          // Notify context's handler with SEChannel instance
+          context.onChannelOpen(contentObj);
+        }
+        resolver.resolve(contentObj);
+        break;
+      case "SE:TransmitAPDUResolved":
+        chromeObj = new SEResponseImpl();
+        chromeObj.initialize(result.sw1,
+                             result.sw2,
+                             result.response,
+                             context);
+        contentObj = this._window.SEResponse._create(this._window, chromeObj);
+        resolver.resolve(contentObj);
+        break;
+      case "SE:CloseChannelResolved":
+        if (context) {
+          // Notify context's onClose handler
+          context.onClose();
+        }
+        resolver.resolve();
+        break;
+      case "SE:GetSEReadersRejected":
+      case "SE:OpenChannelRejected":
+      case "SE:CloseChannelRejected":
+      case "SE:TransmitAPDURejected":
+        let error = result.error || SE.ERROR_GENERIC;
+        resolver.reject(error);
+        break;
+      default:
+        debug("Could not find a handler for " + message.name);
+        resolver.reject();
+        break;
+    }
+  }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([
+  SEResponseImpl, SEChannelImpl, SESessionImpl, SEReaderImpl, SEManagerImpl
+]);
new file mode 100644
--- /dev/null
+++ b/dom/secureelement/DOMSecureElement.manifest
@@ -0,0 +1,21 @@
+component {4a8b6ec0-4674-11e4-916c-0800200c9a66} DOMSecureElement.js
+contract @mozilla.org/secureelement/manager;1 {4a8b6ec0-4674-11e4-916c-0800200c9a66}
+
+component {1c7bdba3-cd35-4f8b-a546-55b3232457d5} DOMSecureElement.js
+contract @mozilla.org/secureelement/reader;1 {1c7bdba3-cd35-4f8b-a546-55b3232457d5}
+
+component {2b1809f8-17bd-4947-abd7-bdef1498561c} DOMSecureElement.js
+contract @mozilla.org/secureelement/session;1 {2b1809f8-17bd-4947-abd7-bdef1498561c}
+
+component {181ebcf4-5164-4e28-99f2-877ec6fa83b9} DOMSecureElement.js
+contract @mozilla.org/secureelement/channel;1 {181ebcf4-5164-4e28-99f2-877ec6fa83b9}
+
+# component {cb8ccb1c-0e99-4a62-bf7d-11acc13848e0} DOMSecureElement.js
+# contract @mozilla.org/secureelement/command;1 {cb8ccb1c-0e99-4a62-bf7d-11acc13848e0}
+
+component {58bc6c7b-686c-47cc-8867-578a6ed23f4e} DOMSecureElement.js
+contract @mozilla.org/secureelement/response;1 {58bc6c7b-686c-47cc-8867-578a6ed23f4e}
+
+
+
+
new file mode 100644
--- /dev/null
+++ b/dom/secureelement/SEUtils.jsm
@@ -0,0 +1,55 @@
+/* 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/. */
+
+/* Copyright © 2015, Deutsche Telekom, Inc. */
+
+"use strict";
+
+this.SEUtils = {
+  byteArrayToHexString: function byteArrayToHexString(array) {
+    let hexStr = "";
+
+    let len = array ? array.length : 0;
+    for (let i = 0; i < len; i++) {
+      let hex = (array[i] & 0xff).toString(16);
+      hex = (hex.length === 1) ? "0" + hex : hex;
+      hexStr += hex;
+    }
+
+    return hexStr.toUpperCase();
+  },
+
+  hexStringToByteArray: function hexStringToByteArray(hexStr) {
+    if (typeof hexStr !== "string" || hexStr.length % 2 !== 0) {
+      return [];
+    }
+
+    let array = [];
+    for (let i = 0, len = hexStr.length; i < len; i += 2) {
+      array.push(parseInt(hexStr.substr(i, 2), 16));
+    }
+
+    return array;
+  },
+
+  arraysEqual: function arraysEqual(a1, a2) {
+    if (!a1 || !a2) {
+      return false;
+    }
+
+    if (a1.length !== a2.length) {
+      return false;
+    }
+
+    for (let i = 0, len = a1.length; i < len; i++) {
+      if (a1[i] !== a2[i]) {
+        return false;
+      }
+    }
+
+    return true;
+  },
+};
+
+this.EXPORTED_SYMBOLS = ["SEUtils"];
new file mode 100644
--- /dev/null
+++ b/dom/secureelement/gonk/SecureElement.js
@@ -0,0 +1,466 @@
+/* Copyright 2012 Mozilla Foundation and Mozilla contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Copyright © 2014, Deutsche Telekom, Inc. */
+
+"use strict";
+
+/* globals dump, Components, XPCOMUtils, SE, Services, UiccConnector,
+   SEUtils, ppmm, gMap, UUIDGenerator */
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/systemlibs.js");
+
+XPCOMUtils.defineLazyGetter(this, "SE", () => {
+  let obj = {};
+  Cu.import("resource://gre/modules/se_consts.js", obj);
+  return obj;
+});
+
+// set to true in se_consts.js to see debug messages
+let DEBUG = SE.DEBUG_SE;
+function debug(s) {
+  if (DEBUG) {
+    dump("-*- SecureElement: " + s + "\n");
+  }
+}
+
+const SE_IPC_SECUREELEMENT_MSG_NAMES = [
+  "SE:GetSEReaders",
+  "SE:OpenChannel",
+  "SE:CloseChannel",
+  "SE:TransmitAPDU"
+];
+
+const SECUREELEMENTMANAGER_CONTRACTID =
+  "@mozilla.org/secureelement/parent-manager;1";
+const SECUREELEMENTMANAGER_CID =
+  Components.ID("{48f4e650-28d2-11e4-8c21-0800200c9a66}");
+const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
+
+XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
+                                   "@mozilla.org/parentprocessmessagemanager;1",
+                                   "nsIMessageBroadcaster");
+
+XPCOMUtils.defineLazyServiceGetter(this, "UUIDGenerator",
+                                   "@mozilla.org/uuid-generator;1",
+                                   "nsIUUIDGenerator");
+
+XPCOMUtils.defineLazyModuleGetter(this, "SEUtils",
+                                  "resource://gre/modules/SEUtils.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "UiccConnector", () => {
+  let uiccClass = Cc["@mozilla.org/secureelement/connector/uicc;1"];
+  return uiccClass ? uiccClass.getService(Ci.nsISecureElementConnector) : null;
+});
+
+function getConnector(type) {
+  switch (type) {
+    case SE.TYPE_UICC:
+      return UiccConnector;
+    case SE.TYPE_ESE:
+    default:
+      debug("Unsupported SEConnector : " + type);
+      return null;
+  }
+}
+
+/**
+ * 'gMap' is a nested dictionary object that manages all the information
+ * pertaining to channels for a given application (appId). It manages the
+ * relationship between given application and its opened channels.
+ */
+XPCOMUtils.defineLazyGetter(this, "gMap", function() {
+  return {
+    // example structure of AppInfoMap
+    // {
+    //   "appId1": {
+    //     target: target1,
+    //     readerType: ["uicc", "eSE"],
+    //     channels: {
+    //       "channelToken1": {
+    //         seType: "uicc",
+    //         aid: "aid1",
+    //         channelNumber: 1
+    //       },
+    //       "channelToken2": { ... }
+    //     }
+    //   },
+    //  "appId2": { ... }
+    // }
+    appInfoMap: {},
+
+    registerSecureElementTarget: function(appId, readerTypes, target) {
+      if (this.isAppIdRegistered(appId)) {
+        debug("AppId: " + appId + "already registered");
+        return;
+      }
+
+      this.appInfoMap[appId] = {
+        target: target,
+        readerTypes: readerTypes,
+        channels: {}
+      };
+
+      debug("Registered a new SE target " + appId);
+    },
+
+    unregisterSecureElementTarget: function(target) {
+      let appId = Object.keys(this.appInfoMap).find((id) => {
+        return this.appInfoMap[id].target === target;
+      });
+
+      if (!appId) {
+        return;
+      }
+
+      debug("Unregistered SE Target for AppId: " + appId);
+      delete this.appInfoMap[appId];
+    },
+
+    isAppIdRegistered: function(appId) {
+      return this.appInfoMap[appId] !== undefined;
+    },
+
+    getChannelCountByAppIdType: function(appId, type) {
+      return Object.keys(this.appInfoMap[appId].channels)
+                   .reduce((cnt, ch) => ch.type === type ? ++cnt : cnt, 0);
+    },
+
+    // Add channel to the appId. Upon successfully adding the entry
+    // this function will return the 'token'
+    addChannel: function(appId, type, aid, channelNumber) {
+      let token = UUIDGenerator.generateUUID().toString();
+      this.appInfoMap[appId].channels[token] = {
+        seType: type,
+        aid: aid,
+        channelNumber: channelNumber
+      };
+      return token;
+    },
+
+    removeChannel: function(appId, channelToken) {
+      if (this.appInfoMap[appId].channels[channelToken]) {
+        debug("Deleting channel with token : " + channelToken);
+        delete this.appInfoMap[appId].channels[channelToken];
+      }
+    },
+
+    getChannel: function(appId, channelToken) {
+      if (!this.appInfoMap[appId].channels[channelToken]) {
+        return null;
+      }
+
+      return this.appInfoMap[appId].channels[channelToken];
+    },
+
+    getChannelsByTarget: function(target) {
+      let appId = Object.keys(this.appInfoMap).find((id) => {
+        return this.appInfoMap[id].target === target;
+      });
+
+      if (!appId) {
+        return [];
+      }
+
+      return Object.keys(this.appInfoMap[appId].channels)
+                   .map(token => this.appInfoMap[appId].channels[token]);
+    },
+  };
+});
+
+/**
+ * 'SecureElementManager' is the main object that handles IPC messages from
+ * child process. It interacts with other objects such as 'gMap' & 'Connector
+ * instances (UiccConnector, eSEConnector)' to perform various
+ * SE-related (open,close,transmit) operations.
+ */
+function SecureElementManager() {
+  this._registerMessageListeners();
+  Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
+}
+
+SecureElementManager.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([
+    Ci.nsIMessageListener,
+    Ci.nsIObserver]),
+  classID: SECUREELEMENTMANAGER_CID,
+  classInfo: XPCOMUtils.generateCI({
+    classID:          SECUREELEMENTMANAGER_CID,
+    classDescription: "SecureElementManager",
+    interfaces:       [Ci.nsIMessageListener,
+                       Ci.nsIObserver]
+  }),
+
+  _shutdown: function() {
+    this.secureelement = null;
+    Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
+    this._unregisterMessageListeners();
+  },
+
+  _registerMessageListeners: function() {
+    ppmm.addMessageListener("child-process-shutdown", this);
+    for (let msgname of SE_IPC_SECUREELEMENT_MSG_NAMES) {
+      ppmm.addMessageListener(msgname, this);
+    }
+  },
+
+  _unregisterMessageListeners: function() {
+    ppmm.removeMessageListener("child-process-shutdown", this);
+    for (let msgname of SE_IPC_SECUREELEMENT_MSG_NAMES) {
+      ppmm.removeMessageListener(msgname, this);
+    }
+    ppmm = null;
+  },
+
+  _getAvailableReaderTypes: function() {
+    let readerTypes = [];
+    // TODO 1: Bug 1118096 - Add IDL so that other sub-systems such as RIL ,
+    // NFC can implement it.
+    // TODO 2: Bug 1118097 - According to OpenMobile spec, the reader names
+    // should support slot based naming convention.
+    // i;e; Instead of returning 'uicc', return 'uicc<slot#>'.
+
+    if (UiccConnector) {
+      readerTypes.push(SE.TYPE_UICC);
+    }
+
+    return readerTypes;
+  },
+
+  _canOpenChannel: function(appId, type) {
+    let opened = gMap.getChannelCountByAppIdType(appId, type);
+    let limit = SE.MAX_CHANNELS_ALLOWED_PER_SESSION;
+    // UICC basic channel is not accessible see comment in se_consts.js
+    limit = type === SE.TYPE_UICC ? limit - 1 : limit;
+    return opened < limit;
+  },
+
+  _handleOpenChannel: function(msg, callback) {
+    if (!this._canOpenChannel(msg.appId, msg.type)) {
+      debug("Max channels per session exceed");
+      callback({ error: SE.ERROR_GENERIC });
+      return;
+    }
+
+    // TODO: Bug 1118098  - Integrate with ACE module
+    let connector = getConnector(msg.type);
+    if (!connector) {
+      debug("No SE connector available");
+      callback({ error: SE.ERROR_NOTPRESENT });
+      return;
+    }
+
+    connector.openChannel(SEUtils.byteArrayToHexString(msg.aid), {
+      notifyOpenChannelSuccess: (channelNumber, openResponse) => {
+        // Add the new 'channel' to the map upon success
+        let channelToken =
+          gMap.addChannel(msg.appId, msg.type, msg.aid, channelNumber);
+        if (channelToken) {
+          callback({
+            error: SE.ERROR_NONE,
+            channelToken: channelToken,
+            isBasicChannel: (channelNumber === SE.BASIC_CHANNEL),
+            openResponse: SEUtils.hexStringToByteArray(openResponse)
+          });
+        } else {
+          callback({ error: SE.ERROR_GENERIC });
+        }
+      },
+
+      notifyError: (reason) => {
+        debug("Failed to open the channel to AID : " +
+               SEUtils.byteArrayToHexString(msg.aid) +
+               ", Rejected with Reason : " + reason);
+        callback({ error: SE.ERROR_GENERIC, reason: reason, response: [] });
+      }
+    });
+  },
+
+  _handleTransmit: function(msg, callback) {
+    let channel = gMap.getChannel(msg.appId, msg.channelToken);
+    if (!channel) {
+      debug("Invalid token:" + msg.channelToken + ", appId: " + msg.appId);
+      callback({ error: SE.ERROR_GENERIC });
+      return;
+    }
+
+    let connector = getConnector(channel.seType);
+    if (!connector) {
+      debug("No SE connector available");
+      callback({ error: SE.ERROR_NOTPRESENT });
+      return;
+    }
+
+    connector.exchangeAPDU(channel.channelNumber, msg.apdu.cla, msg.apdu.ins,
+                           msg.apdu.p1, msg.apdu.p2,
+                           SEUtils.byteArrayToHexString(msg.apdu.data),
+                           msg.apdu.le, {
+      notifyExchangeAPDUResponse: (sw1, sw2, response) => {
+        callback({
+          error: SE.ERROR_NONE,
+          sw1: sw1,
+          sw2: sw2,
+          response: SEUtils.hexStringToByteArray(response)
+        });
+      },
+
+      notifyError: (reason) => {
+        debug("Transmit failed, rejected with Reason : " + reason);
+        callback({ error: SE.ERROR_INVALIDAPPLICATION, reason: reason });
+      }
+    });
+  },
+
+  _handleCloseChannel: function(msg, callback) {
+    let channel = gMap.getChannel(msg.appId, msg.channelToken);
+    if (!channel) {
+      debug("Invalid token:" + msg.channelToken + ", appId:" + msg.appId);
+      callback({ error: SE.ERROR_GENERIC });
+      return;
+    }
+
+    let connector = getConnector(channel.seType);
+    if (!connector) {
+      debug("No SE connector available");
+      callback({ error: SE.ERROR_NOTPRESENT });
+      return;
+    }
+
+    connector.closeChannel(channel.channelNumber, {
+      notifyCloseChannelSuccess: () => {
+        gMap.removeChannel(msg.appId, msg.channelToken);
+        callback({ error: SE.ERROR_NONE });
+      },
+
+      notifyError: (reason) => {
+        debug("Failed to close channel with token: " + msg.channelToken +
+              ", reason: "+ reason);
+        callback({ error: SE.ERROR_BADSTATE, reason: reason });
+      }
+    });
+  },
+
+  _handleGetSEReadersRequest: function(msg, target, callback) {
+    // TODO: Bug 1118101 Get supported readerTypes based on the permissions
+    // available for the given application.
+    let seReaderTypes = this._getAvailableReaderTypes();
+    gMap.registerSecureElementTarget(msg.appId, seReaderTypes, target);
+    callback({ readerTypes: seReaderTypes, error: SE.ERROR_NONE });
+  },
+
+  _handleChildProcessShutdown: function(target) {
+    let channels = gMap.getChannelsByTarget(target);
+
+    let createCb = (seType, channelNumber) => {
+      return {
+        notifyCloseChannelSuccess: () => {
+          debug("closed " + seType + ", channel " + channelNumber);
+        },
+
+        notifyError: (reason) => {
+          debug("Failed to close  " + seType + " channel " +
+                channelNumber + ", reason: " + reason);
+        }
+      };
+    };
+
+    channels.forEach((channel) => {
+      let connector = getConnector(channel.seType);
+      if (!connector) {
+        return;
+      }
+
+      connector.closeChannel(channel.channelNumber,
+                             createCb(channel.seType, channel.channelNumber));
+    });
+
+    gMap.unregisterSecureElementTarget(target);
+  },
+
+  _sendSEResponse: function(msg, result) {
+    let promiseStatus = (result.error === SE.ERROR_NONE) ? "Resolved" : "Rejected";
+    result.resolverId = msg.data.resolverId;
+    msg.target.sendAsyncMessage(msg.name + promiseStatus, {result: result});
+  },
+
+  _isValidMessage: function(msg) {
+    let appIdValid = gMap.isAppIdRegistered(msg.data.appId);
+    return msg.name === "SE:GetSEReaders" ? true : appIdValid;
+  },
+
+  /**
+   * nsIMessageListener interface methods.
+   */
+
+  receiveMessage: function(msg) {
+    DEBUG && debug("Received '" + msg.name + "' message from content process" +
+                   ": " + JSON.stringify(msg.data));
+
+    if (msg.name === "child-process-shutdown") {
+      this._handleChildProcessShutdown(msg.target);
+      return null;
+    }
+
+    if (SE_IPC_SECUREELEMENT_MSG_NAMES.indexOf(msg.name) !== -1) {
+      if (!msg.target.assertPermission("secureelement-manage")) {
+        debug("SecureElement message " + msg.name + " from a content process " +
+              "with no 'secureelement-manage' privileges.");
+        return null;
+      }
+    } else {
+      debug("Ignoring unknown message type: " + msg.name);
+      return null;
+    }
+
+    let callback = (result) => this._sendSEResponse(msg, result);
+    if (!this._isValidMessage(msg)) {
+      debug("Message not valid");
+      callback({ error: SE.ERROR_GENERIC });
+      return null;
+    }
+
+    switch (msg.name) {
+      case "SE:GetSEReaders":
+        this._handleGetSEReadersRequest(msg.data, msg.target, callback);
+        break;
+      case "SE:OpenChannel":
+        this._handleOpenChannel(msg.data, callback);
+        break;
+      case "SE:CloseChannel":
+        this._handleCloseChannel(msg.data, callback);
+        break;
+      case "SE:TransmitAPDU":
+        this._handleTransmit(msg.data, callback);
+        break;
+    }
+    return null;
+  },
+
+  /**
+   * nsIObserver interface methods.
+   */
+
+  observe: function(subject, topic, data) {
+    if (topic === NS_XPCOM_SHUTDOWN_OBSERVER_ID) {
+      this._shutdown();
+    }
+  }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SecureElementManager]);
new file mode 100644
--- /dev/null
+++ b/dom/secureelement/gonk/SecureElement.manifest
@@ -0,0 +1,18 @@
+# Copyright 2012 Mozilla Foundation and Mozilla contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# SecureElementManager
+component {48f4e650-28d2-11e4-8c21-0800200c9a66} SecureElement.js
+contract @mozilla.org/secureelement/parent-manager;1 {48f4e650-28d2-11e4-8c21-0800200c9a66}
+category profile-after-change SecureElementManager @mozilla.org/secureelement/parent-manager;1
new file mode 100644
--- /dev/null
+++ b/dom/secureelement/gonk/UiccConnector.js
@@ -0,0 +1,326 @@
+/* Copyright 2012 Mozilla Foundation and Mozilla contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Copyright © 2014, Deutsche Telekom, Inc. */
+
+"use strict";
+
+/* globals Components, XPCOMUtils, SE, dump, libcutils, Services,
+   iccProvider, SEUtils */
+
+const { interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/systemlibs.js");
+
+XPCOMUtils.defineLazyGetter(this, "SE", function() {
+  let obj = {};
+  Cu.import("resource://gre/modules/se_consts.js", obj);
+  return obj;
+});
+
+// set to true in se_consts.js to see debug messages
+let DEBUG = SE.DEBUG_CONNECTOR;
+function debug(s) {
+  if (DEBUG) {
+    dump("-*- UiccConnector: " + s + "\n");
+  }
+}
+
+XPCOMUtils.defineLazyModuleGetter(this, "SEUtils",
+                                  "resource://gre/modules/SEUtils.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "iccProvider",
+                                   "@mozilla.org/ril/content-helper;1",
+                                   "nsIIccProvider");
+
+const UICCCONNECTOR_CONTRACTID =
+  "@mozilla.org/secureelement/connector/uicc;1";
+const UICCCONNECTOR_CID =
+  Components.ID("{8e040e5d-c8c3-4c1b-ac82-c00d25d8c4a4}");
+const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
+
+// TODO: Bug 1118099  - Add multi-sim support.
+// In the Multi-sim, there is more than one client.
+// For now, use default clientID as 0. Ideally, SE parent process would like to
+// know which clients (uicc slot) are connected to CLF over SWP interface.
+const PREFERRED_UICC_CLIENTID =
+  libcutils.property_get("ro.moz.se.def_client_id", "0");
+
+/**
+ * 'UiccConnector' object is a wrapper over iccProvider's channel management
+ * related interfaces that implements nsISecureElementConnector interface.
+ */
+function UiccConnector() {
+  this._init();
+}
+
+UiccConnector.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISecureElementConnector]),
+  classID: UICCCONNECTOR_CID,
+  classInfo: XPCOMUtils.generateCI({
+    classID: UICCCONNECTOR_CID,
+    contractID: UICCCONNECTOR_CONTRACTID,
+    classDescription: "UiccConnector",
+    interfaces: [Ci.nsISecureElementConnector,
+                 Ci.nsIIccListener,
+                 Ci.nsIObserver]
+  }),
+
+  _isPresent: false,
+
+  _init: function() {
+    Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
+    iccProvider.registerIccMsg(PREFERRED_UICC_CLIENTID, this);
+
+    // Update the state in order to avoid race condition.
+    // By this time, 'notifyCardStateChanged (with proper card state)'
+    // may have occurred already before this module initialization.
+    this._updatePresenceState();
+  },
+
+  _shutdown: function() {
+    Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
+    iccProvider.unregisterIccMsg(PREFERRED_UICC_CLIENTID, this);
+  },
+
+  _updatePresenceState: function() {
+    // Consider following Card states as not quite ready for performing
+    // IccChannel* related commands
+    let notReadyStates = [
+      "unknown",
+      "illegal",
+      "personalizationInProgress",
+      "permanentBlocked",
+    ];
+    let cardState = iccProvider.getCardState(PREFERRED_UICC_CLIENTID);
+    this._isPresent = cardState !== null &&
+                      notReadyStates.indexOf(cardState) == -1;
+  },
+
+  // See GP Spec, 11.1.4 Class Byte Coding
+  _setChannelToCLAByte: function(cla, channel) {
+    if (channel < SE.LOGICAL_CHANNEL_NUMBER_LIMIT) {
+      // b7 = 0 indicates the first interindustry class byte coding
+      cla = (cla & 0x9C) & 0xFF | channel;
+    } else if (channel < SE.SUPPLEMENTARY_LOGICAL_CHANNEL_NUMBER_LIMIT) {
+      // b7 = 1 indicates the further interindustry class byte coding
+      cla = (cla & 0xB0) & 0xFF | 0x40 | (channel - SE.LOGICAL_CHANNEL_NUMBER_LIMIT);
+    } else {
+      debug("Channel number must be within [0..19]");
+      return SE.ERROR_GENERIC;
+    }
+    return cla;
+  },
+
+  _doGetOpenResponse: function(channel, length, callback) {
+    // Le value is set. It means that this is a request for all available
+    // response bytes.
+    let cla = this._setChannelToCLAByte(SE.CLA_GET_RESPONSE, channel);
+    this.exchangeAPDU(channel, cla, SE.INS_GET_RESPONSE, 0x00, 0x00,
+                      null, length, {
+      notifyExchangeAPDUResponse: function(sw1, sw2, response) {
+        debug("GET Response : " + response);
+        if (callback) {
+          callback({
+            error: SE.ERROR_NONE,
+            sw1: sw1,
+            sw2: sw2,
+            response: response
+          });
+        }
+      },
+
+      notifyError: function(reason) {
+        debug("Failed to get open response: " +
+              ", Rejected with Reason : " + reason);
+        if (callback) {
+          callback({ error: SE.ERROR_INVALIDAPPLICATION, reason: reason });
+        }
+      }
+    });
+  },
+
+  _doIccExchangeAPDU: function(channel, cla, ins, p1, p2, p3,
+                               data, appendResp, callback) {
+    iccProvider.iccExchangeAPDU(PREFERRED_UICC_CLIENTID, channel, cla & 0xFC,
+                                ins, p1, p2, p3, data, {
+      notifyExchangeAPDUResponse: (sw1, sw2, response) => {
+        debug("sw1 : " + sw1 + ", sw2 : " + sw2 + ", response : " + response);
+
+        // According to ETSI TS 102 221 , Section 7.2.2.3.1,
+        // Enforce 'Procedure bytes' checks before notifying the callback.
+        // Note that 'Procedure bytes'are special cases.
+        // There is no need to handle '0x60' procedure byte as it implies
+        // no-action from SE stack perspective. This procedure byte is not
+        // notified to application layer.
+        if (sw1 === 0x6C) {
+          // Use the previous command header with length as second procedure
+          // byte (SW2) as received and repeat the procedure.
+
+          // Recursive! and Pass empty response '' as args, since '0x6C'
+          // procedure does not have to deal with appended responses.
+          this._doIccExchangeAPDU(channel, cla, ins, p1, p2,
+                                  sw2, data, "", callback);
+        } else if (sw1 === 0x61) {
+          // Since the terminal waited for a second procedure byte and
+          // received it (sw2), send a GET RESPONSE command header to the UICC
+          // with a maximum length of 'XX', where 'XX' is the value of the
+          // second procedure byte (SW2).
+
+          let claWithChannel = this._setChannelToCLAByte(SE.CLA_GET_RESPONSE,
+                                                         channel);
+
+          // Recursive, with GET RESPONSE bytes and '0x61' procedure IS interested
+          // in appended responses. Pass appended response and note that p3=sw2.
+          this._doIccExchangeAPDU(channel, claWithChannel, SE.INS_GET_RESPONSE,
+                                  0x00, 0x00, sw2, null,
+                                  (response ? response + appendResp : appendResp),
+                                  callback);
+        } else if (callback) {
+          callback.notifyExchangeAPDUResponse(sw1, sw2, response);
+        }
+      },
+
+      notifyError: (reason) => {
+        debug("Failed to trasmit C-APDU over the channel #  : " + channel +
+              ", Rejected with Reason : " + reason);
+        if (callback) {
+          callback.notifyError(reason);
+        }
+      }
+    });
+  },
+
+  /**
+   * nsISecureElementConnector interface methods.
+   */
+
+  /**
+   * Opens a channel on a default clientId
+   */
+  openChannel: function(aid, callback) {
+    if (!this._isPresent) {
+      callback.notifyError(SE.ERROR_NOTPRESENT);
+      return;
+    }
+
+    // TODO: Bug 1118106: Handle Resource management / leaks by persisting
+    // the newly opened channel in some persistent storage so that when this
+    // module gets restarted (say after opening a channel) in the event of
+    // some erroneous conditions such as gecko restart /, crash it can read
+    // the persistent storage to check if there are any held resources
+    // (opened channels) and close them.
+    iccProvider.iccOpenChannel(PREFERRED_UICC_CLIENTID, aid, {
+      notifyOpenChannelSuccess: (channel) => {
+        this._doGetOpenResponse(channel, 0x00, function(result) {
+          if (callback) {
+            callback.notifyOpenChannelSuccess(channel, result.response);
+          }
+        });
+      },
+
+      notifyError: (reason) => {
+        debug("Failed to open the channel to AID : " + aid +
+              ", Rejected with Reason : " + reason);
+        if (callback) {
+          callback.notifyError(reason);
+        }
+      }
+    });
+  },
+
+  /**
+   * Transmit the C-APDU (command) on default clientId.
+   */
+  exchangeAPDU: function(channel, cla, ins, p1, p2, data, le, callback) {
+    if (!this._isPresent) {
+      callback.notifyError(SE.ERROR_NOTPRESENT);
+      return;
+    }
+
+    if (data && data.length % 2 !== 0) {
+      callback.notifyError("Data should be a hex string with length % 2 === 0");
+      return;
+    }
+
+    cla = this._setChannelToCLAByte(cla, channel);
+    let lc = data ? data.length / 2 : 0;
+    let p3 = lc || le;
+
+    if (lc && (le !== -1)) {
+      data += SEUtils.byteArrayToHexString([le]);
+    }
+
+    // Pass empty response '' as args as we are not interested in appended
+    // responses yet!
+    debug("exchangeAPDU on Channel # " + channel);
+    this._doIccExchangeAPDU(channel, cla, ins, p1, p2, p3, data, "",
+                            callback);
+  },
+
+  /**
+   * Closes the channel on default clientId.
+   */
+  closeChannel: function(channel, callback) {
+    if (!this._isPresent) {
+      callback.notifyError(SE.ERROR_NOTPRESENT);
+      return;
+    }
+
+    iccProvider.iccCloseChannel(PREFERRED_UICC_CLIENTID, channel, {
+      notifyCloseChannelSuccess: function() {
+        debug("closeChannel successfully closed the channel # : " + channel);
+        if (callback) {
+          callback.notifyCloseChannelSuccess();
+        }
+      },
+
+      notifyError: function(reason) {
+        debug("Failed to close the channel #  : " + channel +
+              ", Rejected with Reason : " + reason);
+        if (callback) {
+          callback.notifyError(reason);
+        }
+      }
+    });
+  },
+
+  /**
+   * nsIIccListener interface methods.
+   */
+  notifyStkCommand: function() {},
+
+  notifyStkSessionEnd: function() {},
+
+  notifyIccInfoChanged: function() {},
+
+  notifyCardStateChanged: function() {
+    this._updatePresenceState();
+  },
+
+  /**
+   * nsIObserver interface methods.
+   */
+
+  observe: function(subject, topic, data) {
+    if (topic === NS_XPCOM_SHUTDOWN_OBSERVER_ID) {
+      this._shutdown();
+    }
+  }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([UiccConnector]);
new file mode 100644
--- /dev/null
+++ b/dom/secureelement/gonk/UiccConnector.manifest
@@ -0,0 +1,17 @@
+# Copyright 2012 Mozilla Foundation and Mozilla contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# UiccConnector
+component {8e040e5d-c8c3-4c1b-ac82-c00d25d8c4a4} UiccConnector.js
+contract @mozilla.org/secureelement/connector/uicc;1 {8e040e5d-c8c3-4c1b-ac82-c00d25d8c4a4}
new file mode 100644
--- /dev/null
+++ b/dom/secureelement/gonk/nsISecureElementConnector.idl
@@ -0,0 +1,104 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(1ff3f35a-1b6f-4e65-a89e-a363b8604cd7)]
+interface nsISEChannelCallback : nsISupports
+{
+  /**
+   * Callback function to notify on successfully opening a logical channel.
+   *
+   * @param channel
+   *        The Channel Number/Handle that is successfully opened.
+   * @param openResponse
+   *        Response from SE for OpenChannel operation.
+   */
+  void notifyOpenChannelSuccess(in long channel, in DOMString openResponse);
+
+  /**
+   * Callback function to notify on successfully closing the logical channel.
+   *
+   */
+  void notifyCloseChannelSuccess();
+
+  /**
+   * Callback function to notify the status of 'seExchangeAPDU' command.
+   *
+   * @param sw1
+   *        Response's First Status Byte
+   * @param sw2
+   *        Response's Second Status Byte
+   * @param data
+   *        Response's data
+   */
+  void notifyExchangeAPDUResponse(in octet sw1,
+                                  in octet sw2,
+                                  in DOMString data);
+
+  /**
+   * Callback function to notify error
+   *
+   * @param error
+   *        Error describing the reason for failure.
+   */
+  void notifyError(in DOMString error);
+};
+
+[scriptable, uuid(88e23684-0de3-4792-83a0-0eb67a6ca448)]
+interface nsISecureElementConnector : nsISupports
+{
+   /**
+    * Open a logical communication channel with the specific secure element type
+    *
+    * @param aid
+    *        Application Identifier of the Card Applet on the secure element.
+    * @param callback
+    *        callback to notify the result of the operation.
+    */
+    void openChannel(in DOMString aid,
+                     in nsISEChannelCallback callback);
+
+   /**
+    * Exchanges APDU channel with the specific secure element type
+    *
+    * @param channel
+    *        Channel on which C-APDU to be transmitted.
+    * @param cla
+             Class Byte.
+    * @param ins
+             Instruction Byte
+    * @param p1
+             Reference parameter first byte
+    * @param p2
+             Reference parameter second byte
+    *        Refer to 3G TS 31.101 , 10.2 'Command APDU Structure' for all the cases.
+    * @param data
+             Sequence of C-APDU data octets
+    * @param le [optional]
+    *        le is the length of expected response. If the response is not expected,
+             it should be explicitly set to -1.
+    * @param callback
+    *        callback to notify the result of the operation.
+    */
+    void exchangeAPDU(in long channel,
+                      in octet cla,
+                      in octet ins,
+                      in octet p1,
+                      in octet p2,
+                      in DOMString data,
+                      in short le,
+                      in nsISEChannelCallback callback);
+
+   /**
+    * Closes the logical communication channel to the specific secure element type
+    *
+    * @param channel
+    *        Channel to be closed.
+    * @param callback
+    *        callback to notify the result of the operation.
+    */
+   void closeChannel(in long channel,
+                     in nsISEChannelCallback callback);
+};
new file mode 100644
--- /dev/null
+++ b/dom/secureelement/gonk/se_consts.js
@@ -0,0 +1,66 @@
+/* Copyright 2012 Mozilla Foundation and Mozilla contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Copyright © 2014, Deutsche Telekom, Inc. */
+
+// Set to true to debug SecureElement (SE) stack
+this.DEBUG_ALL = false;
+
+// Set individually to debug specific layers
+this.DEBUG_CONNECTOR = DEBUG_ALL || false;
+this.DEBUG_SE = DEBUG_ALL || false ;
+
+// Maximun logical channels per session.
+// For 'uicc' SE type this value is 3, as opening a basic channel' : 0
+// is not allowed for security reasons. In such scenarios, possible
+// supplementary logical channels available are : [1, 2, or 3].
+// However,Other SE types may support upto max 4 (including '0').
+this.MAX_CHANNELS_ALLOWED_PER_SESSION = 4;
+
+this.BASIC_CHANNEL = 0;
+
+// According GPCardSpec 2.2
+this.MAX_APDU_LEN = 255; // including APDU header
+
+// CLA (1 byte) + INS (1 byte) + P1 (1 byte) + P2 (1 byte)
+this.APDU_HEADER_LEN = 4;
+
+this.LOGICAL_CHANNEL_NUMBER_LIMIT = 4;
+this.SUPPLEMENTARY_LOGICAL_CHANNEL_NUMBER_LIMIT = 20;
+
+this.MIN_AID_LEN = 5;
+this.MAX_AID_LEN = 16;
+
+this.CLA_GET_RESPONSE = 0x00;
+
+this.INS_SELECT = 0xA4;
+this.INS_MANAGE_CHANNEL = 0x70;
+this.INS_GET_RESPONSE = 0xC0;
+
+// Match the following errors with SecureElement.webidl's SEError enum values
+this.ERROR_NONE               = "";
+this.ERROR_SECURITY           = "SESecurityError";
+this.ERROR_IO                 = "SEIoError";
+this.ERROR_BADSTATE           = "SEBadStateError";
+this.ERROR_INVALIDCHANNEL     = "SEInvalidChannelError";
+this.ERROR_INVALIDAPPLICATION = "SEInvalidApplicationError";
+this.ERROR_GENERIC            = "SEGenericError";
+this.ERROR_NOTPRESENT         = "SENotPresentError";
+
+this.TYPE_UICC = "uicc";
+this.TYPE_ESE = "eSE";
+
+// Allow this file to be imported via Components.utils.import().
+this.EXPORTED_SYMBOLS = Object.keys(this);
new file mode 100644
--- /dev/null
+++ b/dom/secureelement/moz.build
@@ -0,0 +1,39 @@
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# Copyright © 2014 Deutsche Telekom, Inc.
+
+if CONFIG['MOZ_SECUREELEMENT']:
+    EXTRA_COMPONENTS += [
+        'DOMSecureElement.js',
+        'DOMSecureElement.manifest',
+    ]
+
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_SECUREELEMENT']:
+    EXTRA_COMPONENTS += [
+        'gonk/SecureElement.js',
+        'gonk/SecureElement.manifest',
+    ]
+    XPIDL_MODULE = 'dom_secureelement'
+    XPIDL_SOURCES += [
+        'gonk/nsISecureElementConnector.idl',
+    ]
+    EXTRA_JS_MODULES += [
+        'gonk/se_consts.js',
+        'SEUtils.jsm'
+    ]
+    XPCSHELL_TESTS_MANIFESTS += [
+        'tests/unit/xpcshell.ini'
+    ]
+    if CONFIG['MOZ_B2G_RIL']:
+        EXTRA_COMPONENTS += [
+            'gonk/UiccConnector.js',
+            'gonk/UiccConnector.manifest',
+        ]
+
+FAIL_ON_WARNINGS = True
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
new file mode 100644
--- /dev/null
+++ b/dom/secureelement/tests/unit/test_SEUtils.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/* globals run_next_test, add_test, ok, Components, SEUtils */
+/* exported run_test */
+
+Components.utils.import("resource://gre/modules/SEUtils.jsm");
+
+const VALID_HEX_STR = "0123456789ABCDEF";
+const VALID_BYTE_ARR = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF];
+
+function run_test() {
+  ok(!!SEUtils, "SEUtils should be available");
+  run_next_test();
+}
+
+add_test(function test_byteArrayToHexString() {
+  let hexStr = SEUtils.byteArrayToHexString(VALID_BYTE_ARR);
+  ok(hexStr === VALID_HEX_STR,
+     "should convert byte Array to uppercased hex string");
+
+  [[], null, undefined].forEach((input) => {
+    hexStr = SEUtils.byteArrayToHexString(input);
+    ok(hexStr === "", "invalid arg:" + input + " should return empty string");
+  });
+
+  run_next_test();
+});
+
+add_test(function test_hexStringToByteArray() {
+  let byteArr = SEUtils.hexStringToByteArray(VALID_HEX_STR);
+  ok(SEUtils.arraysEqual(byteArr, VALID_BYTE_ARR),
+     "should convert uppercased string to byte Array");
+
+  byteArr = SEUtils.hexStringToByteArray(VALID_HEX_STR.toLowerCase());
+  ok(SEUtils.arraysEqual(byteArr, VALID_BYTE_ARR),
+     "should convert lowercased string to byte Array");
+
+  ["", null, undefined, "123"].forEach((input) => {
+    byteArr = SEUtils.hexStringToByteArray(input);
+    ok(Array.isArray(byteArr) && byteArr.length === 0,
+       "invalid arg: " + input + " should be empty Array");
+  });
+
+  run_next_test();
+});
+
+add_test(function test_arraysEqual() {
+  ok(SEUtils.arraysEqual([1, 2, 3], [1, 2, 3]),
+     "should return true on equal Arrays");
+
+  [[1], [1, 2, 4], [3, 2, 1]].forEach((input) => {
+    ok(!SEUtils.arraysEqual([1, 2, 3], input),
+       "should return false when Arrays not equal");
+  });
+
+  [null, undefined].forEach((input) => {
+    ok(!SEUtils.arraysEqual([1, 2, 3], input),
+       "should return false when comparing Array with invalid argument");
+
+    ok(!SEUtils.arraysEqual(input, input),
+       "should return false when both args are invalid");
+  });
+
+  run_next_test();
+});
new file mode 100644
--- /dev/null
+++ b/dom/secureelement/tests/unit/xpcshell.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+head =
+tail =
+
+[test_SEUtils.js]
\ No newline at end of file
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -130,16 +130,17 @@ function RILContentHelper() {
       cardState: Ci.nsIIccProvider.CARD_STATE_UNKNOWN,
       iccInfo: null
     };
   }
 
   this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES);
   this._windowsMap = [];
   this._iccListeners = [];
+  this._iccChannelCallback = [];
 
   Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
 
   Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
 }
 
 RILContentHelper.prototype = {
   __proto__: DOMRequestIpcHelper.prototype,
@@ -588,16 +589,18 @@ RILContentHelper.prototype = {
 
     let index = listeners.indexOf(listener);
     if (index != -1) {
       listeners.splice(index, 1);
       if (DEBUG) debug("Unregistered listener: " + listener);
     }
   },
 
+  _iccChannelCallback: null,
+
   _addIccChannelCallback: function(requestId, channelCb) {
     let cbInterfaces = this._iccChannelCallback;
     if (!cbInterfaces[requestId] && channelCb) {
       cbInterfaces[requestId] = channelCb;
       return;
     }
 
     if (DEBUG) debug("Unable to add channelCbInterface for requestId : " + requestId);
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -526,20 +526,30 @@ XPCOMUtils.defineLazyGetter(this, "gRadi
       } else {
         _request = this._setRadioEnabledInternal.bind(this, message);
 
         // In 2G network, modem takes 35+ seconds to process deactivate data
         // call request if device has active voice call (please see bug 964974
         // for more details). Therefore we should hangup all active voice calls
         // first. And considering some DSDS architecture, toggling one radio may
         // toggle both, so we send hangUpAll to all clients.
-        for (let i = 0, N = _ril.numRadioInterfaces; i < N; ++i) {
-          let iface = _ril.getRadioInterface(i);
-          iface.workerMessenger.send("hangUpAll");
-        }
+        let hangUpCallback = {
+          QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyCallback]),
+          notifySuccess: function() {},
+          notifyError: function() {}
+        };
+
+        gTelephonyService.enumerateCalls({
+          QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
+          enumerateCallState: function(aInfo) {
+            gTelephonyService.hangUpCall(aInfo.clientId, aInfo.callIndex,
+                                         hangUpCallback);
+          },
+          enumerateCallStateComplete: function() {}
+        });
 
         // In some DSDS architecture with only one modem, toggling one radio may
         // toggle both. Therefore, for safely turning off, we should first
         // explicitly deactivate all data calls from all clients.
         this._deactivateDataCalls().then(() => {
           if (DEBUG) debug("RadioControl: deactivation done");
           this._executeRequest();
         });
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -1552,25 +1552,16 @@ RilObject.prototype = {
     let Buf = this.context.Buf;
     options.request = REQUEST_CDMA_FLASH;
     Buf.newParcel(options.request, options);
     Buf.writeString(options.featureStr || "");
     Buf.sendParcel();
   },
 
   /**
-   * Hang up all calls
-   */
-  hangUpAll: function() {
-    for (let callIndex in this.currentCalls) {
-      this.hangUpCall({callIndex: callIndex});
-    }
-  },
-
-  /**
    * Hang up the phone.
    *
    * @param callIndex
    *        Call index (1-based) as reported by REQUEST_GET_CURRENT_CALLS.
    */
   hangUpCall: function(options) {
     let call = this.currentCalls[options.callIndex];
     if (!call) {
--- a/dom/telephony/TelephonyCall.cpp
+++ b/dom/telephony/TelephonyCall.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TelephonyCall.h"
 #include "mozilla/dom/CallEvent.h"
 #include "mozilla/dom/TelephonyCallBinding.h"
 #include "mozilla/dom/telephony/TelephonyCallback.h"
 
 #include "mozilla/dom/DOMError.h"
+#include "nsPrintfCString.h"
 
 #include "Telephony.h"
 #include "TelephonyCallGroup.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::dom::telephony;
 using mozilla::ErrorResult;
 
@@ -64,52 +65,52 @@ TelephonyCall::WrapObject(JSContext* aCx
 
 void
 TelephonyCall::ChangeStateInternal(uint16_t aCallState, bool aFireEvents)
 {
   nsRefPtr<TelephonyCall> kungFuDeathGrip(this);
 
   nsString stateString;
   switch (aCallState) {
+    // These states are used internally to mark this call is currently being
+    // controlled, and we should block consecutive requests of the same type
+    // according to these states.
+    case nsITelephonyService::CALL_STATE_CONNECTING:
+    case nsITelephonyService::CALL_STATE_DISCONNECTING:
+    case nsITelephonyService::CALL_STATE_HOLDING:
+    case nsITelephonyService::CALL_STATE_RESUMING:
+      break;
+    // These states will be translated into literal strings which are used to
+    // show the current status of this call.
     case nsITelephonyService::CALL_STATE_DIALING:
       stateString.AssignLiteral("dialing");
       break;
     case nsITelephonyService::CALL_STATE_ALERTING:
       stateString.AssignLiteral("alerting");
       break;
-    case nsITelephonyService::CALL_STATE_CONNECTING:
-      stateString.AssignLiteral("connecting");
-      break;
     case nsITelephonyService::CALL_STATE_CONNECTED:
       stateString.AssignLiteral("connected");
       break;
-    case nsITelephonyService::CALL_STATE_HOLDING:
-      stateString.AssignLiteral("holding");
-      break;
     case nsITelephonyService::CALL_STATE_HELD:
       stateString.AssignLiteral("held");
       break;
-    case nsITelephonyService::CALL_STATE_RESUMING:
-      stateString.AssignLiteral("resuming");
-      break;
-    case nsITelephonyService::CALL_STATE_DISCONNECTING:
-      stateString.AssignLiteral("disconnecting");
-      break;
     case nsITelephonyService::CALL_STATE_DISCONNECTED:
       stateString.AssignLiteral("disconnected");
       break;
     case nsITelephonyService::CALL_STATE_INCOMING:
       stateString.AssignLiteral("incoming");
       break;
     default:
       NS_NOTREACHED("Unknown state!");
   }
 
-  mState = stateString;
   mCallState = aCallState;
+  if (!stateString.IsEmpty()) {
+    mState = stateString;
+  }
 
   if (aCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
     NS_ASSERTION(mLive, "Should be live!");
     mLive = false;
     if (mGroup) {
       mGroup->RemoveCall(this);
     } else {
       mTelephony->RemoveCall(this);
@@ -151,16 +152,33 @@ TelephonyCall::DispatchCallEvent(const n
   init.mCancelable = false;
   init.mCall = aCall;
 
   nsRefPtr<CallEvent> event = CallEvent::Constructor(this, aType, init);
 
   return DispatchTrustedEvent(event);
 }
 
+already_AddRefed<Promise>
+TelephonyCall::CreatePromise(ErrorResult& aRv)
+{
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
+  if (!global) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  return promise.forget();
+}
+
 void
 TelephonyCall::NotifyError(const nsAString& aError)
 {
   // Set the error string
   NS_ASSERTION(!mError, "Already have an error?");
 
   mError = new DOMError(GetOwner(), aError);
 
@@ -226,82 +244,73 @@ TelephonyCall::GetGroup() const
 {
   nsRefPtr<TelephonyCallGroup> group = mGroup;
   return group.forget();
 }
 
 already_AddRefed<Promise>
 TelephonyCall::Answer(ErrorResult& aRv)
 {
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
-  if (!global) {
-    aRv.Throw(NS_ERROR_FAILURE);
+  nsRefPtr<Promise> promise = CreatePromise(aRv);
+  if (!promise) {
     return nullptr;
   }
 
-  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
-  NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
-
   if (mCallState != nsITelephonyService::CALL_STATE_INCOMING) {
-    NS_WARNING("Answer on non-incoming call is rejected!");
+    NS_WARNING(nsPrintfCString("Answer on non-incoming call is rejected!"
+                               " (State: %u)", mCallState).get());
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
   aRv = mTelephony->Service()->AnswerCall(mServiceId, mCallIndex, callback);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
-  ChangeStateInternal(nsITelephonyService::CALL_STATE_CONNECTING, true);
+  ChangeStateInternal(nsITelephonyService::CALL_STATE_CONNECTING, false);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 TelephonyCall::HangUp(ErrorResult& aRv)
 {
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
-  if (!global) {
-    aRv.Throw(NS_ERROR_FAILURE);
+  nsRefPtr<Promise> promise = CreatePromise(aRv);
+  if (!promise) {
     return nullptr;
   }
 
-  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
-  NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
-
   if (mCallState == nsITelephonyService::CALL_STATE_DISCONNECTING ||
       mCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
-    NS_WARNING("HangUp on previously disconnected call is rejected!");
+    NS_WARNING(nsPrintfCString("HangUp on previously disconnected call"
+                               " is rejected! (State: %u)", mCallState).get());
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
   aRv = mCallState == nsITelephonyService::CALL_STATE_INCOMING ?
     mTelephony->Service()->RejectCall(mServiceId, mCallIndex, callback) :
     mTelephony->Service()->HangUpCall(mServiceId, mCallIndex, callback);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
-  ChangeStateInternal(nsITelephonyService::CALL_STATE_DISCONNECTING, true);
+  ChangeStateInternal(nsITelephonyService::CALL_STATE_DISCONNECTING, false);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 TelephonyCall::Hold(ErrorResult& aRv)
 {
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
-  if (!global) {
-    aRv.Throw(NS_ERROR_FAILURE);
+  nsRefPtr<Promise> promise = CreatePromise(aRv);
+  if (!promise) {
     return nullptr;
   }
 
-  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
-  NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
-
   if (mCallState != nsITelephonyService::CALL_STATE_CONNECTED) {
-    NS_WARNING("Hold non-connected call is rejected!");
+    NS_WARNING(nsPrintfCString("Hold non-connected call is rejected!"
+                               " (State: %u)", mCallState).get());
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   if (mGroup) {
     NS_WARNING("Hold a call in conference is rejected!");
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
@@ -319,34 +328,31 @@ TelephonyCall::Hold(ErrorResult& aRv)
 
   if (mSecondId) {
     // No state transition when we switch two numbers within one TelephonyCall
     // object. Otherwise, the state here will be inconsistent with the backend
     // RIL and will never be right.
     return promise.forget();
   }
 
-  ChangeStateInternal(nsITelephonyService::CALL_STATE_HOLDING, true);
+  ChangeStateInternal(nsITelephonyService::CALL_STATE_HOLDING, false);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 TelephonyCall::Resume(ErrorResult& aRv)
 {
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
-  if (!global) {
-    aRv.Throw(NS_ERROR_FAILURE);
+  nsRefPtr<Promise> promise = CreatePromise(aRv);
+  if (!promise) {
     return nullptr;
   }
 
-  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
-  NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
-
   if (mCallState != nsITelephonyService::CALL_STATE_HELD) {
-    NS_WARNING("Resume non-held call is rejected!");
+    NS_WARNING(nsPrintfCString("Resume non-held call is rejected!"
+                               " (State: %u)", mCallState).get());
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   if (mGroup) {
     NS_WARNING("Resume a call in conference is rejected!");
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
@@ -357,11 +363,11 @@ TelephonyCall::Resume(ErrorResult& aRv)
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
   aRv = mTelephony->Service()->ResumeCall(mServiceId, mCallIndex, callback);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
-  ChangeStateInternal(nsITelephonyService::CALL_STATE_RESUMING, true);
+  ChangeStateInternal(nsITelephonyService::CALL_STATE_RESUMING, false);
   return promise.forget();
 }
--- a/dom/telephony/TelephonyCall.h
+++ b/dom/telephony/TelephonyCall.h
@@ -100,23 +100,19 @@ public:
   Hold(ErrorResult& aRv);
 
   already_AddRefed<Promise>
   Resume(ErrorResult& aRv);
 
   IMPL_EVENT_HANDLER(statechange)
   IMPL_EVENT_HANDLER(dialing)
   IMPL_EVENT_HANDLER(alerting)
-  IMPL_EVENT_HANDLER(connecting)
   IMPL_EVENT_HANDLER(connected)
-  IMPL_EVENT_HANDLER(disconnecting)
   IMPL_EVENT_HANDLER(disconnected)
-  IMPL_EVENT_HANDLER(holding)
   IMPL_EVENT_HANDLER(held)
-  IMPL_EVENT_HANDLER(resuming)
   IMPL_EVENT_HANDLER(error)
   IMPL_EVENT_HANDLER(groupchange)
 
   static already_AddRefed<TelephonyCall>
   Create(Telephony* aTelephony, TelephonyCallId* aId,
          uint32_t aServiceId, uint32_t aCallIndex, uint16_t aCallState,
          bool aEmergency = false, bool aConference = false,
          bool aSwitchable = true, bool aMergeable = true);
@@ -178,14 +174,17 @@ private:
   ~TelephonyCall();
 
   void
   ChangeStateInternal(uint16_t aCallState, bool aFireEvents);
 
   nsresult
   DispatchCallEvent(const nsAString& aType,
                     TelephonyCall* aCall);
+
+  already_AddRefed<Promise>
+  CreatePromise(ErrorResult& aRv);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_telephony_telephonycall_h__
--- a/dom/telephony/test/marionette/head.js
+++ b/dom/telephony/test/marionette/head.js
@@ -496,103 +496,86 @@ let emulator = (function() {
    *        triggers conference state change.
    * @return Promise<TelephonyCall>
    */
   function answer(call, conferenceStateChangeCallback) {
     log("Answering the incoming call.");
 
     let promises = [];
 
-    let promise = waitForNamedStateEvent(call, "connecting")
-      .then(() => waitForNamedStateEvent(call, "connected"));
-
-    promises.push(promise);
-
     // incoming call triggers conference state change. We should wait for
     // |conference.onstatechange| before checking the state of the conference
     // call.
     if (conference.state === "connected") {
       let promise = waitForStateChangeEvent(conference, "held")
         .then(() => {
           if (typeof conferenceStateChangeCallback === "function") {
             conferenceStateChangeCallback();
           }
         });
 
       promises.push(promise);
     }
 
-    promise = call.answer();
-    promises.push(promise);
+    promises.push(waitForNamedStateEvent(call, "connected"));
+    promises.push(call.answer());
 
     return Promise.all(promises).then(() => call);
   }
 
   /**
    * Hold a call.
    *
    * @param call
    *        A TelephonyCall object.
    * @return Promise<TelephonyCall>
    */
   function hold(call) {
     log("Putting the call on hold.");
 
     let promises = [];
 
-    let promise = waitForNamedStateEvent(call, "holding")
-      .then(() => waitForNamedStateEvent(call, "held"));
-    promises.push(promise);
-
-    promise = call.hold();
-    promises.push(promise);
+    promises.push(waitForNamedStateEvent(call, "held"));
+    promises.push(call.hold());
 
     return Promise.all(promises).then(() => call);
   }
 
   /**
    * Resume a call.
    *
    * @param call
    *        A TelephonyCall object.
    * @return Promise<TelephonyCall>
    */
   function resume(call) {
     log("Resuming the held call.");
 
     let promises = [];
 
-    let promise = waitForNamedStateEvent(call, "resuming")
-      .then(() => waitForNamedStateEvent(call, "connected"));
-    promises.push(promise);
-
-    promise = call.resume();
-    promises.push(promise);
+    promises.push(waitForNamedStateEvent(call, "connected"));
+    promises.push(call.resume());
 
     return Promise.all(promises).then(() => call);
   }
 
   /**
    * Locally hang up a call.
    *
    * @param call
    *        A TelephonyCall object.
    * @return Promise<TelephonyCall>
    */
   function hangUp(call) {
     log("Local hanging up the call: " + call.id.number);
 
     let promises = [];
 
-    let promise = waitForNamedStateEvent(call, "disconnecting")
-      .then(() => waitForNamedStateEvent(call, "disconnected"));
-    promises.push(promise);
-
-    promise = call.hangUp();
-    promises.push(promise);
+    promises.push(waitForNamedStateEvent(call, "disconnected"));
+    promises.push(call.hangUp());
 
     return Promise.all(promises).then(() => call);
   }
 
   /**
    * Simulate an incoming call.
    *
    * @param number
@@ -723,19 +706,17 @@ let emulator = (function() {
    * @return Promise<[TelephonyCall ...]>
    */
   function holdConference(callsInConference, heldCallback) {
     log("Holding the conference call.");
 
     let promises = [];
 
     for (let call of callsInConference) {
-      let promise = waitForNamedStateEvent(call, "holding")
-        .then(() => waitForNamedStateEvent(call, "held"));
-      promises.push(promise);
+      promises.push(waitForNamedStateEvent(call, "held"));
     }
 
     let promise = waitForNamedStateEvent(conference, "holding")
       .then(() => waitForNamedStateEvent(conference, "held"))
       .then(() => {
         if (typeof heldCallback === "function") {
           heldCallback();
         }
@@ -758,19 +739,17 @@ let emulator = (function() {
    * @return Promise<[TelephonyCall ...]>
    */
   function resumeConference(callsInConference, connectedCallback) {
     log("Resuming the held conference call.");
 
     let promises = [];
 
     for (let call of callsInConference) {
-      let promise = waitForNamedStateEvent(call, "resuming")
-        .then(() => waitForNamedStateEvent(call, "connected"));
-      promises.push(promise);
+      promises.push(waitForNamedStateEvent(call, "connected"));
     }
 
     let promise = waitForNamedStateEvent(conference, "resuming")
       .then(() => waitForNamedStateEvent(conference, "connected"))
       .then(() => {
         if (typeof connectedCallback === "function") {
           connectedCallback();
         }
--- a/dom/telephony/test/marionette/manifest.ini
+++ b/dom/telephony/test/marionette/manifest.ini
@@ -24,17 +24,16 @@ qemu = true
 [test_emergency_label.js]
 [test_incall_mmi_call_hold.js]
 [test_incall_mmi_call_waiting.js]
 [test_incall_mmi_conference.js]
 [test_incoming_already_connected.js]
 [test_incoming_already_held.js]
 [test_incoming_answer_hangup_oncallschanged.js]
 [test_incoming_basic_operations.js]
-[test_incoming_connecting_hangup.js]
 [test_incoming_onstatechange.js]
 [test_mmi.js]
 [test_mmi_call_forwarding.js]
 [test_mmi_change_barring_password.js]
 [test_mmi_change_pin.js]
 [test_mmi_unlock_puk.js]
 [test_multiple_hold.js]
 [test_outgoing_already_held.js]
deleted file mode 100644
--- a/dom/telephony/test/marionette/test_incoming_connecting_hangup.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-MARIONETTE_TIMEOUT = 60000;
-MARIONETTE_HEAD_JS = 'head.js';
-
-const inNumber = "5555552222";
-const inInfo = gInCallStrPool(inNumber);
-let inCall;
-
-function incoming() {
-  return gRemoteDial(inNumber)
-    .then(call => inCall = call)
-    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]));
-}
-
-function connecting() {
-  let promises = [
-    gWaitForNamedStateEvent(inCall, "connecting"),
-    inCall.answer()
-  ];
-  return Promise.all(promises).then(() => inCall);
-}
-
-function hangUp() {
-  return gHangUp(inCall)
-    .then(() => gCheckAll(null, [], "", [], []));
-}
-
-function remoteHangUp() {
-  return gRemoteHangUp(inCall)
-    .then(() => gCheckAll(null, [], "", [], []));
-}
-
-// Test cases.
-
-function testConnectingHangUp() {
-  log("= testConnectingHangUp =");
-  return incoming()
-    .then(() => connecting())
-    .then(() => hangUp());
-}
-
-function testConnectingRemoteHangUp() {
-  log("= testConnectingRemoteHangUp =");
-  return incoming()
-    .then(() => connecting())
-    .then(() => remoteHangUp());
-}
-
-startTest(function() {
-  Promise.resolve()
-    .then(() => testConnectingHangUp())
-    .then(() => testConnectingRemoteHangUp())
-
-    .catch(error => ok(false, "Promise reject: " + error))
-    .then(finish);
-});
--- a/dom/telephony/test/marionette/test_incoming_onstatechange.js
+++ b/dom/telephony/test/marionette/test_incoming_onstatechange.js
@@ -9,46 +9,26 @@ const inInfo = gInCallStrPool(inNumber);
 let inCall;
 
 startTest(function() {
   gRemoteDial(inNumber)
     .then(call => inCall = call)
     .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
 
     // Answer incoming call
-    .then(() => {
-      let p1 = gWaitForStateChangeEvent(inCall, "connecting")
-        .then(() => gWaitForStateChangeEvent(inCall, "connected"));
-      let p2 = gAnswer(inCall);
-      return Promise.all([p1, p2]);
-    })
+    .then(() => gAnswer(inCall))
     .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
 
     // Hold the call.
-    .then(() => {
-      let p1 = gWaitForStateChangeEvent(inCall, "holding")
-        .then(() => gWaitForStateChangeEvent(inCall, "held"));
-      let p2 = gHold(inCall);
-      return Promise.all([p1, p2]);
-    })
+    .then(() => gHold(inCall))
     .then(() => gCheckAll(null, [inCall], "", [], [inInfo.held]))
 
     // Resume the call.
-    .then(() => {
-      let p1 = gWaitForStateChangeEvent(inCall, "resuming")
-        .then(() => gWaitForStateChangeEvent(inCall, "connected"));
-      let p2 = gResume(inCall);
-      return Promise.all([p1, p2]);
-    })
+    .then(() => gResume(inCall))
     .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
 
     // Hang-up call
-    .then(() => {
-      let p1 = gWaitForStateChangeEvent(inCall, "disconnecting")
-        .then(() => gWaitForStateChangeEvent(inCall, "disconnected"));
-      let p2 = gHangUp(inCall);
-      return Promise.all([p1, p2]);
-    })
+    .then(() => gHangUp(inCall))
     .then(() => gCheckAll(null, [], "", [], []))
 
     .catch(error => ok(false, "Promise reject: " + error))
     .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_onstatechange.js
+++ b/dom/telephony/test/marionette/test_outgoing_onstatechange.js
@@ -17,37 +17,22 @@ startTest(function() {
     .then(() => {
       let p1 = gWaitForStateChangeEvent(outCall, "connected");
       let p2 = gRemoteAnswer(outCall);
       return Promise.all([p1, p2]);
     })
     .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
 
     // Hold the call.
-    .then(() => {
-      let p1 = gWaitForStateChangeEvent(outCall, "holding")
-        .then(() => gWaitForStateChangeEvent(outCall, "held"));
-      let p2 = gHold(outCall);
-      return Promise.all([p1, p2]);
-    })
+    .then(() => gHold(outCall))
     .then(() => gCheckAll(null, [outCall], "", [], [outInfo.held]))
 
     // Resume the call.
-    .then(() => {
-      let p1 = gWaitForStateChangeEvent(outCall, "resuming")
-        .then(() => gWaitForStateChangeEvent(outCall, "connected"));
-      let p2 = gResume(outCall);
-      return Promise.all([p1, p2]);
-    })
+    .then(() => gResume(outCall))
     .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
 
     // Hang-up call
-    .then(() => {
-      let p1 = gWaitForStateChangeEvent(outCall, "disconnecting")
-        .then(() => gWaitForStateChangeEvent(outCall, "disconnected"));
-      let p2 = gHangUp(outCall);
-      return Promise.all([p1, p2]);
-    })
+    .then(() => gHangUp(outCall))
     .then(() => gCheckAll(null, [], "", [], []))
 
     .catch(error => ok(false, "Promise reject: " + error))
     .then(finish);
 });
--- a/dom/telephony/test/marionette/test_redundant_operations.js
+++ b/dom/telephony/test/marionette/test_redundant_operations.js
@@ -3,65 +3,47 @@
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
 const inNumber = "5555552222";
 const inInfo = gInCallStrPool(inNumber);
 let inCall;
 
-function error(event, action) {
-  ok(false, "Received '" + event + "' event when " + action);
+function error(aEvent, aAction) {
+  ok(false, "Received '" + aEvent + "' event when " + aAction);
 }
 
-function checkUnexpected(msg, call, event1, event2, actionCallback) {
-  let error1 = error.bind(this, event1, msg);
-  let error2 = error.bind(this, event2, msg);
-
-  call.addEventListener(event1, error1);
-  call.addEventListener(event2, error2);
+function checkUnexpected(aMsg, aCall, aEvent, aActionCallback) {
+  let handler = error.bind(this, aEvent, aMsg);
+  aCall.addEventListener(aEvent, handler);
 
-  return actionCallback().then(
+  return aActionCallback().then(
     () => ok(false, msg + "should be rejected."),
-    () => gDelay(2000).then(() => {
-      call.removeEventListener(event1, error1);
-      call.removeEventListener(event2, error2);
-    }));
+    () => gDelay(2000).then(() => aCall.removeEventListener(aEvent, handler)));
 }
 
 startTest(function() {
   gRemoteDial(inNumber)
     .then(call => inCall = call)
     .then(() => gAnswer(inCall))
     .then(() => checkUnexpected("answered an active call", inCall,
-                                "connecting", "connected",
-                                () => inCall.answer()))
-
+                                "connected", () => inCall.answer()))
     .then(() => gHold(inCall))
     .then(() => checkUnexpected("held a held call", inCall,
-                                "holding", "held",
-                                () => inCall.hold()))
+                                "held", () => inCall.hold()))
     .then(() => checkUnexpected("answered a held call", inCall,
-                                "connecting", "connected",
-                                () => inCall.answer()))
-
+                                "connected", () => inCall.answer()))
     .then(() => gResume(inCall))
     .then(() => checkUnexpected("resumed non-held call", inCall,
-                                "resuming", "connected",
-                                () => inCall.resume()))
-
+                                "connected", () => inCall.resume()))
     .then(() => gHangUp(inCall))
     .then(() => checkUnexpected("answered a disconnected call", inCall,
-                                "connecting", "connected",
-                                () => inCall.answer()))
+                                "connected", () => inCall.answer()))
     .then(() => checkUnexpected("held a disconnected call", inCall,
-                                "holding", "held",
-                                () => inCall.hold()))
+                                "held", () => inCall.hold()))
     .then(() => checkUnexpected("resumed a disconnected call", inCall,
-                                "resuming", "connected",
-                                () => inCall.resume()))
+                                "connected", () => inCall.resume()))
     .then(() => checkUnexpected("hang-up a disconnected call", inCall,
-                                "disconnecting", "disconnected",
-                                () => inCall.hangUp()))
-
+                                "disconnected", () => inCall.hangUp()))
     .catch(error => ok(false, "Promise reject: " + error))
     .then(finish);
 });
new file mode 100644
--- /dev/null
+++ b/dom/webidl/SecureElement.webidl
@@ -0,0 +1,160 @@
+/* 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/. */
+
+ /* Copyright © 2014 Deutsche Telekom, Inc. */
+
+enum SEType {
+  "uicc",
+  "eSE"
+};
+
+enum SEError {
+  "SESecurityError",            // Requested operation does not match the access control rules of the application.
+  "SEIoError",                  // I/O Error while communicating with the secure element.
+  "SEBadStateError",            // Error occuring as a result of bad state.
+  "SEInvalidChannelError",      // Opening a channel failed because no channel is available.
+  "SEInvalidApplicationError",  // The requested application was not found on the secure element.
+  "SEGenericError"              // Generic failures.
+};
+
+enum SEChannelType {
+  "basic",
+  "logical"
+};
+
+// Dictionary that represents an APDU command to be sent to a secure element.
+dictionary SECommand {
+  required octet cla;            // Class Byte
+  required octet ins;            // Instruction Byte
+  required octet p1;             // First Octet of Parameters Byte
+  required octet p2;             // Second Octet of Parameters Byte
+  sequence<octet>? data = null;  // Sequence of octets
+  short le = -1;                 // The length of the expected
+                                 // response data or -1 if none is expected
+};
+
+[Pref="dom.secureelement.enabled",
+ CheckPermissions="secureelement-manage",
+ AvailableIn="CertifiedApps",
+ JSImplementation="@mozilla.org/secureelement/reader;1"]
+interface SEReader {
+
+  // 'true' if a secure element is present
+  readonly attribute boolean isSEPresent;
+
+  // Type of SecureElement
+  readonly attribute SEType type;
+
+  /**
+   * Opens a session with the Secure Element.
+   * Note that a reader may have several opened sessions.
+   *
+   * @return If the operation is successful the promise is resolved with an instance of SESession.
+   */
+  [Throws]
+  Promise<SESession> openSession();
+
+  /**
+   * Closes all sessions associated with this Reader and its associated channels.
+   *
+   */
+  [Throws]
+  Promise<void> closeAll();
+};
+
+[Pref="dom.secureelement.enabled",
+ CheckPermissions="secureelement-manage",
+ AvailableIn="CertifiedApps",
+ JSImplementation="@mozilla.org/secureelement/session;1"]
+interface SESession {
+
+  // 'reader' that provides this session
+  readonly attribute SEReader reader;
+
+  // Status of current session
+  readonly attribute boolean isClosed;
+
+  /**
+   * Opens a communication logical channel to an application on Secure Element identified by the AID.
+   * The 'aid' can be null for some secure elements.
+   *
+   * @param aid
+   *     Application Identifier of the Card Applet on the secure element.
+   *     If the 'aid' is null :
+   *       For secure element type 'eSE', the default applet is selected.
+   *       For secure element type 'uicc', the request will be immediately rejected.
+   *     Note that the length of 'aid should be between 5 and 16.
+   *
+   * @return If the operation is successful the promise is resolved with an instance of SEChannel.
+   */
+  [Throws]
+  Promise<SEChannel> openLogicalChannel(Uint8Array? aid);
+
+  /**
+   * Close all active channels associated with this session.
+   *
+   */
+  [Throws]
+  Promise<void> closeAll();
+};
+
+[Pref="dom.secureelement.enabled",
+ CheckPermissions="secureelement-manage",
+ AvailableIn="CertifiedApps",
+ JSImplementation="@mozilla.org/secureelement/channel;1"]
+interface SEChannel {
+
+  // 'session' obj this channel is bound to
+  readonly attribute SESession session;
+
+  // response to openBasicChannel / openLogicalChannel operation
+  [Constant, Cached] readonly  attribute Uint8Array? openResponse;
+
+  // Status of channel
+  readonly attribute boolean isClosed;
+
+  // Type of channel
+  readonly attribute SEChannelType type;
+
+  /**
+   * Transmits the APDU command to the secure element. This is an atomic operation that transmits
+   * an APDU command (as per ISO7816-4) to the secure element (UICC / eSE). Upon receiving response
+   * to the transmit apdu command, it is propogated to the applications using SEResponse object.
+   *
+   * @param command
+   *     SECommand to be sent to secure element
+   *
+   * @return If success, the promise is resolved with the new created
+   * SEResponse object. Otherwise, rejected with the error of type 'SEError'.
+   */
+  [Throws]
+  Promise<SEResponse> transmit(optional SECommand command);
+
+  /**
+   * Closes the active channel.
+   *
+   */
+  [Throws]
+  Promise<void> close();
+};
+
+[Pref="dom.secureelement.enabled",
+ CheckPermissions="secureelement-manage",
+ AvailableIn="CertifiedApps",
+ JSImplementation="@mozilla.org/secureelement/response;1"]
+interface SEResponse {
+  // Response received on this 'channel' object.
+  [Constant] readonly attribute SEChannel channel;
+
+  // First octet of response's status word
+  [Constant] readonly attribute octet        sw1;
+
+  // Second octet of response's status word
+  [Constant] readonly attribute octet        sw2;
+
+  // The response's data field bytes
+  [Cached, Pure] readonly attribute sequence<octet>?  data;
+
+};
+
new file mode 100644
--- /dev/null
+++ b/dom/webidl/SecureElementManager.webidl
@@ -0,0 +1,23 @@
+/* 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/. */
+
+ /* Copyright © 2014 Deutsche Telekom, Inc. */
+
+[Pref="dom.secureelement.enabled",
+ CheckPermissions="secureelement-manage",
+ AvailableIn="CertifiedApps",
+ JSImplementation="@mozilla.org/secureelement/manager;1",
+ NavigatorProperty="seManager",
+ NoInterfaceObject]
+interface SEManager {
+
+  /**
+   * Retrieves all the readers available on the device.
+   *
+   * @return If success, the promise is resolved to  a sequence
+   *        of SEReaders Otherwise, rejected with an error.
+   */
+  [Throws]
+  Promise<sequence<SEReader>> getSEReaders();
+};
--- a/dom/webidl/TelephonyCall.webidl
+++ b/dom/webidl/TelephonyCall.webidl
@@ -40,20 +40,16 @@ interface TelephonyCall : EventTarget {
   [NewObject]
   Promise<void> hold();
   [NewObject]
   Promise<void> resume();
 
   attribute EventHandler onstatechange;
   attribute EventHandler ondialing;
   attribute EventHandler onalerting;
-  attribute EventHandler onconnecting;
   attribute EventHandler onconnected;
-  attribute EventHandler ondisconnecting;
   attribute EventHandler ondisconnected;
-  attribute EventHandler onholding;
   attribute EventHandler onheld;
-  attribute EventHandler onresuming;
   attribute EventHandler onerror;
 
   // Fired whenever the group attribute changes.
   attribute EventHandler ongroupchange;
 };
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -656,16 +656,22 @@ if CONFIG['MOZ_NFC']:
          'MozIsoDepTech.webidl',
          'MozNDEFRecord.webidl',
          'MozNFC.webidl',
          'MozNFCPeer.webidl',
          'MozNFCTag.webidl',
          'NfcOptions.webidl',
     ]
 
+if CONFIG['MOZ_SECUREELEMENT']:
+    WEBIDL_FILES += [
+         'SecureElement.webidl',
+         'SecureElementManager.webidl',
+    ]
+
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     WEBIDL_FILES += [
         'MozNetworkStats.webidl',
         'MozNetworkStatsAlarm.webidl',
         'MozNetworkStatsData.webidl',
         'MozNetworkStatsInterface.webidl',
         'MozSpeakerManager.webidl',
         'MozWifiCapabilities.webidl',
--- a/layout/build/moz.build
+++ b/layout/build/moz.build
@@ -114,9 +114,14 @@ if CONFIG['MOZ_B2G_BT']:
 if CONFIG['MOZ_WEBSPEECH']:
     LOCAL_INCLUDES += [
         '/dom/media/webspeech/synth',
     ]
 
 if CONFIG['MOZ_GSTREAMER']:
     CXXFLAGS += CONFIG['GSTREAMER_CFLAGS']
 
+if CONFIG['MOZ_SECUREELEMENT']:
+    LOCAL_INCLUDES += [
+        '/dom/secureelement',
+    ]
+
 FINAL_LIBRARY = 'xul'
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4560,8 +4560,13 @@ pref("reader.has_used_toolbar", false);
 pref("reader.toolbar.vertical", true);
 
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
 // Whether to allow, on a Linux system that doesn't support the necessary sandboxing
 // features, loading Gecko Media Plugins unsandboxed.  However, EME CDMs will not be
 // loaded without sandboxing even if this pref is changed.
 pref("media.gmp.insecure.allow", false);
 #endif
+
+// Secure Element API
+#ifdef MOZ_SECUREELEMENT
+pref("dom.secureelement.enabled", false);
+#endif
--- a/toolkit/components/url-classifier/Classifier.cpp
+++ b/toolkit/components/url-classifier/Classifier.cpp
@@ -394,17 +394,18 @@ nsresult
 Classifier::RegenActiveTables()
 {
   mActiveTablesCache.Clear();
 
   nsTArray<nsCString> foundTables;
   ScanStoreDir(foundTables);
 
   for (uint32_t i = 0; i < foundTables.Length(); i++) {
-    HashStore store(nsCString(foundTables[i]), mStoreDirectory);
+    nsCString table(foundTables[i]);
+    HashStore store(table, mStoreDirectory);
 
     nsresult rv = store.Open();
     if (NS_FAILED(rv))
       continue;
 
     LookupCache *lookupCache = GetLookupCache(store.TableName());
     if (!lookupCache) {
       continue;
--- a/toolkit/components/url-classifier/content/listmanager.js
+++ b/toolkit/components/url-classifier/content/listmanager.js
@@ -11,44 +11,44 @@ Cu.import("resource://gre/modules/Servic
 // update, and store lists.
 //
 // There is a single listmanager for the whole application.
 //
 // TODO more comprehensive update tests, for example add unittest check 
 //      that the listmanagers tables are properly written on updates
 
 // Log only if browser.safebrowsing.debug is true
-function log(...stuff) {
+this.log = function log(...stuff) {
   var prefs_ = new G_Preferences();
   var debug = prefs_.getPref("browser.safebrowsing.debug");
   if (!debug) {
     return;
   }
 
   var d = new Date();
   let msg = "listmanager: " + d.toTimeString() + ": " + stuff.join(" ");
   Services.console.logStringMessage(msg);
   dump(msg + "\n");
 }
 
-function QueryAdapter(callback) {
+this.QueryAdapter = function QueryAdapter(callback) {
   this.callback_ = callback;
 };
 
 QueryAdapter.prototype.handleResponse = function(value) {
   this.callback_.handleEvent(value);
 }
 
 /**
  * A ListManager keeps track of black and white lists and knows
  * how to update them.
  *
  * @constructor
  */
-function PROT_ListManager() {
+this.PROT_ListManager = function PROT_ListManager() {
   log("Initializing list manager");
   this.prefs_ = new G_Preferences();
   this.updateInterval = this.prefs_.getPref("urlclassifier.updateinterval", 30 * 60) * 1000;
 
   // A map of tableNames to objects of type
   // { updateUrl: <updateUrl>, gethashUrl: <gethashUrl> }
   this.tablesData = {};
   // A map of updateUrls to maps of tables requiring updates, e.g.
--- a/toolkit/components/url-classifier/content/moz/alarm.js
+++ b/toolkit/components/url-classifier/content/moz/alarm.js
@@ -34,16 +34,17 @@
  *
  * @param callback Function to call when the alarm fires
  * @param delayMS Number indicating the length of the alarm period in ms
  * @param opt_repeating Boolean indicating whether this should fire 
  *                      periodically
  * @param opt_maxTimes Number indicating a maximum number of times to 
  *                     repeat (obviously only useful when opt_repeating==true)
  */
+this.G_Alarm =
 function G_Alarm(callback, delayMS, opt_repeating, opt_maxTimes) {
   this.debugZone = "alarm";
   this.callback_ = callback;
   this.repeating_ = !!opt_repeating;
   this.timer_ = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   var type = opt_repeating ? 
              this.timer_.TYPE_REPEATING_SLACK : 
              this.timer_.TYPE_ONE_SHOT;
@@ -119,21 +120,29 @@ G_Alarm.prototype.QueryInterface = funct
 
 
 /**
  * An alarm with the additional property that it cancels itself if its 
  * callback returns true.
  *
  * For parameter documentation, see G_Alarm
  */
+this.G_ConditionalAlarm =
 function G_ConditionalAlarm(callback, delayMS, opt_repeating, opt_maxTimes) {
   G_Alarm.call(this, callback, delayMS, opt_repeating, opt_maxTimes);
   this.debugZone = "conditionalalarm";
 }
 
+G_ConditionalAlarm.inherits = function(parentCtor) {
+  var tempCtor = function(){};
+  tempCtor.prototype = parentCtor.prototype;
+  this.superClass_ = parentCtor.prototype;
+  this.prototype = new tempCtor();
+}
+
 G_ConditionalAlarm.inherits(G_Alarm);
 
 /**
  * Invoked by the timer when it fires
  * 
  * @param timer Reference to the nsITimer which fired (not currently 
  *              passed along)
  */
--- a/toolkit/components/url-classifier/content/moz/cryptohasher.js
+++ b/toolkit/components/url-classifier/content/moz/cryptohasher.js
@@ -15,16 +15,17 @@
 //
 // IMPORTANT NOTE: Due to https://bugzilla.mozilla.org/show_bug.cgi?id=321024
 // you cannot use the cryptohasher before app-startup. The symptom of doing
 // so is a segfault in NSS.
 
 /**
  * Instantiate a new hasher. You must explicitly call init() before use!
  */
+this.G_CryptoHasher =
 function G_CryptoHasher() {
   this.debugZone = "cryptohasher";
   this.hasher_ = null;
 }
 
 G_CryptoHasher.algorithms = {
   MD2: Ci.nsICryptoHash.MD2,
   MD5: Ci.nsICryptoHash.MD5,
@@ -141,17 +142,17 @@ G_CryptoHasher.prototype.toHex_ = functi
   }
   return hexrep.join('');
 }
 
 #ifdef DEBUG
 /**
  * Lame unittest function
  */
-function TEST_G_CryptoHasher() {
+this.TEST_G_CryptoHasher = function TEST_G_CryptoHasher() {
   if (G_GDEBUG) {
     var z = "cryptohasher UNITTEST";
     G_debugService.enableZone(z);
 
     G_Debug(z, "Starting");
 
     var md5 = function(str) {
       var hasher = new G_CryptoHasher();
--- a/toolkit/components/url-classifier/content/moz/debug.js
+++ b/toolkit/components/url-classifier/content/moz/debug.js
@@ -73,26 +73,26 @@ if (typeof G_GDEBUG == "undefined") {
 
 /**
  * Write out a debugging message.
  *
  * @param who The thingy to convert into a zone name corresponding to the 
  *            zone to which this message belongs
  * @param msg Message to output
  */
-function G_Debug(who, msg) {
+this.G_Debug = function G_Debug(who, msg) {
   if (G_GDEBUG) {
     G_GetDebugZone(who).debug(msg);
   }
 }
 
 /**
  * Debugs loudly
  */
-function G_DebugL(who, msg) {
+this.G_DebugL = function G_DebugL(who, msg) {
   if (G_GDEBUG) {
     var zone = G_GetDebugZone(who);
 
     if (zone.zoneIsEnabled()) {
       G_debugService.dump(
         "\n************************************************************\n");
 
       G_Debug(who, msg);
@@ -105,60 +105,60 @@ function G_DebugL(who, msg) {
 
 /**
  * Write out a call tracing message
  *
  * @param who The thingy to convert into a zone name corresponding to the 
  *            zone to which this message belongs
  * @param msg Message to output
  */
-function G_TraceCall(who, msg) {
+this.G_TraceCall = function G_TraceCall(who, msg) {
   if (G_GDEBUG) {
     if (G_debugService.callTracingEnabled()) {
       G_debugService.dump(msg + "\n");
     }
   }
 }
 
 /**
  * Write out an error (and throw)
  *
  * @param who The thingy to convert into a zone name corresponding to the 
  *            zone to which this message belongs
  * @param msg Message to output
  */
-function G_Error(who, msg) {
+this.G_Error = function G_Error(who, msg) {
   if (G_GDEBUG) {
     G_GetDebugZone(who).error(msg);
   }
 }
 
 /**
  * Assert something as true and signal an error if it's not
  *
  * @param who The thingy to convert into a zone name corresponding to the 
  *            zone to which this message belongs
  * @param condition Boolean condition to test
  * @param msg Message to output
  */
-function G_Assert(who, condition, msg) {
+this.G_Assert = function G_Assert(who, condition, msg) {
   if (G_GDEBUG) {
     G_GetDebugZone(who).assert(condition, msg);
   }
 }
 
 /**
  * Helper function that takes input and returns the DebugZone
  * corresponding to it.
  *
  * @param who Arbitrary input that will be converted into a zone name. Most
  *            likely an object that has .debugZone property, or a string.
  * @returns The DebugZone object corresponding to the input
  */
-function G_GetDebugZone(who) {
+this.G_GetDebugZone = function G_GetDebugZone(who) {
   if (G_GDEBUG) {
     var zone = "?";
 
     if (who && who.debugZone) {
       zone = who.debugZone;
     } else if (typeof who == "string") {
       zone = who;
     }
@@ -179,17 +179,17 @@ function G_GetDebugZone(who) {
  *
  * @constructor
  * @param service Reference to the DebugService object we use for 
  *                registration
  * @param prefix String indicating the unique prefix we should use
  *               when creating preferences to control this zone
  * @param zone String indicating the name of the zone
  */
-function G_DebugZone(service, prefix, zone) {
+this.G_DebugZone = function G_DebugZone(service, prefix, zone) {
   if (G_GDEBUG) {
     this.debugService_ = service;
     this.prefix_ = prefix;
     this.zone_ = zone;
     this.zoneEnabledPrefName_ = prefix + ".zone." + this.zone_;
     this.settings_ = new G_DebugSettings();
   }
 }
@@ -272,17 +272,17 @@ G_DebugZone.prototype.assert = function(
  * The debug service handles auto-registration of zones, namespacing
  * the zones preferences, and various global settings such as whether
  * all zones are enabled.
  *
  * @constructor
  * @param opt_prefix Optional string indicating the unique prefix we should 
  *                   use when creating preferences
  */
-function G_DebugService(opt_prefix) {
+this.G_DebugService = function G_DebugService(opt_prefix) {
   if (G_GDEBUG) {
     this.prefix_ = opt_prefix ? opt_prefix : "safebrowsing-debug-service";
     this.consoleEnabledPrefName_ = this.prefix_ + ".alsologtoconsole";
     this.allZonesEnabledPrefName_ = this.prefix_ + ".enableallzones";
     this.callTracingEnabledPrefName_ = this.prefix_ + ".trace-function-calls";
     this.logFileEnabledPrefName_ = this.prefix_ + ".logfileenabled";
     this.logFileErrorLevelPrefName_ = this.prefix_ + ".logfile-errorlevel";
     this.zones_ = {};
@@ -623,17 +623,17 @@ G_DebugService.prototype.reportScriptErr
  * This code is mostly stolen from Aaron Boodman's original
  * implementation in clobber utils.
  *
  * Note that this class uses the "loggifier" debug zone, so you'll see 
  * a complete call trace when that zone is enabled.
  *
  * @constructor
  */
-function G_Loggifier() {
+this.G_Loggifier = function G_Loggifier() {
   if (G_GDEBUG) {
     // Careful not to loggify ourselves!
     this.mark_(this);  
   }
 }
 
 /**
  * Marks an object as having been loggified. Loggification is not 
@@ -790,17 +790,17 @@ G_Loggifier.prototype.loggify = function
  * Simple abstraction around debug settings. The thing with debug settings is
  * that we want to be able to specify a default in the application's startup,
  * but have that default be overridable by the user via their prefs.
  *
  * To generalize this, we package up a dictionary of defaults with the 
  * preferences tree. If a setting isn't in the preferences tree, then we grab it
  * from the defaults.
  */
-function G_DebugSettings() {
+this.G_DebugSettings = function G_DebugSettings() {
   this.defaults_ = {};
   this.prefs_ = new G_Preferences();
 }
 
 /**
  * Returns the value of a settings, optionally defaulting to a given value if it
  * doesn't exist. If no default is specified, the default is |undefined|.
  */
@@ -830,14 +830,14 @@ if (G_GDEBUG) {
   G_debugService.enableAllZones();
 }
 
 #else
 
 // Stubs for the debugging aids scattered through this component.
 // They will be expanded if you compile yourself a debug build.
 
-function G_Debug(who, msg) { }
-function G_Assert(who, condition, msg) { }
-function G_Error(who, msg) { }
-var G_debugService = { __noSuchMethod__: function() { } };
+this.G_Debug = function G_Debug(who, msg) { }
+this.G_Assert = function G_Assert(who, condition, msg) { }
+this.G_Error = function G_Error(who, msg) { }
+this.G_debugService = { __noSuchMethod__: function() { } };
 
 #endif
--- a/toolkit/components/url-classifier/content/moz/lang.js
+++ b/toolkit/components/url-classifier/content/moz/lang.js
@@ -22,17 +22,17 @@
  * @param fn {string} Reference to the function to be bound
  *
  * @param self {object} Specifies the object which |this| should point to
  * when the function is run. If the value is null or undefined, it will default
  * to the global object.
  *
  * @returns {function} A partially-applied form of the speficied function.
  */
-function BindToObject(fn, self, opt_args) {
+this.BindToObject = function BindToObject(fn, self, opt_args) {
   var boundargs = fn.boundArgs_ || [];
   boundargs = boundargs.concat(Array.slice(arguments, 2, arguments.length));
 
   if (fn.boundSelf_)
     self = fn.boundSelf_;
   if (fn.boundFn_)
     fn = fn.boundFn_;
 
--- a/toolkit/components/url-classifier/content/moz/observer.js
+++ b/toolkit/components/url-classifier/content/moz/observer.js
@@ -26,17 +26,17 @@
  *
  * @param topic String containing the topic the observer will filter for
  *
  * @param observeFunction Reference to the function to call when the 
  *                        observer fires
  *
  * @constructor
  */
-function G_ObserverWrapper(topic, observeFunction) {
+this.G_ObserverWrapper = function G_ObserverWrapper(topic, observeFunction) {
   this.debugZone = "observer";
   this.topic_ = topic;
   this.observeFunction_ = observeFunction;
 }
 
 /**
  * XPCOM
  */
@@ -65,16 +65,17 @@ G_ObserverWrapper.prototype.observe = fu
  * @param observeFunction Reference to the function to call when the 
  *                        observer fires
  *
  * @param opt_onlyOnce Boolean indicating if the observer should unregister
  *                     after it has fired
  *
  * @constructor
  */
+this.G_ObserverServiceObserver =
 function G_ObserverServiceObserver(topic, observeFunction, opt_onlyOnce) {
   this.debugZone = "observerserviceobserver";
   this.topic_ = topic;
   this.observeFunction_ = observeFunction;
   this.onlyOnce_ = !!opt_onlyOnce;
   
   this.observer_ = new G_ObserverWrapper(this.topic_, 
                                          BindToObject(this.observe_, this));
@@ -96,17 +97,17 @@ G_ObserverServiceObserver.prototype.unre
  */
 G_ObserverServiceObserver.prototype.observe_ = function(subject, topic, data) {
   this.observeFunction_(subject, topic, data);
   if (this.onlyOnce_)
     this.unregister();
 }
 
 #ifdef DEBUG
-function TEST_G_Observer() {
+this.TEST_G_Observer = function TEST_G_Observer() {
   if (G_GDEBUG) {
 
     var z = "observer UNITTEST";
     G_debugService.enableZone(z);
 
     G_Debug(z, "Starting");
 
     var regularObserverRan = 0;
--- a/toolkit/components/url-classifier/content/moz/preferences.js
+++ b/toolkit/components/url-classifier/content/moz/preferences.js
@@ -41,16 +41,17 @@
  * @param opt_startPoint        A starting point on the prefs tree to resolve 
  *                              names passed to setPref and getPref.
  *
  * @param opt_useDefaultPranch  Set to true to work against the default 
  *                              preferences tree instead of the profile one.
  *
  * @constructor
  */
+this.G_Preferences =
 function G_Preferences(opt_startPoint, opt_getDefaultBranch) {
   this.debugZone = "prefs";
   this.observers_ = {};
   this.getDefaultBranch_ = !!opt_getDefaultBranch;
 
   this.startPoint_ = opt_startPoint || null;
 }
 
@@ -191,16 +192,17 @@ G_Preferences.prototype.removeAllObserve
 
 /**
  * Helper class that knows how to observe preference changes and
  * invoke a callback when they do
  *
  * @constructor
  * @param callback Function to call when the preference changes
  */
+this.G_PreferenceObserver =
 function G_PreferenceObserver(callback) {
   this.debugZone = "prefobserver";
   this.callback_ = callback;
 }
 
 /**
  * Invoked by the pref system when a preference changes. Passes the
  * message along to the callback.
@@ -226,17 +228,17 @@ G_PreferenceObserver.prototype.QueryInte
       iid.equals(Ci.nsIObserver) ||
       iid.equals(Ci.nsISupportsWeakReference))
     return this;
   throw Components.results.NS_ERROR_NO_INTERFACE;
 }
 
 #ifdef DEBUG
 // UNITTESTS
-function TEST_G_Preferences() {
+this.TEST_G_Preferences = function TEST_G_Preferences() {
   if (G_GDEBUG) {
     var z = "preferences UNITTEST";
     G_debugService.enableZone(z);
     G_Debug(z, "Starting");
 
     var p = new G_Preferences();
     
     var testPref = "test-preferences-unittest";
--- a/toolkit/components/url-classifier/content/moz/protocol4.js
+++ b/toolkit/components/url-classifier/content/moz/protocol4.js
@@ -16,17 +16,17 @@
 
 
 /**
  * This class knows how to serialize/deserialize maps to/from their
  * protocol4 representation.
  *
  * @constructor
  */
-function G_Protocol4Parser() {
+this.G_Protocol4Parser = function G_Protocol4Parser() {
   this.debugZone = "protocol4";
 
   this.protocol4RegExp_ = new RegExp("([^:]+):\\d+:(.*)$");
   this.newlineRegExp_ = new RegExp("(\\r)?\\n");
 }
 
 /**
  * Create a map from a protocol4 string. Silently skips invalid lines.
@@ -75,17 +75,17 @@ G_Protocol4Parser.prototype.serialize = 
   
   return text;
 }
 
 #ifdef DEBUG
 /**
  * Cheesey unittests
  */
-function TEST_G_Protocol4Parser() {
+this.TEST_G_Protocol4Parser = function TEST_G_Protocol4Parser() {
   if (G_GDEBUG) {
     var z = "protocol4 UNITTEST";
     G_debugService.enableZone(z);
 
     G_Debug(z, "Starting");
 
     var p = new G_Protocol4Parser();
     
--- a/toolkit/components/url-classifier/content/multi-querier.js
+++ b/toolkit/components/url-classifier/content/multi-querier.js
@@ -10,16 +10,17 @@
  * This is an "Abstract" base class.  Subclasses need to supply
  * the condition_ method.
  *
  * @param tokens Array of strings to lookup in the db
  * @param tableName String name of the table
  * @param callback Function callback function that takes true if the condition
  *        passes.
  */
+this.MultiQuerier =
 function MultiQuerier(tokens, tableName, callback) {
   this.tokens_ = tokens;
   this.tableName_ = tableName;
   this.callback_ = callback;
   this.dbservice_ = Cc["@mozilla.org/url-classifier/dbservice;1"]
                     .getService(Ci.nsIUrlClassifierDBService);
   // We put the current token in this variable.
   this.key_ = null;
@@ -60,38 +61,54 @@ MultiQuerier.prototype.result_ = functio
 MultiQuerier.prototype.condition_ = function(value) {
   throw "MultiQuerier is an abstract base class";
 }
 
 
 /**
  * Concrete MultiQuerier that stops if the key exists in the db.
  */
+this.ExistsMultiQuerier =
 function ExistsMultiQuerier(tokens, tableName, callback) {
   MultiQuerier.call(this, tokens, tableName, callback);
   this.debugZone = "existsMultiQuerier";
 }
+
+ExistsMultiQuerier.inherits = function(parentCtor) {
+  var tempCtor = function(){};
+  tempCtor.prototype = parentCtor.prototype;
+  this.superClass_ = parentCtor.prototype;
+  this.prototype = new tempCtor();
+}
 ExistsMultiQuerier.inherits(MultiQuerier);
 
 ExistsMultiQuerier.prototype.condition_ = function(value) {
   return value.length > 0;
 }
 
 
 /**
  * Concrete MultiQuerier that looks up a key, decrypts it, then
  * checks the the resulting regular expressions for a match.
  * @param tokens Array of hosts
  */
+this.EnchashMultiQuerier =
 function EnchashMultiQuerier(tokens, tableName, callback, url) {
   MultiQuerier.call(this, tokens, tableName, callback);
   this.url_ = url;
   this.enchashDecrypter_ = new PROT_EnchashDecrypter();
   this.debugZone = "enchashMultiQuerier";
 }
+
+EnchashMultiQuerier.inherits = function(parentCtor) {
+  var tempCtor = function(){};
+  tempCtor.prototype = parentCtor.prototype;
+  this.superClass_ = parentCtor.prototype;
+  this.prototype = new tempCtor();
+}
 EnchashMultiQuerier.inherits(MultiQuerier);
 
 EnchashMultiQuerier.prototype.run = function() {
   if (this.tokens_.length == 0) {
     this.callback_.handleEvent(false);
     this.dbservice_ = null;
     this.callback_ = null;
     return;
--- a/toolkit/components/url-classifier/content/request-backoff.js
+++ b/toolkit/components/url-classifier/content/request-backoff.js
@@ -7,30 +7,31 @@
 // back off for TIMEOUT_INCREMENT minutes.  If we get another error
 // immediately after we restart, we double the timeout and add
 // TIMEOUT_INCREMENT minutes, etc.
 // 
 // This is similar to the logic used by the search suggestion service.
 
 // HTTP responses that count as an error.  We also include any 5xx response
 // as an error.
-const HTTP_FOUND                 = 302;
-const HTTP_SEE_OTHER             = 303;
-const HTTP_TEMPORARY_REDIRECT    = 307;
+this.HTTP_FOUND                 = 302;
+this.HTTP_SEE_OTHER             = 303;
+this.HTTP_TEMPORARY_REDIRECT    = 307;
 
 /**
  * @param maxErrors Number of times to request before backing off.
  * @param retryIncrement Time (ms) for each retry before backing off.
  * @param maxRequests Number the number of requests needed to trigger backoff
  * @param requestPeriod Number time (ms) in which maxRequests have to occur to
  *     trigger the backoff behavior (0 to disable maxRequests)
  * @param timeoutIncrement Number time (ms) the starting timeout period
  *     we double this time for consecutive errors
  * @param maxTimeout Number time (ms) maximum timeout period
  */
+this.RequestBackoff =
 function RequestBackoff(maxErrors, retryIncrement,
                         maxRequests, requestPeriod,
                         timeoutIncrement, maxTimeout) {
   this.MAX_ERRORS_ = maxErrors;
   this.RETRY_INCREMENT_ = retryIncrement;
   this.MAX_REQUESTS_ = maxRequests;
   this.REQUEST_PERIOD_ = requestPeriod;
   this.TIMEOUT_INCREMENT_ = timeoutIncrement;
--- a/toolkit/components/url-classifier/content/trtable.js
+++ b/toolkit/components/url-classifier/content/trtable.js
@@ -4,17 +4,17 @@
 
 // XXX: This should all be moved into the dbservice class so it happens
 // in the background thread.
 
 /**
  * Abstract base class for a lookup table.
  * @construction
  */
-function UrlClassifierTable() {
+this.UrlClassifierTable = function UrlClassifierTable() {
   this.debugZone = "urlclassifier-table";
   this.name = '';
   this.needsUpdate = false;
   this.enchashDecrypter_ = new PROT_EnchashDecrypter();
   this.wrappedJSObject = this;
 }
 
 UrlClassifierTable.prototype.QueryInterface = function(iid) {
@@ -29,19 +29,26 @@ UrlClassifierTable.prototype.QueryInterf
  * Subclasses need to implement this method.
  */
 UrlClassifierTable.prototype.exists = function(url, callback) {
   throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /////////////////////////////////////////////////////////////////////
 // Url table implementation
-function UrlClassifierTableUrl() {
+this.UrlClassifierTableUrl = function UrlClassifierTableUrl() {
   UrlClassifierTable.call(this);
 }
+
+UrlClassifierTableUrl.inherits = function(parentCtor) {
+  var tempCtor = function(){};
+  tempCtor.prototype = parentCtor.prototype;
+  this.superClass_ = parentCtor.prototype;
+  this.prototype = new tempCtor();
+}
 UrlClassifierTableUrl.inherits(UrlClassifierTable);
 
 /**
  * Look up a URL in a URL table
  */
 UrlClassifierTableUrl.prototype.exists = function(url, callback) {
   // nsIUrlClassifierUtils.canonicalizeURL is the old way of canonicalizing a
   // URL.  Unfortunately, it doesn't normalize numeric domains so alternate IP
@@ -58,22 +65,29 @@ UrlClassifierTableUrl.prototype.exists =
   (new ExistsMultiQuerier([oldCanonicalized, canonicalized],
                           this.name,
                           callback)).run();
 }
 
 /////////////////////////////////////////////////////////////////////
 // Domain table implementation
 
-function UrlClassifierTableDomain() {
+this.UrlClassifierTableDomain = function UrlClassifierTableDomain() {
   UrlClassifierTable.call(this);
   this.debugZone = "urlclassifier-table-domain";
   this.ioService_ = Cc["@mozilla.org/network/io-service;1"]
                     .getService(Ci.nsIIOService);
 }
+
+UrlClassifierTableDomain.inherits = function(parentCtor) {
+  var tempCtor = function(){};
+  tempCtor.prototype = parentCtor.prototype;
+  this.superClass_ = parentCtor.prototype;
+  this.prototype = new tempCtor();
+}
 UrlClassifierTableDomain.inherits(UrlClassifierTable);
 
 /**
  * Look up a URL in a domain table
  * We also try to lookup domain + first path component (e.g.,
  * www.mozilla.org/products).
  *
  * @returns Boolean true if the url domain is in the table
@@ -115,20 +129,27 @@ UrlClassifierTableDomain.prototype.exist
 
   // Run the possible domains against the db.
   (new ExistsMultiQuerier(possible, this.name, callback)).run();
 }
 
 /////////////////////////////////////////////////////////////////////
 // Enchash table implementation
 
-function UrlClassifierTableEnchash() {
+this.UrlClassifierTableEnchash = function UrlClassifierTableEnchash() {
   UrlClassifierTable.call(this);
   this.debugZone = "urlclassifier-table-enchash";
 }
+
+UrlClassifierTableEnchash.inherits = function(parentCtor) {
+  var tempCtor = function(){};
+  tempCtor.prototype = parentCtor.prototype;
+  this.superClass_ = parentCtor.prototype;
+  this.prototype = new tempCtor();
+}
 UrlClassifierTableEnchash.inherits(UrlClassifierTable);
 
 /**
  * Look up a URL in an enchashDB.  We try all sub domains (up to MAX_DOTS).
  */
 UrlClassifierTableEnchash.prototype.exists = function(url, callback) {
   url = this.enchashDecrypter_.getCanonicalUrl(url);
   var host = this.enchashDecrypter_.getCanonicalHost(url,
--- a/toolkit/components/url-classifier/content/wireformat.js
+++ b/toolkit/components/url-classifier/content/wireformat.js
@@ -31,16 +31,17 @@
  * [name-of-table X.Y update?]                
  * ...key/value pairs to add or delete follow...
  * <blank line ends the table>
  *
  * The X.Y is the version number and the optional "update" token means 
  * that the table is a differential from the curent table the extension
  * has. Its absence means that this is a full, new table.
  */
+this.PROT_VersionParser =
 function PROT_VersionParser(type, opt_major, opt_minor, opt_requireMac) {
   this.debugZone = "versionparser";
   this.type = type;
   this.major = 0;
   this.minor = 0;
 
   this.badHeader = false;
 
@@ -197,17 +198,17 @@ PROT_VersionParser.prototype.processOptT
       break;
     }
   }
 
   return true;
 }
 
 #ifdef DEBUG
-function TEST_PROT_WireFormat() {
+this.TEST_PROT_WireFormat = function TEST_PROT_WireFormat() {
   if (G_GDEBUG) {
     var z = "versionparser UNITTEST";
     G_Debug(z, "Starting");
 
     var vp = new PROT_VersionParser("dummy");
     G_Assert(z, vp.fromString("[foo-bar-url 1.234]"),
              "failed to parse old format");
     G_Assert(z, "foo-bar-url" == vp.type, "failed to parse type");
--- a/toolkit/components/url-classifier/content/xml-fetcher.js
+++ b/toolkit/components/url-classifier/content/xml-fetcher.js
@@ -11,17 +11,17 @@
 
 /**
  * Because we might be in a component, we can't just assume that
  * XMLHttpRequest exists. So we use this tiny factory function to wrap the
  * XPCOM version.
  *
  * @return XMLHttpRequest object
  */
-function PROT_NewXMLHttpRequest() {
+this.PROT_NewXMLHttpRequest = function PROT_NewXMLHttpRequest() {
   var Cc = Components.classes;
   var Ci = Components.interfaces;
   var request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
                 .createInstance(Ci.nsIXMLHttpRequest);
   // Need the following so we get onerror/load/progresschange
   request.QueryInterface(Ci.nsIJSXMLHttpRequest);
   return request;
 }
@@ -32,17 +32,17 @@ function PROT_NewXMLHttpRequest() {
  * callback.
  *
  * Note, that XMLFetcher is only used for SafeBrowsing, therefore
  * we inherit from nsILoadContext, so we can use the callbacks on the
  * channel to separate the safebrowsing cookie based on a reserved
  * appId.
  * @constructor
  */
-function PROT_XMLFetcher() {
+this.PROT_XMLFetcher = function PROT_XMLFetcher() {
   this.debugZone = "xmlfetcher";
   this._request = PROT_NewXMLHttpRequest();
   // implements nsILoadContext
   this.appId = Ci.nsIScriptSecurityManager.SAFEBROWSING_APP_ID;
   this.isInBrowserElement = false;
   this.usePrivateBrowsing = false;
   this.isContent = false;
 }
--- a/toolkit/components/url-classifier/nsUrlClassifierListManager.js
+++ b/toolkit/components/url-classifier/nsUrlClassifierListManager.js
@@ -9,17 +9,22 @@ Components.utils.import("resource://gre/
 
 #include ./content/listmanager.js
 
 var modScope = this;
 function Init() {
   // Pull the library in.
   var jslib = Cc["@mozilla.org/url-classifier/jslib;1"]
               .getService().wrappedJSObject;
-  Function.prototype.inherits = jslib.Function.prototype.inherits;
+  Function.prototype.inherits = function(parentCtor) {
+    var tempCtor = function(){};
+    tempCtor.prototype = parentCtor.prototype;
+    this.superClass_ = parentCtor.prototype;
+    this.prototype = new tempCtor();
+  },
   modScope.G_Preferences = jslib.G_Preferences;
   modScope.G_PreferenceObserver = jslib.G_PreferenceObserver;
   modScope.G_ObserverServiceObserver = jslib.G_ObserverServiceObserver;
   modScope.G_Debug = jslib.G_Debug;
   modScope.G_Assert = jslib.G_Assert;
   modScope.G_debugService = jslib.G_debugService;
   modScope.G_Alarm = jslib.G_Alarm;
   modScope.BindToObject = jslib.BindToObject;