Merge b2ginbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Tue, 02 Jun 2015 18:34:21 -0700
changeset 246813 b0a507af2b4ad4f98fb3f73a4406e178f897c68a
parent 246764 20a96e15631afb63521825aefb1faaee9d7bc452 (current diff)
parent 246812 6d67dafa4d0ff8d6c66968097925251604e10f5d (diff)
child 246819 bad6921c051a700878beda47f10b0b4434604b7a
child 246841 db827f2026fb2437d96aa079217275b4f58101e5
child 246877 f8f45198c60f0d7c7ace00a21bfc62f31e276a11
push id28840
push userkwierso@gmail.com
push dateWed, 03 Jun 2015 01:34:22 +0000
treeherdermozilla-central@b0a507af2b4a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone41.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 b2ginbound to central, a=merge
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/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="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
   <!-- 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"/>
--- 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="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
   <!-- 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,21 +14,21 @@
   <!--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="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <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="6d477a7884273886605049b20f60af5c1583a150"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
-  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="22664edc4c73e5fe8f5095ff1d5549db78a2bc10"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="218a5637399d023f4326e12c8a486dad95403b6c"/>
+  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="10b3daf0093db94c64e78a72ac43a93b68976087"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- 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"/>
--- 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="4efd19d199ae52656604f794c5a77518400220fd">
     <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="6d477a7884273886605049b20f60af5c1583a150"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
   <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="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
   <!-- 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"/>
@@ -124,17 +124,17 @@
   <project name="platform/system/vold" path="system/vold" revision="d4455b8cf361f8353e8aebac15ffd64b4aedd2b9"/>
   <project name="platform/external/icu4c" path="external/icu4c" remote="aosp" revision="b4c6379528887dc25ca9991a535a8d92a61ad6b6"/>
   <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="f3cedd7fd9b1649aa5107d466be9078bb7602af6"/>
   <project name="platform_system_core" path="system/core" remote="b2g" revision="9395eb5aa885cf6d305a202de6e9694a58a89717"/>
   <default remote="caf" revision="refs/tags/android-4.4.2_r1" sync-j="4"/>
   <!-- Emulator specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="f390788a00706c06e5248edfd8d27b365387e84a"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d2f58dbee70cba71bd3fad8cdd0fee620d10cf92"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c4d9746e5f1a3a2e6cb53d59d5d721e9888cd2e1"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
   <project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/>
-  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="42f61f665e7a9857da8cd14b455e15bae98e6b44"/>
+  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="de4bfffbbc2aabe5b5eca485e459da75e49097e2"/>
   <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d82e00fb6380b4f6cea7a96213913ee9eb441239"/>
   <project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
   <project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
 </manifest>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-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="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
   <!-- 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="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
   <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="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
   <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="8af5ff6f5dced9eb5a8127459df6c75d24342204"/>
   <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="30915518fa7ea07166efedc191a4f40aef516fe7"/>
   <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="96eee58e3389fb05a835310d6a06a6ba4486097a"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" revision="7c8a46698171aa2e0be09edb43d15a6acf832770"/>
   <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="24b2038be8a636fd4a5d21f0abae1e466b07bcf7"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,21 +14,21 @@
   <!--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="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <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="6d477a7884273886605049b20f60af5c1583a150"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
-  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="22664edc4c73e5fe8f5095ff1d5549db78a2bc10"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="218a5637399d023f4326e12c8a486dad95403b6c"/>
+  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="10b3daf0093db94c64e78a72ac43a93b68976087"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- 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"/>
--- 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="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
   <!-- 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"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "6d477a7884273886605049b20f60af5c1583a150", 
+        "git_revision": "9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "c7beef2b034d2308a85e8c866395c78245bc554f", 
+    "revision": "d5e509fd9697316bcbc267413a30478dcd4dbca9", 
     "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="4efd19d199ae52656604f794c5a77518400220fd">
     <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="6d477a7884273886605049b20f60af5c1583a150"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
   <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="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <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="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
   <!-- 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="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
   <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="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
   <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="8af5ff6f5dced9eb5a8127459df6c75d24342204"/>
   <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="30915518fa7ea07166efedc191a4f40aef516fe7"/>
   <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="96eee58e3389fb05a835310d6a06a6ba4486097a"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" revision="7c8a46698171aa2e0be09edb43d15a6acf832770"/>
   <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="24b2038be8a636fd4a5d21f0abae1e466b07bcf7"/>
--- a/dom/bluetooth/bluedroid/BluetoothGattManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothGattManager.cpp
@@ -517,18 +517,17 @@ public:
       BluetoothGattManager* gattManager = BluetoothGattManager::Get();
       NS_ENSURE_TRUE_VOID(gattManager);
 
       nsRefPtr<BluetoothVoidReplyRunnable> result =
         new BluetoothVoidReplyRunnable(nullptr);
       gattManager->UnregisterClient(mClient->mClientIf, result);
     }
 
-    DispatchReplyError(mClient->mStartLeScanRunnable,
-                       BluetoothValue(mClient->mAppUuid));
+    DispatchReplyError(mClient->mStartLeScanRunnable, aStatus);
     mClient->mStartLeScanRunnable = nullptr;
   }
 
 private:
   nsRefPtr<BluetoothGattClient> mClient;
 };
 
 class BluetoothGattManager::StopLeScanResultHandler final
--- a/dom/bluetooth/bluedroid/BluetoothSocket.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothSocket.cpp
@@ -69,26 +69,29 @@ public:
    */
   enum ConnectionStatus {
     SOCKET_IS_DISCONNECTED = 0,
     SOCKET_IS_LISTENING,
     SOCKET_IS_CONNECTING,
     SOCKET_IS_CONNECTED
   };
 
-  DroidSocketImpl(MessageLoop* aIOLoop, BluetoothSocket* aConsumer)
+  DroidSocketImpl(nsIThread* aConsumerThread,
+                  MessageLoop* aIOLoop,
+                  BluetoothSocket* aConsumer)
     : ipc::UnixFdWatcher(aIOLoop)
+    , DataSocketIO(aConsumerThread)
     , mConsumer(aConsumer)
     , mShuttingDownOnIOThread(false)
     , mConnectionStatus(SOCKET_IS_DISCONNECTED)
   { }
 
   ~DroidSocketImpl()
   {
-    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(IsConsumerThread());
   }
 
   void Send(UnixSocketIOBuffer* aBuffer)
   {
     EnqueueData(aBuffer);
     AddWatchers(WRITE_WATCHER, false);
   }
 
@@ -115,18 +118,18 @@ public:
 
   DataSocket* GetDataSocket()
   {
     return GetBluetoothSocket();
   }
 
   /**
    * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
-   * directly from main thread. All non-main-thread accesses should happen with
-   * mImpl as container.
+   * directly from consumer thread. All non-consumer-thread accesses should
+   * happen with mImpl as container.
    */
   RefPtr<BluetoothSocket> mConsumer;
 
   // Methods for |DataSocket|
   //
 
   nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer);
   void ConsumeBuffer();
@@ -135,37 +138,39 @@ public:
   // Methods for |SocketIOBase|
   //
 
   SocketBase* GetSocketBase() override
   {
     return GetDataSocket();
   }
 
-  bool IsShutdownOnMainThread() const override
+  bool IsShutdownOnConsumerThread() const override
   {
-    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(IsConsumerThread());
+
     return mConsumer == nullptr;
   }
 
   bool IsShutdownOnIOThread() const override
   {
     return mShuttingDownOnIOThread;
   }
 
-  void ShutdownOnMainThread() override
+  void ShutdownOnConsumerThread() override
   {
-    MOZ_ASSERT(NS_IsMainThread());
-    MOZ_ASSERT(!IsShutdownOnMainThread());
+    MOZ_ASSERT(IsConsumerThread());
+    MOZ_ASSERT(!IsShutdownOnConsumerThread());
+
     mConsumer = nullptr;
   }
 
   void ShutdownOnIOThread() override
   {
-    MOZ_ASSERT(!NS_IsMainThread());
+    MOZ_ASSERT(!IsConsumerThread());
     MOZ_ASSERT(!mShuttingDownOnIOThread);
 
     Close(); // will also remove fd from I/O loop
     mShuttingDownOnIOThread = true;
   }
 
 private:
   class ReceiveRunnable;
@@ -209,17 +214,17 @@ class SocketConnectTask final : public S
 public:
   SocketConnectTask(DroidSocketImpl* aDroidSocketImpl, int aFd)
   : SocketIOTask<DroidSocketImpl>(aDroidSocketImpl)
   , mFd(aFd)
   { }
 
   void Run() override
   {
-    MOZ_ASSERT(!NS_IsMainThread());
+    MOZ_ASSERT(!GetIO()->IsConsumerThread());
     MOZ_ASSERT(!IsCanceled());
 
     GetIO()->Connect(mFd);
   }
 
 private:
   int mFd;
 };
@@ -229,17 +234,17 @@ class SocketListenTask final : public So
 public:
   SocketListenTask(DroidSocketImpl* aDroidSocketImpl, int aFd)
   : SocketIOTask<DroidSocketImpl>(aDroidSocketImpl)
   , mFd(aFd)
   { }
 
   void Run() override
   {
-    MOZ_ASSERT(!NS_IsMainThread());
+    MOZ_ASSERT(!GetIO()->IsConsumerThread());
 
     if (!IsCanceled()) {
       GetIO()->Listen(mFd);
     }
   }
 
 private:
   int mFd;
@@ -249,17 +254,17 @@ class SocketConnectClientFdTask final
 : public SocketIOTask<DroidSocketImpl>
 {
   SocketConnectClientFdTask(DroidSocketImpl* aImpl)
   : SocketIOTask<DroidSocketImpl>(aImpl)
   { }
 
   void Run() override
   {
-    MOZ_ASSERT(!NS_IsMainThread());
+    MOZ_ASSERT(!GetIO()->IsConsumerThread());
 
     GetIO()->ConnectClientFd();
   }
 };
 
 void
 DroidSocketImpl::Connect(int aFd)
 {
@@ -309,18 +314,19 @@ DroidSocketImpl::Accept(int aFd)
   if (!(flags & O_NONBLOCK)) {
     int res = TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, flags | O_NONBLOCK));
     NS_ENSURE_TRUE_VOID(!res);
   }
 
   SetFd(aFd);
   mConnectionStatus = SOCKET_IS_CONNECTED;
 
-  NS_DispatchToMainThread(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
+  GetConsumerThread()->Dispatch(
+    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
+    NS_DISPATCH_NORMAL);
 
   AddWatchers(READ_WATCHER, true);
   if (HasPendingData()) {
     AddWatchers(WRITE_WATCHER, false);
   }
 }
 
 void
@@ -333,17 +339,17 @@ DroidSocketImpl::OnFileCanReadWithoutBlo
   } else {
     NS_NOTREACHED("invalid connection state for reading");
   }
 }
 
 void
 DroidSocketImpl::OnSocketCanReceiveWithoutBlocking(int aFd)
 {
-  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(!IsConsumerThread());
   MOZ_ASSERT(!mShuttingDownOnIOThread);
 
   ssize_t res = ReceiveData(aFd);
   if (res < 0) {
     /* I/O error */
     RemoveWatchers(READ_WATCHER|WRITE_WATCHER);
   } else if (!res) {
     /* EOF or peer shutdown */
@@ -356,17 +362,17 @@ class AcceptTask final : public SocketIO
 public:
   AcceptTask(DroidSocketImpl* aDroidSocketImpl, int aFd)
   : SocketIOTask<DroidSocketImpl>(aDroidSocketImpl)
   , mFd(aFd)
   { }
 
   void Run() override
   {
-    MOZ_ASSERT(!NS_IsMainThread());
+    MOZ_ASSERT(!GetIO()->IsConsumerThread());
     MOZ_ASSERT(!IsCanceled());
 
     GetIO()->Accept(mFd);
   }
 
 private:
   int mFd;
 };
@@ -378,41 +384,41 @@ public:
   : mImpl(aImpl)
   {
     MOZ_ASSERT(mImpl);
   }
 
   void Accept(int aFd, const nsAString& aBdAddress,
               int aConnectionStatus) override
   {
-    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(mImpl->IsConsumerThread());
 
     mozilla::ScopedClose fd(aFd); // Close received socket fd on error
 
-    if (mImpl->IsShutdownOnMainThread()) {
+    if (mImpl->IsShutdownOnConsumerThread()) {
       BT_LOGD("mConsumer is null, aborting receive!");
       return;
     }
 
     if (aConnectionStatus != 0) {
       mImpl->mConsumer->NotifyError();
       return;
     }
 
     mImpl->mConsumer->SetAddress(aBdAddress);
-    XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
-                                     new AcceptTask(mImpl, fd.forget()));
+    mImpl->GetIOLoop()->PostTask(FROM_HERE,
+                                 new AcceptTask(mImpl, fd.forget()));
   }
 
   void OnError(BluetoothStatus aStatus) override
   {
-    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(mImpl->IsConsumerThread());
     BT_LOGR("BluetoothSocketInterface::Accept failed: %d", (int)aStatus);
 
-    if (!mImpl->IsShutdownOnMainThread()) {
+    if (!mImpl->IsShutdownOnConsumerThread()) {
       // Instead of NotifyError(), call NotifyDisconnect() to trigger
       // BluetoothOppManager::OnSocketDisconnect() as
       // DroidSocketImpl::OnFileCanReadWithoutBlocking() in Firefox OS 2.0 in
       // order to keep the same behavior and reduce regression risk.
       mImpl->mConsumer->NotifyDisconnect();
     }
   }
 
@@ -425,17 +431,17 @@ class AcceptRunnable final : public Sock
 public:
   AcceptRunnable(DroidSocketImpl* aImpl, int aFd)
   : SocketIORunnable<DroidSocketImpl>(aImpl)
   , mFd(aFd)
   { }
 
   NS_IMETHOD Run() override
   {
-    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(GetIO()->IsConsumerThread());
     MOZ_ASSERT(sBluetoothSocketInterface);
 
     BluetoothSocketResultHandler* res = new AcceptResultHandler(GetIO());
     GetIO()->mConsumer->SetCurrentResultHandler(res);
 
     sBluetoothSocketInterface->Accept(mFd, res);
 
     return NS_OK;
@@ -443,26 +449,26 @@ public:
 
 private:
   int mFd;
 };
 
 void
 DroidSocketImpl::OnSocketCanAcceptWithoutBlocking(int aFd)
 {
-  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(!IsConsumerThread());
   MOZ_ASSERT(!mShuttingDownOnIOThread);
 
   /* When a listening socket is ready for receiving data,
    * we can call |Accept| on it.
    */
 
   RemoveWatchers(READ_WATCHER);
-  nsRefPtr<AcceptRunnable> t = new AcceptRunnable(this, aFd);
-  NS_DispatchToMainThread(t);
+  GetConsumerThread()->Dispatch(new AcceptRunnable(this, aFd),
+                                NS_DISPATCH_NORMAL);
 }
 
 void
 DroidSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
 {
   if (mConnectionStatus == SOCKET_IS_CONNECTED) {
     OnSocketCanSendWithoutBlocking(aFd);
   } else if (mConnectionStatus == SOCKET_IS_CONNECTING) {
@@ -470,44 +476,45 @@ DroidSocketImpl::OnFileCanWriteWithoutBl
   } else {
     NS_NOTREACHED("invalid connection state for writing");
   }
 }
 
 void
 DroidSocketImpl::OnSocketCanSendWithoutBlocking(int aFd)
 {
-  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(!IsConsumerThread());
   MOZ_ASSERT(!mShuttingDownOnIOThread);
   MOZ_ASSERT(aFd >= 0);
 
   nsresult rv = SendPendingData(aFd);
   if (NS_FAILED(rv)) {
     return;
   }
 
   if (HasPendingData()) {
     AddWatchers(WRITE_WATCHER, false);
   }
 }
 
 void
 DroidSocketImpl::OnSocketCanConnectWithoutBlocking(int aFd)
 {
-  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(!IsConsumerThread());
   MOZ_ASSERT(!mShuttingDownOnIOThread);
 
   /* We follow Posix behaviour here: Connect operations are
    * complete once we can write to the connecting socket.
    */
 
   mConnectionStatus = SOCKET_IS_CONNECTED;
 
-  NS_DispatchToMainThread(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
+  GetConsumerThread()->Dispatch(
+    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
+    NS_DISPATCH_NORMAL);
 
   AddWatchers(READ_WATCHER, true);
   if (HasPendingData()) {
     AddWatchers(WRITE_WATCHER, false);
   }
 }
 
 // |DataSocketIO|
@@ -523,34 +530,34 @@ DroidSocketImpl::QueryReceiveBuffer(
   }
   *aBuffer = mBuffer.get();
 
   return NS_OK;
 }
 
 /**
  * |ReceiveRunnable| transfers data received on the I/O thread
- * to an instance of |BluetoothSocket| on the main thread.
+ * to an instance of |BluetoothSocket| on the consumer thread.
  */
 class DroidSocketImpl::ReceiveRunnable final
   : public SocketIORunnable<DroidSocketImpl>
 {
 public:
   ReceiveRunnable(DroidSocketImpl* aIO, UnixSocketBuffer* aBuffer)
     : SocketIORunnable<DroidSocketImpl>(aIO)
     , mBuffer(aBuffer)
   { }
 
   NS_IMETHOD Run() override
   {
-    MOZ_ASSERT(NS_IsMainThread());
-
     DroidSocketImpl* io = SocketIORunnable<DroidSocketImpl>::GetIO();
 
-    if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
+    MOZ_ASSERT(io->IsConsumerThread());
+
+    if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
       // Since we've already explicitly closed and the close
       // happened before this, this isn't really an error.
       return NS_OK;
     }
 
     BluetoothSocket* bluetoothSocket = io->GetBluetoothSocket();
     MOZ_ASSERT(bluetoothSocket);
 
@@ -561,17 +568,18 @@ public:
 
 private:
   nsAutoPtr<UnixSocketBuffer> mBuffer;
 };
 
 void
 DroidSocketImpl::ConsumeBuffer()
 {
-  NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget()));
+  GetConsumerThread()->Dispatch(new ReceiveRunnable(this, mBuffer.forget()),
+                                NS_DISPATCH_NORMAL);
 }
 
 void
 DroidSocketImpl::DiscardBuffer()
 {
   // Nothing to do.
 }
 
@@ -597,39 +605,39 @@ public:
   : mImpl(aImpl)
   {
     MOZ_ASSERT(mImpl);
   }
 
   void Connect(int aFd, const nsAString& aBdAddress,
                int aConnectionStatus) override
   {
-    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(mImpl->IsConsumerThread());
 
-    if (mImpl->IsShutdownOnMainThread()) {
+    if (mImpl->IsShutdownOnConsumerThread()) {
       BT_LOGD("mConsumer is null, aborting send!");
       return;
     }
 
     if (aConnectionStatus != 0) {
       mImpl->mConsumer->NotifyError();
       return;
     }
 
     mImpl->mConsumer->SetAddress(aBdAddress);
-    XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
-                                     new SocketConnectTask(mImpl, aFd));
+    mImpl->GetIOLoop()->PostTask(FROM_HERE,
+                                 new SocketConnectTask(mImpl, aFd));
   }
 
   void OnError(BluetoothStatus aStatus) override
   {
-    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(mImpl->IsConsumerThread());
     BT_WARNING("Connect failed: %d", (int)aStatus);
 
-    if (!mImpl->IsShutdownOnMainThread()) {
+    if (!mImpl->IsShutdownOnConsumerThread()) {
       // Instead of NotifyError(), call NotifyDisconnect() to trigger
       // BluetoothOppManager::OnSocketDisconnect() as
       // DroidSocketImpl::OnFileCanReadWithoutBlocking() in Firefox OS 2.0 in
       // order to keep the same behavior and reduce regression risk.
       mImpl->mConsumer->NotifyDisconnect();
     }
   }
 
@@ -637,159 +645,190 @@ private:
   DroidSocketImpl* mImpl;
 };
 
 nsresult
 BluetoothSocket::Connect(const nsAString& aDeviceAddress,
                          const BluetoothUuid& aServiceUuid,
                          BluetoothSocketType aType,
                          int aChannel,
-                         bool aAuth, bool aEncrypt)
+                         bool aAuth, bool aEncrypt,
+                         nsIThread* aConsumerThread,
+                         MessageLoop* aIOLoop)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mImpl);
 
   SetConnectionStatus(SOCKET_CONNECTING);
 
-  mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this);
+  mImpl = new DroidSocketImpl(aConsumerThread, aIOLoop, this);
 
   BluetoothSocketResultHandler* res = new ConnectSocketResultHandler(mImpl);
   SetCurrentResultHandler(res);
 
   sBluetoothSocketInterface->Connect(
     aDeviceAddress, aType,
     aServiceUuid.mUuid, aChannel,
     aEncrypt, aAuth, res);
 
   return NS_OK;
 }
 
+nsresult
+BluetoothSocket::Connect(const nsAString& aDeviceAddress,
+                         const BluetoothUuid& aServiceUuid,
+                         BluetoothSocketType aType,
+                         int aChannel,
+                         bool aAuth, bool aEncrypt)
+{
+  nsIThread* consumerThread = nullptr;
+  nsresult rv = NS_GetCurrentThread(&consumerThread);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  return Connect(aDeviceAddress, aServiceUuid, aType, aChannel, aAuth,
+                 aEncrypt, consumerThread, XRE_GetIOMessageLoop());
+}
+
 class ListenResultHandler final : public BluetoothSocketResultHandler
 {
 public:
   ListenResultHandler(DroidSocketImpl* aImpl)
   : mImpl(aImpl)
   {
     MOZ_ASSERT(mImpl);
   }
 
   void Listen(int aFd) override
   {
-    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(mImpl->IsConsumerThread());
 
-    XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
-                                     new SocketListenTask(mImpl, aFd));
+    mImpl->GetIOLoop()->PostTask(FROM_HERE, new SocketListenTask(mImpl, aFd));
   }
 
   void OnError(BluetoothStatus aStatus) override
   {
-    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(mImpl->IsConsumerThread());
 
     BT_WARNING("Listen failed: %d", (int)aStatus);
   }
 
 private:
   DroidSocketImpl* mImpl;
 };
 
 nsresult
 BluetoothSocket::Listen(const nsAString& aServiceName,
                         const BluetoothUuid& aServiceUuid,
                         BluetoothSocketType aType,
                         int aChannel,
-                        bool aAuth, bool aEncrypt)
+                        bool aAuth, bool aEncrypt,
+                        nsIThread* aConsumerThread,
+                        MessageLoop* aIOLoop)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mImpl);
 
   SetConnectionStatus(SOCKET_LISTENING);
 
-  mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this);
+  mImpl = new DroidSocketImpl(aConsumerThread, aIOLoop, this);
 
   BluetoothSocketResultHandler* res = new ListenResultHandler(mImpl);
   SetCurrentResultHandler(res);
 
   sBluetoothSocketInterface->Listen(
     aType,
     aServiceName, aServiceUuid.mUuid, aChannel,
     aEncrypt, aAuth, res);
 
   return NS_OK;
 }
 
+nsresult
+BluetoothSocket::Listen(const nsAString& aServiceName,
+                        const BluetoothUuid& aServiceUuid,
+                        BluetoothSocketType aType,
+                        int aChannel,
+                        bool aAuth, bool aEncrypt)
+{
+  nsIThread* consumerThread = nullptr;
+  nsresult rv = NS_GetCurrentThread(&consumerThread);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  return Listen(aServiceName, aServiceUuid, aType, aChannel, aAuth, aEncrypt,
+                consumerThread, XRE_GetIOMessageLoop());
+}
+
 void
 BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mObserver);
 
   mObserver->ReceiveSocketData(this, aBuffer);
 }
 
 // |DataSocket|
 
 void
 BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mImpl);
-  MOZ_ASSERT(!mImpl->IsShutdownOnMainThread());
+  MOZ_ASSERT(mImpl->IsConsumerThread());
+  MOZ_ASSERT(!mImpl->IsShutdownOnConsumerThread());
 
-  XRE_GetIOMessageLoop()->PostTask(
+  mImpl->GetIOLoop()->PostTask(
     FROM_HERE,
     new SocketIOSendTask<DroidSocketImpl, UnixSocketIOBuffer>(mImpl, aBuffer));
 }
 
 // |SocketBase|
 
 void
 BluetoothSocket::Close()
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(sBluetoothSocketInterface);
+
   if (!mImpl) {
     return;
   }
 
+  MOZ_ASSERT(mImpl->IsConsumerThread());
+
   // Stop any watching |SocketMessageWatcher|
   if (mCurrentRes) {
     sBluetoothSocketInterface->Close(mCurrentRes);
   }
 
   // From this point on, we consider mImpl as being deleted.
   // We sever the relationship here so any future calls to listen or connect
   // will create a new implementation.
-  mImpl->ShutdownOnMainThread();
-
-  XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mImpl));
-
+  mImpl->ShutdownOnConsumerThread();
+  mImpl->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mImpl));
   mImpl = nullptr;
 
   NotifyDisconnect();
 }
 
 void
 BluetoothSocket::OnConnectSuccess()
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mObserver);
 
   SetCurrentResultHandler(nullptr);
   mObserver->OnSocketConnectSuccess(this);
 }
 
 void
 BluetoothSocket::OnConnectError()
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mObserver);
 
   SetCurrentResultHandler(nullptr);
   mObserver->OnSocketConnectError(this);
 }
 
 void
 BluetoothSocket::OnDisconnect()
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mObserver);
   mObserver->OnSocketDisconnect(this);
 }
--- a/dom/bluetooth/bluedroid/BluetoothSocket.h
+++ b/dom/bluetooth/bluedroid/BluetoothSocket.h
@@ -5,42 +5,61 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_BluetoothSocket_h
 #define mozilla_dom_bluetooth_BluetoothSocket_h
 
 #include "BluetoothCommon.h"
 #include "mozilla/ipc/DataSocket.h"
 
+class MessageLoop;
+class nsIThread;
+
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothSocketObserver;
 class BluetoothSocketResultHandler;
 class DroidSocketImpl;
 
 class BluetoothSocket final : public mozilla::ipc::DataSocket
 {
 public:
   BluetoothSocket(BluetoothSocketObserver* aObserver);
 
   nsresult Connect(const nsAString& aDeviceAddress,
                    const BluetoothUuid& aServiceUuid,
                    BluetoothSocketType aType,
                    int aChannel,
+                   bool aAuth, bool aEncrypt,
+                   nsIThread* aConsumerThread,
+                   MessageLoop* aIOLoop);
+
+  nsresult Connect(const nsAString& aDeviceAddress,
+                   const BluetoothUuid& aServiceUuid,
+                   BluetoothSocketType aType,
+                   int aChannel,
                    bool aAuth, bool aEncrypt);
 
   nsresult Listen(const nsAString& aServiceName,
                   const BluetoothUuid& aServiceUuid,
                   BluetoothSocketType aType,
                   int aChannel,
+                  bool aAuth, bool aEncrypt,
+                  nsIThread* aConsumerThread,
+                  MessageLoop* aIOLoop);
+
+  nsresult Listen(const nsAString& aServiceName,
+                  const BluetoothUuid& aServiceUuid,
+                  BluetoothSocketType aType,
+                  int aChannel,
                   bool aAuth, bool aEncrypt);
 
   /**
    * Method to be called whenever data is received. This is only called on the
-   * main thread.
+   * consumer thread.
    *
    * @param aBuffer Data received from the socket.
    */
   void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketBuffer>& aBuffer);
 
   inline void GetAddress(nsAString& aDeviceAddress)
   {
     aDeviceAddress = mDeviceAddress;
--- a/dom/bluetooth/bluez/BluetoothSocket.cpp
+++ b/dom/bluetooth/bluez/BluetoothSocket.cpp
@@ -23,17 +23,18 @@ static const size_t MAX_READ_SIZE = 1 <<
 // BluetoothSocketIO
 //
 
 class BluetoothSocket::BluetoothSocketIO final
   : public UnixSocketWatcher
   , public DataSocketIO
 {
 public:
-  BluetoothSocketIO(MessageLoop* mIOLoop,
+  BluetoothSocketIO(nsIThread* aConsumerThread,
+                    MessageLoop* aIOLoop,
                     BluetoothSocket* aConsumer,
                     UnixSocketConnector* aConnector);
   ~BluetoothSocketIO();
 
   void GetSocketAddr(nsAString& aAddrStr) const;
 
   BluetoothSocket* GetBluetoothSocket();
   DataSocket* GetDataSocket();
@@ -77,31 +78,31 @@ public:
   void ConsumeBuffer();
   void DiscardBuffer();
 
   // Methods for |SocketIOBase|
   //
 
   SocketBase* GetSocketBase() override;
 
-  bool IsShutdownOnMainThread() const override;
+  bool IsShutdownOnConsumerThread() const override;
   bool IsShutdownOnIOThread() const override;
 
-  void ShutdownOnMainThread() override;
+  void ShutdownOnConsumerThread() override;
   void ShutdownOnIOThread() override;
 
 private:
   class ReceiveRunnable;
 
   void FireSocketError();
 
   /**
    * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
-   * directly from main thread. All non-main-thread accesses should happen with
-   * mIO as container.
+   * directly from consumer thread. All non-consumer-thread accesses should
+   * happen with mIO as container.
    */
   RefPtr<BluetoothSocket> mConsumer;
 
   /**
    * Connector object used to create the connection we are currently using.
    */
   nsAutoPtr<UnixSocketConnector> mConnector;
 
@@ -116,45 +117,48 @@ private:
   socklen_t mAddressLength;
 
   /**
    * Address structure of the socket currently in use
    */
   struct sockaddr_storage mAddress;
 
   /**
-   * Task member for delayed connect task. Should only be access on main thread.
+   * Task member for delayed connect task. Should only be access on consumer
+   * thread.
    */
   CancelableTask* mDelayedConnectTask;
 
   /**
    * I/O buffer for received data
    */
   nsAutoPtr<UnixSocketRawData> mBuffer;
 };
 
 BluetoothSocket::BluetoothSocketIO::BluetoothSocketIO(
-  MessageLoop* mIOLoop,
+  nsIThread* aConsumerThread,
+  MessageLoop* aIOLoop,
   BluetoothSocket* aConsumer,
   UnixSocketConnector* aConnector)
-  : UnixSocketWatcher(mIOLoop)
+  : UnixSocketWatcher(aIOLoop)
+  , DataSocketIO(aConsumerThread)
   , mConsumer(aConsumer)
   , mConnector(aConnector)
   , mShuttingDownOnIOThread(false)
   , mAddressLength(0)
   , mDelayedConnectTask(nullptr)
 {
   MOZ_ASSERT(mConsumer);
   MOZ_ASSERT(mConnector);
 }
 
 BluetoothSocket::BluetoothSocketIO::~BluetoothSocketIO()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(IsShutdownOnMainThread());
+  MOZ_ASSERT(IsConsumerThread());
+  MOZ_ASSERT(IsShutdownOnConsumerThread());
 }
 
 void
 BluetoothSocket::BluetoothSocketIO::GetSocketAddr(nsAString& aAddrStr) const
 {
   if (!mConnector) {
     NS_WARNING("No connector to get socket address from!");
     aAddrStr.Truncate();
@@ -183,33 +187,33 @@ DataSocket*
 BluetoothSocket::BluetoothSocketIO::GetDataSocket()
 {
   return GetBluetoothSocket();
 }
 
 void
 BluetoothSocket::BluetoothSocketIO::SetDelayedConnectTask(CancelableTask* aTask)
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsConsumerThread());
 
   mDelayedConnectTask = aTask;
 }
 
 void
 BluetoothSocket::BluetoothSocketIO::ClearDelayedConnectTask()
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsConsumerThread());
 
   mDelayedConnectTask = nullptr;
 }
 
 void
 BluetoothSocket::BluetoothSocketIO::CancelDelayedConnectTask()
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsConsumerThread());
 
   if (!mDelayedConnectTask) {
     return;
   }
 
   mDelayedConnectTask->Cancel();
   ClearDelayedConnectTask();
 }
@@ -272,18 +276,19 @@ BluetoothSocket::BluetoothSocketIO::Send
 }
 
 void
 BluetoothSocket::BluetoothSocketIO::OnConnected()
 {
   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
   MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
 
-  NS_DispatchToMainThread(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
+  GetConsumerThread()->Dispatch(
+    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
+    NS_DISPATCH_NORMAL);
 
   AddWatchers(READ_WATCHER, true);
   if (HasPendingData()) {
     AddWatchers(WRITE_WATCHER, false);
   }
 }
 
 void
@@ -321,18 +326,19 @@ BluetoothSocket::BluetoothSocketIO::OnSo
   if (NS_WARN_IF(NS_FAILED(rv))) {
     FireSocketError();
     return;
   }
 
   Close();
   SetSocket(fd, SOCKET_IS_CONNECTED);
 
-  NS_DispatchToMainThread(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
+  GetConsumerThread()->Dispatch(
+    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
+    NS_DISPATCH_NORMAL);
 
   AddWatchers(READ_WATCHER, true);
   if (HasPendingData()) {
     AddWatchers(WRITE_WATCHER, false);
   }
 }
 
 void
@@ -370,19 +376,20 @@ BluetoothSocket::BluetoothSocketIO::OnSo
 void
 BluetoothSocket::BluetoothSocketIO::FireSocketError()
 {
   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
 
   // Clean up watchers, statuses, fds
   Close();
 
-  // Tell the main thread we've errored
-  NS_DispatchToMainThread(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR));
+  // Tell the consumer thread we've errored
+  GetConsumerThread()->Dispatch(
+    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
+    NS_DISPATCH_NORMAL);
 
 }
 
 // |DataSocketIO|
 
 nsresult
 BluetoothSocket::BluetoothSocketIO::QueryReceiveBuffer(
   UnixSocketIOBuffer** aBuffer)
@@ -394,34 +401,34 @@ BluetoothSocket::BluetoothSocketIO::Quer
   }
   *aBuffer = mBuffer.get();
 
   return NS_OK;
 }
 
 /**
  * |ReceiveRunnable| transfers data received on the I/O thread
- * to an instance of |BluetoothSocket| on the main thread.
+ * to an instance of |BluetoothSocket| on the consumer thread.
  */
 class BluetoothSocket::BluetoothSocketIO::ReceiveRunnable final
   : public SocketIORunnable<BluetoothSocketIO>
 {
 public:
   ReceiveRunnable(BluetoothSocketIO* aIO, UnixSocketBuffer* aBuffer)
     : SocketIORunnable<BluetoothSocketIO>(aIO)
     , mBuffer(aBuffer)
   { }
 
   NS_IMETHOD Run() override
   {
-    MOZ_ASSERT(NS_IsMainThread());
-
     BluetoothSocketIO* io = SocketIORunnable<BluetoothSocketIO>::GetIO();
 
-    if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
+    MOZ_ASSERT(io->IsConsumerThread());
+
+    if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
       // Since we've already explicitly closed and the close
       // happened before this, this isn't really an error.
       return NS_OK;
     }
 
     BluetoothSocket* bluetoothSocket = io->GetBluetoothSocket();
     MOZ_ASSERT(bluetoothSocket);
 
@@ -432,17 +439,18 @@ public:
 
 private:
   nsAutoPtr<UnixSocketBuffer> mBuffer;
 };
 
 void
 BluetoothSocket::BluetoothSocketIO::ConsumeBuffer()
 {
-  NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget()));
+  GetConsumerThread()->Dispatch(new ReceiveRunnable(this, mBuffer.forget()),
+                                NS_DISPATCH_NORMAL);
 }
 
 void
 BluetoothSocket::BluetoothSocketIO::DiscardBuffer()
 {
   // Nothing to do.
 }
 
@@ -450,42 +458,42 @@ BluetoothSocket::BluetoothSocketIO::Disc
 
 SocketBase*
 BluetoothSocket::BluetoothSocketIO::GetSocketBase()
 {
   return GetDataSocket();
 }
 
 bool
-BluetoothSocket::BluetoothSocketIO::IsShutdownOnMainThread() const
+BluetoothSocket::BluetoothSocketIO::IsShutdownOnConsumerThread() const
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsConsumerThread());
 
   return mConsumer == nullptr;
 }
 
 void
-BluetoothSocket::BluetoothSocketIO::ShutdownOnMainThread()
+BluetoothSocket::BluetoothSocketIO::ShutdownOnConsumerThread()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!IsShutdownOnMainThread());
+  MOZ_ASSERT(IsConsumerThread());
+  MOZ_ASSERT(!IsShutdownOnConsumerThread());
 
   mConsumer = nullptr;
 }
 
 bool
 BluetoothSocket::BluetoothSocketIO::IsShutdownOnIOThread() const
 {
   return mShuttingDownOnIOThread;
 }
 
 void
 BluetoothSocket::BluetoothSocketIO::ShutdownOnIOThread()
 {
-  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(!IsConsumerThread());
   MOZ_ASSERT(!mShuttingDownOnIOThread);
 
   Close(); // will also remove fd from I/O loop
   mShuttingDownOnIOThread = true;
 }
 
 
 //
@@ -497,17 +505,17 @@ class BluetoothSocket::ListenTask final
 {
 public:
   ListenTask(BluetoothSocketIO* aIO)
     : SocketIOTask<BluetoothSocketIO>(aIO)
   { }
 
   void Run() override
   {
-    MOZ_ASSERT(!NS_IsMainThread());
+    MOZ_ASSERT(!GetIO()->IsConsumerThread());
 
     if (!IsCanceled()) {
       GetIO()->Listen();
     }
   }
 };
 
 class BluetoothSocket::ConnectTask final
@@ -515,46 +523,46 @@ class BluetoothSocket::ConnectTask final
 {
 public:
   ConnectTask(BluetoothSocketIO* aIO)
     : SocketIOTask<BluetoothSocketIO>(aIO)
   { }
 
   void Run() override
   {
-    MOZ_ASSERT(!NS_IsMainThread());
+    MOZ_ASSERT(!GetIO()->IsConsumerThread());
     MOZ_ASSERT(!IsCanceled());
 
     GetIO()->Connect();
   }
 };
 
 class BluetoothSocket::DelayedConnectTask final
   : public SocketIOTask<BluetoothSocketIO>
 {
 public:
   DelayedConnectTask(BluetoothSocketIO* aIO)
     : SocketIOTask<BluetoothSocketIO>(aIO)
   { }
 
   void Run() override
   {
-    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(GetIO()->IsConsumerThread());
 
     if (IsCanceled()) {
       return;
     }
 
     BluetoothSocketIO* io = GetIO();
-    if (io->IsShutdownOnMainThread()) {
+    if (io->IsShutdownOnConsumerThread()) {
       return;
     }
 
     io->ClearDelayedConnectTask();
-    XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new ConnectTask(io));
+    io->GetIOLoop()->PostTask(FROM_HERE, new ConnectTask(io));
   }
 };
 
 //
 // BluetoothSocket
 //
 
 BluetoothSocket::BluetoothSocket(BluetoothSocketObserver* aObserver)
@@ -571,17 +579,16 @@ BluetoothSocket::~BluetoothSocket()
 
 nsresult
 BluetoothSocket::Connect(const nsAString& aDeviceAddress,
                          const BluetoothUuid& aServiceUuid,
                          BluetoothSocketType aType,
                          int aChannel,
                          bool aAuth, bool aEncrypt)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!aDeviceAddress.IsEmpty());
 
   nsAutoPtr<BluetoothUnixSocketConnector> connector(
     new BluetoothUnixSocketConnector(NS_ConvertUTF16toUTF8(aDeviceAddress),
                                      aType, aChannel, aAuth, aEncrypt));
 
   nsresult rv = Connect(connector);
   if (NS_FAILED(rv)) {
@@ -598,18 +605,16 @@ BluetoothSocket::Connect(const nsAString
 
 nsresult
 BluetoothSocket::Listen(const nsAString& aServiceName,
                         const BluetoothUuid& aServiceUuid,
                         BluetoothSocketType aType,
                         int aChannel,
                         bool aAuth, bool aEncrypt)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   nsAutoPtr<BluetoothUnixSocketConnector> connector(
     new BluetoothUnixSocketConnector(NS_LITERAL_CSTRING(BLUETOOTH_ADDRESS_NONE),
                                      aType, aChannel, aAuth, aEncrypt));
 
   nsresult rv = Listen(connector);
   if (NS_FAILED(rv)) {
     nsAutoString addr;
     GetAddress(addr);
@@ -620,17 +625,16 @@ BluetoothSocket::Listen(const nsAString&
   connector.forget();
 
   return NS_OK;
 }
 
 void
 BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mObserver);
 
   mObserver->ReceiveSocketData(this, aBuffer);
 }
 
 bool
 BluetoothSocket::SendSocketData(const nsACString& aStr)
 {
@@ -640,49 +644,78 @@ BluetoothSocket::SendSocketData(const ns
 
   SendSocketData(new UnixSocketRawData(aStr.BeginReading(), aStr.Length()));
 
   return true;
 }
 
 nsresult
 BluetoothSocket::Connect(BluetoothUnixSocketConnector* aConnector,
-                         int aDelayMs)
+                         int aDelayMs,
+                         nsIThread* aConsumerThread, MessageLoop* aIOLoop)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aConnector);
+  MOZ_ASSERT(aConsumerThread);
+  MOZ_ASSERT(aIOLoop);
   MOZ_ASSERT(!mIO);
 
-  MessageLoop* ioLoop = XRE_GetIOMessageLoop();
-  mIO = new BluetoothSocketIO(ioLoop, this, aConnector);
+  mIO = new BluetoothSocketIO(aConsumerThread, aIOLoop, this, aConnector);
   SetConnectionStatus(SOCKET_CONNECTING);
+
   if (aDelayMs > 0) {
     DelayedConnectTask* connectTask = new DelayedConnectTask(mIO);
     mIO->SetDelayedConnectTask(connectTask);
     MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs);
   } else {
-    ioLoop->PostTask(FROM_HERE, new ConnectTask(mIO));
+    aIOLoop->PostTask(FROM_HERE, new ConnectTask(mIO));
+  }
+
+  return NS_OK;
+}
+
+nsresult
+BluetoothSocket::Connect(BluetoothUnixSocketConnector* aConnector,
+                         int aDelayMs)
+{
+  nsIThread* consumerThread = nullptr;
+  nsresult rv = NS_GetCurrentThread(&consumerThread);
+  if (NS_FAILED(rv)) {
+    return rv;
   }
+
+  return Connect(aConnector, aDelayMs, consumerThread, XRE_GetIOMessageLoop());
+}
+
+nsresult
+BluetoothSocket::Listen(BluetoothUnixSocketConnector* aConnector,
+                        nsIThread* aConsumerThread, MessageLoop* aIOLoop)
+{
+  MOZ_ASSERT(aConnector);
+  MOZ_ASSERT(aConsumerThread);
+  MOZ_ASSERT(aIOLoop);
+  MOZ_ASSERT(!mIO);
+
+  mIO = new BluetoothSocketIO(aConsumerThread, aIOLoop, this, aConnector);
+  SetConnectionStatus(SOCKET_LISTENING);
+
+  aIOLoop->PostTask(FROM_HERE, new ListenTask(mIO));
+
   return NS_OK;
 }
 
 nsresult
 BluetoothSocket::Listen(BluetoothUnixSocketConnector* aConnector)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aConnector);
-  MOZ_ASSERT(!mIO);
-
-  MessageLoop* ioLoop = XRE_GetIOMessageLoop();
+  nsIThread* consumerThread = nullptr;
+  nsresult rv = NS_GetCurrentThread(&consumerThread);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
 
-  mIO = new BluetoothSocketIO(ioLoop, this, aConnector);
-  SetConnectionStatus(SOCKET_LISTENING);
-  ioLoop->PostTask(FROM_HERE, new ListenTask(mIO));
-
-  return NS_OK;
+  return Listen(aConnector, consumerThread, XRE_GetIOMessageLoop());
 }
 
 void
 BluetoothSocket::GetAddress(nsAString& aAddrStr)
 {
   aAddrStr.Truncate();
   if (!mIO || GetConnectionStatus() != SOCKET_CONNECTED) {
     NS_WARNING("No socket currently open!");
@@ -691,66 +724,62 @@ BluetoothSocket::GetAddress(nsAString& a
   mIO->GetSocketAddr(aAddrStr);
 }
 
 // |DataSocket|
 
 void
 BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mIO);
-  MOZ_ASSERT(!mIO->IsShutdownOnMainThread());
+  MOZ_ASSERT(mIO->IsConsumerThread());
+  MOZ_ASSERT(!mIO->IsShutdownOnConsumerThread());
 
-  XRE_GetIOMessageLoop()->PostTask(
+  mIO->GetIOLoop()->PostTask(
     FROM_HERE,
     new SocketIOSendTask<BluetoothSocketIO, UnixSocketIOBuffer>(mIO, aBuffer));
 }
 
 // |SocketBase|
 
 void
 BluetoothSocket::Close()
 {
-  MOZ_ASSERT(NS_IsMainThread());
   if (!mIO) {
     return;
   }
 
+  MOZ_ASSERT(mIO->IsConsumerThread());
+
   mIO->CancelDelayedConnectTask();
 
   // From this point on, we consider mIO as being deleted.
   // We sever the relationship here so any future calls to listen or connect
   // will create a new implementation.
-  mIO->ShutdownOnMainThread();
-
-  XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
-
+  mIO->ShutdownOnConsumerThread();
+  mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
   mIO = nullptr;
 
   NotifyDisconnect();
 }
 
 void
 BluetoothSocket::OnConnectSuccess()
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mObserver);
   mObserver->OnSocketConnectSuccess(this);
 }
 
 void
 BluetoothSocket::OnConnectError()
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mObserver);
   mObserver->OnSocketConnectError(this);
 }
 
 void
 BluetoothSocket::OnDisconnect()
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mObserver);
   mObserver->OnSocketDisconnect(this);
 }
 
 END_BLUETOOTH_NAMESPACE
--- a/dom/bluetooth/bluez/BluetoothSocket.h
+++ b/dom/bluetooth/bluez/BluetoothSocket.h
@@ -11,16 +11,18 @@
 #include <stdlib.h>
 #include "mozilla/ipc/DataSocket.h"
 #include "mozilla/ipc/UnixSocketWatcher.h"
 #include "mozilla/RefPtr.h"
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 
+class MessageLoop;
+
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothSocketObserver;
 class BluetoothUnixSocketConnector;
 
 class BluetoothSocket final : public mozilla::ipc::DataSocket
 {
 public:
@@ -36,17 +38,17 @@ public:
   nsresult Listen(const nsAString& aServiceName,
                   const BluetoothUuid& aServiceUuid,
                   BluetoothSocketType aType,
                   int aChannel,
                   bool aAuth, bool aEncrypt);
 
   /**
    * Method to be called whenever data is received. This is only called on the
-   * main thread.
+   * consumer thread.
    *
    * @param aBuffer Data received from the socket.
    */
   void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketBuffer>& aBuffer);
 
   /**
    * Convenience function for sending strings to the socket (common in bluetooth
    * profile usage). Converts to a UnixSocketRawData struct. Can only be called
@@ -59,26 +61,51 @@ public:
   bool SendSocketData(const nsACString& aMessage);
 
   /**
    * Starts a task on the socket that will try to connect to a socket in a
    * non-blocking manner.
    *
    * @param aConnector Connector object for socket type specific functions
    * @param aDelayMs Time delay in milli-seconds.
+   * @param aConsumerThread The socket's consumer thread.
+   * @param aIOLoop The socket's I/O thread.
+   * @return NS_OK on success, or an XPCOM error code otherwise.
+   */
+  nsresult Connect(BluetoothUnixSocketConnector* aConnector, int aDelayMs,
+                   nsIThread* aConsumerThread, MessageLoop* aIOLoop);
+
+  /**
+   * Starts a task on the socket that will try to connect to a socket in a
+   * non-blocking manner.
+   *
+   * @param aConnector Connector object for socket type specific functions
+   * @param aDelayMs Time delay in milli-seconds.
    * @return NS_OK on success, or an XPCOM error code otherwise.
    */
   nsresult Connect(BluetoothUnixSocketConnector* aConnector,
                    int aDelayMs = 0);
 
   /**
    * Starts a task on the socket that will try to accept a new connection in a
    * non-blocking manner.
    *
    * @param aConnector Connector object for socket type specific functions
+   * @param aConsumerThread The socket's consumer thread.
+   * @param aIOLoop The socket's I/O thread.
+   * @return NS_OK on success, or an XPCOM error code otherwise.
+   */
+  nsresult Listen(BluetoothUnixSocketConnector* aConnector,
+                  nsIThread* aConsumerThread, MessageLoop* aIOLoop);
+
+  /**
+   * Starts a task on the socket that will try to accept a new connection in a
+   * non-blocking manner.
+   *
+   * @param aConnector Connector object for socket type specific functions
    * @return NS_OK on success, or an XPCOM error code otherwise.
    */
   nsresult Listen(BluetoothUnixSocketConnector* aConnector);
 
   /**
    * Get the current socket address.
    *
    * @param[out] aDeviceAddress Returns the address string.
--- a/ipc/bluetooth/BluetoothDaemonConnection.cpp
+++ b/ipc/bluetooth/BluetoothDaemonConnection.cpp
@@ -201,18 +201,19 @@ BluetoothDaemonPDUConsumer::~BluetoothDa
 // BluetoothDaemonConnectionIO
 //
 
 class BluetoothDaemonConnectionIO final
   : public UnixSocketWatcher
   , public ConnectionOrientedSocketIO
 {
 public:
-  BluetoothDaemonConnectionIO(MessageLoop* aIOLoop, int aFd,
-                              ConnectionStatus aConnectionStatus,
+  BluetoothDaemonConnectionIO(nsIThread* aConsumerThread,
+                              MessageLoop* aIOLoop,
+                              int aFd, ConnectionStatus aConnectionStatus,
                               BluetoothDaemonConnection* aConnection,
                               BluetoothDaemonPDUConsumer* aConsumer);
 
   // Task callback methods
   //
 
   void Send(UnixSocketIOBuffer* aBuffer);
 
@@ -236,38 +237,41 @@ public:
   void ConsumeBuffer() override;
   void DiscardBuffer() override;
 
   // Methods for |SocketIOBase|
   //
 
   SocketBase* GetSocketBase() override;
 
-  bool IsShutdownOnMainThread() const override;
+  bool IsShutdownOnConsumerThread() const override;
   bool IsShutdownOnIOThread() const override;
 
-  void ShutdownOnMainThread() override;
+  void ShutdownOnConsumerThread() override;
   void ShutdownOnIOThread() override;
 
 private:
   BluetoothDaemonConnection* mConnection;
   BluetoothDaemonPDUConsumer* mConsumer;
   nsAutoPtr<BluetoothDaemonPDU> mPDU;
   bool mShuttingDownOnIOThread;
 };
 
 BluetoothDaemonConnectionIO::BluetoothDaemonConnectionIO(
-  MessageLoop* aIOLoop, int aFd,
+  nsIThread* aConsumerThread,
+  MessageLoop* aIOLoop,
+  int aFd,
   ConnectionStatus aConnectionStatus,
   BluetoothDaemonConnection* aConnection,
   BluetoothDaemonPDUConsumer* aConsumer)
-: UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
-, mConnection(aConnection)
-, mConsumer(aConsumer)
-, mShuttingDownOnIOThread(false)
+  : UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
+  , ConnectionOrientedSocketIO(aConsumerThread)
+  , mConnection(aConnection)
+  , mConsumer(aConsumer)
+  , mShuttingDownOnIOThread(false)
 {
   MOZ_ASSERT(mConnection);
   MOZ_ASSERT(mConsumer);
 }
 
 void
 BluetoothDaemonConnectionIO::Send(UnixSocketIOBuffer* aBuffer)
 {
@@ -303,18 +307,19 @@ BluetoothDaemonConnectionIO::OnSocketCan
 }
 
 void
 BluetoothDaemonConnectionIO::OnConnected()
 {
   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
   MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
 
-  NS_DispatchToMainThread(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
+  GetConsumerThread()->Dispatch(
+    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
+    NS_DISPATCH_NORMAL);
 
   AddWatchers(READ_WATCHER, true);
   if (HasPendingData()) {
     AddWatchers(WRITE_WATCHER, false);
   }
 }
 
 void
@@ -322,19 +327,20 @@ BluetoothDaemonConnectionIO::OnError(con
 {
   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
 
   UnixFdWatcher::OnError(aFunction, aErrno);
 
   // Clean up watchers, status, fd
   Close();
 
-  // Tell the main thread we've errored
-  NS_DispatchToMainThread(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR));
+  // Tell the consumer thread we've errored
+  GetConsumerThread()->Dispatch(
+    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
+    NS_DISPATCH_NORMAL);
 }
 
 // |ConnectionOrientedSocketIO|
 
 nsresult
 BluetoothDaemonConnectionIO::Accept(int aFd,
                                     const struct sockaddr* aAddress,
                                     socklen_t aAddressLength)
@@ -392,142 +398,137 @@ BluetoothDaemonConnectionIO::DiscardBuff
 
 SocketBase*
 BluetoothDaemonConnectionIO::GetSocketBase()
 {
   return mConnection;
 }
 
 bool
-BluetoothDaemonConnectionIO::IsShutdownOnMainThread() const
+BluetoothDaemonConnectionIO::IsShutdownOnConsumerThread() const
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsConsumerThread());
 
   return mConnection == nullptr;
 }
 
 bool
 BluetoothDaemonConnectionIO::IsShutdownOnIOThread() const
 {
   return mShuttingDownOnIOThread;
 }
 
 void
-BluetoothDaemonConnectionIO::ShutdownOnMainThread()
+BluetoothDaemonConnectionIO::ShutdownOnConsumerThread()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!IsShutdownOnMainThread());
+  MOZ_ASSERT(IsConsumerThread());
+  MOZ_ASSERT(!IsShutdownOnConsumerThread());
 
   mConnection = nullptr;
 }
 
 void
 BluetoothDaemonConnectionIO::ShutdownOnIOThread()
 {
-  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(!IsConsumerThread());
   MOZ_ASSERT(!mShuttingDownOnIOThread);
 
   Close(); // will also remove fd from I/O loop
   mShuttingDownOnIOThread = true;
 }
 
 //
 // BluetoothDaemonConnection
 //
 
 BluetoothDaemonConnection::BluetoothDaemonConnection(
   BluetoothDaemonPDUConsumer* aPDUConsumer,
   BluetoothDaemonConnectionConsumer* aConsumer,
   int aIndex)
-  : mPDUConsumer(aPDUConsumer)
+  : mIO(nullptr)
+  , mPDUConsumer(aPDUConsumer)
   , mConsumer(aConsumer)
   , mIndex(aIndex)
-  , mIO(nullptr)
 {
   MOZ_ASSERT(mConsumer);
 }
 
 BluetoothDaemonConnection::~BluetoothDaemonConnection()
 { }
 
 // |ConnectionOrientedSocket|
 
 nsresult
 BluetoothDaemonConnection::PrepareAccept(UnixSocketConnector* aConnector,
+                                         nsIThread* aConsumerThread,
+                                         MessageLoop* aIOLoop,
                                          ConnectionOrientedSocketIO*& aIO)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mIO);
 
   // |BluetoothDaemonConnection| now owns the connector, but doesn't
   // actually use it. So the connector is stored in an auto pointer
   // to be deleted at the end of the method.
   nsAutoPtr<UnixSocketConnector> connector(aConnector);
 
   SetConnectionStatus(SOCKET_CONNECTING);
 
   mIO = new BluetoothDaemonConnectionIO(
-    XRE_GetIOMessageLoop(), -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
+    aConsumerThread, aIOLoop, -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
     this, mPDUConsumer);
   aIO = mIO;
 
   return NS_OK;
 }
 
 // |DataSocket|
 
 void
 BluetoothDaemonConnection::SendSocketData(UnixSocketIOBuffer* aBuffer)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mIO);
+  MOZ_ASSERT(mIO->IsConsumerThread());
 
-  XRE_GetIOMessageLoop()->PostTask(
+  mIO->GetIOLoop()->PostTask(
     FROM_HERE,
     new SocketIOSendTask<BluetoothDaemonConnectionIO,
                          UnixSocketIOBuffer>(mIO, aBuffer));
 }
 
 // |SocketBase|
 
 void
 BluetoothDaemonConnection::Close()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   if (!mIO) {
     CHROMIUM_LOG("Bluetooth daemon already disconnected!");
     return;
   }
 
-  XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
+  MOZ_ASSERT(mIO->IsConsumerThread());
 
+  mIO->ShutdownOnConsumerThread();
+  mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
   mIO = nullptr;
 
   NotifyDisconnect();
 }
 
 void
 BluetoothDaemonConnection::OnConnectSuccess()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConsumer->OnConnectSuccess(mIndex);
 }
 
 void
 BluetoothDaemonConnection::OnConnectError()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConsumer->OnConnectError(mIndex);
 }
 
 void
 BluetoothDaemonConnection::OnDisconnect()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConsumer->OnDisconnect(mIndex);
 }
 
 }
 }
--- a/ipc/bluetooth/BluetoothDaemonConnection.h
+++ b/ipc/bluetooth/BluetoothDaemonConnection.h
@@ -7,16 +7,18 @@
 #ifndef mozilla_ipc_bluetooth_BluetoothDaemonConnection_h
 #define mozilla_ipc_bluetooth_BluetoothDaemonConnection_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/ipc/ConnectionOrientedSocket.h"
 #include "nsAutoPtr.h"
 
+class MessageLoop;
+
 namespace mozilla {
 namespace ipc {
 
 class BluetoothDaemonConnectionConsumer;
 class BluetoothDaemonConnectionIO;
 class BluetoothDaemonPDUConsumer;
 
 /*
@@ -87,17 +89,17 @@ private:
   BluetoothDaemonPDUConsumer* mConsumer;
   void* mUserData;
   ScopedClose mReceivedFd;
 };
 
 /*
  * |BluetoothDaemonPDUConsumer| processes incoming PDUs from the Bluetooth
  * daemon. Please note that its method |Handle| runs on a different than the
- * main thread.
+ * consumer thread.
  */
 class BluetoothDaemonPDUConsumer
 {
 public:
   virtual ~BluetoothDaemonPDUConsumer();
 
   virtual void Handle(BluetoothDaemonPDU& aPDU) = 0;
   virtual void StoreUserData(const BluetoothDaemonPDU& aPDU) = 0;
@@ -118,34 +120,36 @@ public:
                             BluetoothDaemonConnectionConsumer* aConsumer,
                             int aIndex);
   virtual ~BluetoothDaemonConnection();
 
   // Methods for |ConnectionOrientedSocket|
   //
 
   nsresult PrepareAccept(UnixSocketConnector* aConnector,
+                         nsIThread* aConsumerThread,
+                         MessageLoop* aIOLoop,
                          ConnectionOrientedSocketIO*& aIO) override;
 
   // Methods for |DataSocket|
   //
 
   void SendSocketData(UnixSocketIOBuffer* aBuffer) override;
 
   // Methods for |SocketBase|
   //
 
   void Close() override;
   void OnConnectSuccess() override;
   void OnConnectError() override;
   void OnDisconnect() override;
 
 private:
+  BluetoothDaemonConnectionIO* mIO;
   BluetoothDaemonPDUConsumer* mPDUConsumer;
   BluetoothDaemonConnectionConsumer* mConsumer;
   int mIndex;
-  BluetoothDaemonConnectionIO* mIO;
 };
 
 }
 }
 
 #endif
--- a/ipc/bluetooth/BluetoothDaemonConnectionConsumer.h
+++ b/ipc/bluetooth/BluetoothDaemonConnectionConsumer.h
@@ -17,31 +17,31 @@ namespace ipc {
 
 /*
  * |BluetoothDaemonConnectionConsumer| handles socket events.
  */
 class BluetoothDaemonConnectionConsumer
 {
 public:
   /**
-   * Callback for socket success. Main-thread only.
+   * Callback for socket success. Consumer-thread only.
    *
    * @param aIndex The index that has been given to the stream socket.
    */
   virtual void OnConnectSuccess(int aIndex) = 0;
 
   /**
-   * Callback for socket errors. Main-thread only.
+   * Callback for socket errors. Consumer-thread only.
    *
    * @param aIndex The index that has been given to the stream socket.
    */
   virtual void OnConnectError(int aIndex) = 0;
 
   /**
-   * Callback for socket disconnect. Main-thread only.
+   * Callback for socket disconnect. Consumer-thread only.
    *
    * @param aIndex The index that has been given to the stream socket.
    */
   virtual void OnDisconnect(int aIndex) = 0;
 
 protected:
   BluetoothDaemonConnectionConsumer();
   virtual ~BluetoothDaemonConnectionConsumer();
--- a/ipc/unixsocket/ConnectionOrientedSocket.cpp
+++ b/ipc/unixsocket/ConnectionOrientedSocket.cpp
@@ -4,16 +4,29 @@
  * 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 "ConnectionOrientedSocket.h"
 
 namespace mozilla {
 namespace ipc {
 
+//
+// ConnectionOrientedSocketIO
+//
+
+ConnectionOrientedSocketIO::ConnectionOrientedSocketIO(
+  nsIThread* aConsumerThread)
+  : DataSocketIO(aConsumerThread)
+{ }
+
 ConnectionOrientedSocketIO::~ConnectionOrientedSocketIO()
 { }
 
+//
+// ConnectionOrientedSocket
+//
+
 ConnectionOrientedSocket::~ConnectionOrientedSocket()
 { }
 
 }
 }
--- a/ipc/unixsocket/ConnectionOrientedSocket.h
+++ b/ipc/unixsocket/ConnectionOrientedSocket.h
@@ -5,50 +5,57 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ipc_connectionorientedsocket_h
 #define mozilla_ipc_connectionorientedsocket_h
 
 #include <sys/socket.h>
 #include "DataSocket.h"
 
+class MessageLoop;
+
 namespace mozilla {
 namespace ipc {
 
 class UnixSocketConnector;
 
 /*
  * |ConnectionOrientedSocketIO| and |ConnectionOrientedSocket| define
- * interfaces for implementing stream sockets on I/O and main thread.
+ * interfaces for implementing stream sockets on I/O and consumer thread.
  * |ListenSocket| uses these classes to handle accepted sockets.
  */
 
 class ConnectionOrientedSocketIO : public DataSocketIO
 {
 public:
+  ConnectionOrientedSocketIO(nsIThread* aConsumerThread);
   virtual ~ConnectionOrientedSocketIO();
 
   virtual nsresult Accept(int aFd,
                           const struct sockaddr* aAddress,
                           socklen_t aAddressLength) = 0;
 };
 
 class ConnectionOrientedSocket : public DataSocket
 {
 public:
   /**
    * Prepares an instance of |ConnectionOrientedSocket| in DISCONNECTED
-   * state for accepting a connection. Main-thread only.
+   * state for accepting a connection. Consumer-thread only.
    *
    * @param aConnector The new connector object, owned by the
    *                   connection-oriented socket.
+   * @param aConsumerThread The socket's consumer thread.
+   * @param aIOLoop The socket's I/O thread.
    * @param[out] aIO, Returns an instance of |ConnectionOrientedSocketIO|.
    * @return NS_OK on success, or an XPCOM error code otherwise.
    */
   virtual nsresult PrepareAccept(UnixSocketConnector* aConnector,
+                                 nsIThread* aConsumerThread,
+                                 MessageLoop* aIOLoop,
                                  ConnectionOrientedSocketIO*& aIO) = 0;
 
 protected:
   virtual ~ConnectionOrientedSocket();
 };
 
 }
 }
--- a/ipc/unixsocket/DataSocket.cpp
+++ b/ipc/unixsocket/DataSocket.cpp
@@ -45,30 +45,33 @@ ssize_t
 DataSocketIO::ReceiveData(int aFd)
 {
   MOZ_ASSERT(aFd >= 0);
 
   UnixSocketIOBuffer* incoming;
   nsresult rv = QueryReceiveBuffer(&incoming);
   if (NS_FAILED(rv)) {
     /* an error occured */
-    NS_DispatchToMainThread(new SocketIORequestClosingRunnable(this));
+    GetConsumerThread()->Dispatch(new SocketIORequestClosingRunnable(this),
+                                  NS_DISPATCH_NORMAL);
     return -1;
   }
 
   ssize_t res = incoming->Receive(aFd);
   if (res < 0) {
     /* an I/O error occured */
     DiscardBuffer();
-    NS_DispatchToMainThread(new SocketIORequestClosingRunnable(this));
+    GetConsumerThread()->Dispatch(new SocketIORequestClosingRunnable(this),
+                                  NS_DISPATCH_NORMAL);
     return -1;
   } else if (!res) {
     /* EOF or peer shut down sending */
     DiscardBuffer();
-    NS_DispatchToMainThread(new SocketIORequestClosingRunnable(this));
+    GetConsumerThread()->Dispatch(new SocketIORequestClosingRunnable(this),
+                                  NS_DISPATCH_NORMAL);
     return 0;
   }
 
 #ifdef MOZ_TASK_TRACER
   /* Make unix socket creation events to be the source events of TaskTracer,
    * and originate the rest correlation tasks from here.
    */
   AutoSourceEvent taskTracerEvent(SourceEventType::Unixsocket);
@@ -85,32 +88,34 @@ DataSocketIO::SendPendingData(int aFd)
   MOZ_ASSERT(aFd >= 0);
 
   while (HasPendingData()) {
     UnixSocketIOBuffer* outgoing = mOutgoingQ.ElementAt(0);
 
     ssize_t res = outgoing->Send(aFd);
     if (res < 0) {
       /* an I/O error occured */
-      NS_DispatchToMainThread(new SocketIORequestClosingRunnable(this));
+      GetConsumerThread()->Dispatch(new SocketIORequestClosingRunnable(this),
+                                    NS_DISPATCH_NORMAL);
       return NS_ERROR_FAILURE;
     } else if (!res && outgoing->GetSize()) {
       /* I/O is currently blocked; try again later */
       return NS_OK;
     }
     if (!outgoing->GetSize()) {
       mOutgoingQ.RemoveElementAt(0);
       delete outgoing;
     }
   }
 
   return NS_OK;
 }
 
-DataSocketIO::DataSocketIO()
+DataSocketIO::DataSocketIO(nsIThread* aConsumerThread)
+  : SocketIOBase(aConsumerThread)
 { }
 
 //
 // DataSocket
 //
 
 DataSocket::~DataSocket()
 { }
--- a/ipc/unixsocket/DataSocket.h
+++ b/ipc/unixsocket/DataSocket.h
@@ -85,17 +85,17 @@ public:
   void EnqueueData(UnixSocketIOBuffer* aBuffer);
   bool HasPendingData() const;
 
   ssize_t ReceiveData(int aFd);
 
   nsresult SendPendingData(int aFd);
 
 protected:
-  DataSocketIO();
+  DataSocketIO(nsIThread* aConsumerThread);
 
 private:
   /**
    * Raw data queue. Must be pushed/popped from I/O thread only.
    */
   nsTArray<UnixSocketIOBuffer*> mOutgoingQ;
 };
 
@@ -115,20 +115,20 @@ public:
   : SocketIOTask<Tio>(aIO)
   , mData(aData)
   {
     MOZ_ASSERT(aData);
   }
 
   void Run() override
   {
-    MOZ_ASSERT(!NS_IsMainThread());
     MOZ_ASSERT(!SocketIOTask<Tio>::IsCanceled());
 
     Tio* io = SocketIOTask<Tio>::GetIO();
+    MOZ_ASSERT(!io->IsConsumerThread());
     MOZ_ASSERT(!io->IsShutdownOnIOThread());
 
     io->Send(mData);
   }
 
 private:
   Tdata* mData;
 };
--- a/ipc/unixsocket/ListenSocket.cpp
+++ b/ipc/unixsocket/ListenSocket.cpp
@@ -22,17 +22,18 @@ namespace ipc {
 
 class ListenSocketIO final
   : public UnixSocketWatcher
   , public SocketIOBase
 {
 public:
   class ListenTask;
 
-  ListenSocketIO(MessageLoop* mIOLoop,
+  ListenSocketIO(nsIThread* aConsumerThread,
+                 MessageLoop* aIOLoop,
                  ListenSocket* aListenSocket,
                  UnixSocketConnector* aConnector);
   ~ListenSocketIO();
 
   UnixSocketConnector* GetConnector() const;
 
   // Task callback methods
   //
@@ -50,29 +51,29 @@ public:
   void OnListening() override;
   void OnSocketCanAcceptWithoutBlocking() override;
 
   // Methods for |SocketIOBase|
   //
 
   SocketBase* GetSocketBase() override;
 
-  bool IsShutdownOnMainThread() const override;
+  bool IsShutdownOnConsumerThread() const override;
   bool IsShutdownOnIOThread() const override;
 
-  void ShutdownOnMainThread() override;
+  void ShutdownOnConsumerThread() override;
   void ShutdownOnIOThread() override;
 
 private:
   void FireSocketError();
 
   /**
    * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
-   * directly from main thread. All non-main-thread accesses should happen with
-   * mIO as container.
+   * directly from consumer thread. All non-consumer-thread accesses should
+   * happen with mIO as container.
    */
   RefPtr<ListenSocket> mListenSocket;
 
   /**
    * Connector object used to create the connection we are currently using.
    */
   nsAutoPtr<UnixSocketConnector> mConnector;
 
@@ -89,35 +90,36 @@ private:
   /**
    * Address structure of the socket currently in use
    */
   struct sockaddr_storage mAddress;
 
   ConnectionOrientedSocketIO* mCOSocketIO;
 };
 
-ListenSocketIO::ListenSocketIO(MessageLoop* mIOLoop,
+ListenSocketIO::ListenSocketIO(nsIThread* aConsumerThread,
+                               MessageLoop* aIOLoop,
                                ListenSocket* aListenSocket,
                                UnixSocketConnector* aConnector)
-  : UnixSocketWatcher(mIOLoop)
-  , SocketIOBase()
+  : UnixSocketWatcher(aIOLoop)
+  , SocketIOBase(aConsumerThread)
   , mListenSocket(aListenSocket)
   , mConnector(aConnector)
   , mShuttingDownOnIOThread(false)
   , mAddressLength(0)
   , mCOSocketIO(nullptr)
 {
   MOZ_ASSERT(mListenSocket);
   MOZ_ASSERT(mConnector);
 }
 
 ListenSocketIO::~ListenSocketIO()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(IsShutdownOnMainThread());
+  MOZ_ASSERT(IsConsumerThread());
+  MOZ_ASSERT(IsShutdownOnConsumerThread());
 }
 
 UnixSocketConnector*
 ListenSocketIO::GetConnector() const
 {
   return mConnector;
 }
 
@@ -161,18 +163,19 @@ void
 ListenSocketIO::OnListening()
 {
   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
   MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_LISTENING);
 
   AddWatchers(READ_WATCHER, true);
 
   /* We signal a successful 'connection' to a local address for listening. */
-  NS_DispatchToMainThread(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
+  GetConsumerThread()->Dispatch(
+    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
+    NS_DISPATCH_NORMAL);
 }
 
 void
 ListenSocketIO::OnError(const char* aFunction, int aErrno)
 {
   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
 
   UnixFdWatcher::OnError(aFunction, aErrno);
@@ -182,19 +185,20 @@ ListenSocketIO::OnError(const char* aFun
 void
 ListenSocketIO::FireSocketError()
 {
   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
 
   // Clean up watchers, statuses, fds
   Close();
 
-  // Tell the main thread we've errored
-  NS_DispatchToMainThread(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR));
+  // Tell the consumer thread we've errored
+  GetConsumerThread()->Dispatch(
+    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
+    NS_DISPATCH_NORMAL);
 }
 
 void
 ListenSocketIO::OnSocketCanAcceptWithoutBlocking()
 {
   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
   MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_LISTENING);
   MOZ_ASSERT(mCOSocketIO);
@@ -223,42 +227,42 @@ ListenSocketIO::OnSocketCanAcceptWithout
 
 SocketBase*
 ListenSocketIO::GetSocketBase()
 {
   return mListenSocket.get();
 }
 
 bool
-ListenSocketIO::IsShutdownOnMainThread() const
+ListenSocketIO::IsShutdownOnConsumerThread() const
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsConsumerThread());
 
   return mListenSocket == nullptr;
 }
 
 bool
 ListenSocketIO::IsShutdownOnIOThread() const
 {
   return mShuttingDownOnIOThread;
 }
 
 void
-ListenSocketIO::ShutdownOnMainThread()
+ListenSocketIO::ShutdownOnConsumerThread()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!IsShutdownOnMainThread());
+  MOZ_ASSERT(IsConsumerThread());
+  MOZ_ASSERT(!IsShutdownOnConsumerThread());
 
   mListenSocket = nullptr;
 }
 
 void
 ListenSocketIO::ShutdownOnIOThread()
 {
-  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(!IsConsumerThread());
   MOZ_ASSERT(!mShuttingDownOnIOThread);
 
   Close(); // will also remove fd from I/O loop
   mShuttingDownOnIOThread = true;
 }
 
 //
 // Socket tasks
@@ -272,138 +276,145 @@ public:
   : SocketIOTask<ListenSocketIO>(aIO)
   , mCOSocketIO(aCOSocketIO)
   {
     MOZ_ASSERT(mCOSocketIO);
   }
 
   void Run() override
   {
-    MOZ_ASSERT(!NS_IsMainThread());
+    MOZ_ASSERT(!GetIO()->IsConsumerThread());
 
     if (!IsCanceled()) {
       GetIO()->Listen(mCOSocketIO);
     }
   }
 
 private:
   ConnectionOrientedSocketIO* mCOSocketIO;
 };
 
 //
 // UnixSocketConsumer
 //
 
 ListenSocket::ListenSocket(ListenSocketConsumer* aConsumer, int aIndex)
-  : mConsumer(aConsumer)
+  : mIO(nullptr)
+  , mConsumer(aConsumer)
   , mIndex(aIndex)
-  , mIO(nullptr)
 {
   MOZ_ASSERT(mConsumer);
 }
 
 ListenSocket::~ListenSocket()
 {
   MOZ_ASSERT(!mIO);
 }
 
 nsresult
 ListenSocket::Listen(UnixSocketConnector* aConnector,
+                     nsIThread* aConsumerThread,
+                     MessageLoop* aIOLoop,
                      ConnectionOrientedSocket* aCOSocket)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mIO);
 
-  mIO = new ListenSocketIO(XRE_GetIOMessageLoop(), this, aConnector);
+  mIO = new ListenSocketIO(aConsumerThread, aIOLoop, this, aConnector);
 
   // Prepared I/O object, now start listening.
   nsresult rv = Listen(aCOSocket);
   if (NS_FAILED(rv)) {
     delete mIO;
     mIO = nullptr;
     return rv;
   }
 
   return NS_OK;
 }
 
 nsresult
+ListenSocket::Listen(UnixSocketConnector* aConnector,
+                     ConnectionOrientedSocket* aCOSocket)
+{
+  nsIThread* consumerThread = nullptr;
+  nsresult rv = NS_GetCurrentThread(&consumerThread);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  return Listen(aConnector, consumerThread, XRE_GetIOMessageLoop(), aCOSocket);
+}
+
+nsresult
 ListenSocket::Listen(ConnectionOrientedSocket* aCOSocket)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aCOSocket);
   MOZ_ASSERT(mIO);
 
   // We first prepare the connection-oriented socket with a
   // socket connector and a socket I/O class.
 
   nsAutoPtr<UnixSocketConnector> connector;
   nsresult rv = mIO->GetConnector()->Duplicate(*connector.StartAssignment());
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   nsAutoPtr<ConnectionOrientedSocketIO> io;
-  rv = aCOSocket->PrepareAccept(connector, *io.StartAssignment());
+  rv = aCOSocket->PrepareAccept(connector,
+                                mIO->GetConsumerThread(), mIO->GetIOLoop(),
+                                *io.StartAssignment());
   if (NS_FAILED(rv)) {
     return rv;
   }
   connector.forget(); // now owned by |io|
 
   // Then we start listening for connection requests.
 
   SetConnectionStatus(SOCKET_LISTENING);
 
-  XRE_GetIOMessageLoop()->PostTask(
+  mIO->GetIOLoop()->PostTask(
     FROM_HERE, new ListenSocketIO::ListenTask(mIO, io.forget()));
 
   return NS_OK;
 }
 
 // |SocketBase|
 
 void
 ListenSocket::Close()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   if (!mIO) {
     return;
   }
 
+  MOZ_ASSERT(mIO->IsConsumerThread());
+
   // From this point on, we consider mIO as being deleted. We sever
   // the relationship here so any future calls to listen or connect
   // will create a new implementation.
-  mIO->ShutdownOnMainThread();
-
-  XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
-
+  mIO->ShutdownOnConsumerThread();
+  mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
   mIO = nullptr;
 
   NotifyDisconnect();
 }
 
 void
 ListenSocket::OnConnectSuccess()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConsumer->OnConnectSuccess(mIndex);
 }
 
 void
 ListenSocket::OnConnectError()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConsumer->OnConnectError(mIndex);
 }
 
 void
 ListenSocket::OnDisconnect()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConsumer->OnDisconnect(mIndex);
 }
 
 } // namespace ipc
 } // namespace mozilla
--- a/ipc/unixsocket/ListenSocket.h
+++ b/ipc/unixsocket/ListenSocket.h
@@ -5,31 +5,53 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ipc_listensocket_h
 #define mozilla_ipc_listensocket_h
 
 #include "nsString.h"
 #include "mozilla/ipc/SocketBase.h"
 
+class MessageLoop;
+class nsIThread;
+
 namespace mozilla {
 namespace ipc {
 
 class ConnectionOrientedSocket;
 class ListenSocketConsumer;
 class ListenSocketIO;
 class UnixSocketConnector;
 
 class ListenSocket final : public SocketBase
 {
-protected:
-  virtual ~ListenSocket();
+public:
+  /**
+   * Constructs an instance of |ListenSocket|.
+   *
+   * @param aConsumer The consumer for the socket.
+   * @param aIndex An arbitrary index.
+   */
+  ListenSocket(ListenSocketConsumer* aConsumer, int aIndex);
 
-public:
-  ListenSocket(ListenSocketConsumer* aConsumer, int aIndex);
+  /**
+   * Starts a task on the socket that will try to accept a new connection
+   * in a non-blocking manner.
+   *
+   * @param aConnector Connector object for socket-type-specific functions
+   * @param aConsumerThread The socket's consumer thread.
+   * @param aIOLoop The socket's I/O thread.
+   * @param aCOSocket The connection-oriented socket for handling the
+   *                  accepted connection.
+   * @return NS_OK on success, or an XPCOM error code otherwise.
+   */
+  nsresult Listen(UnixSocketConnector* aConnector,
+                  nsIThread* aConsumerThread,
+                  MessageLoop* aIOLoop,
+                  ConnectionOrientedSocket* aCOSocket);
 
   /**
    * Starts a task on the socket that will try to accept a new connection
    * in a non-blocking manner.
    *
    * @param aConnector Connector object for socket-type-specific functions
    * @param aCOSocket The connection-oriented socket for handling the
    *                  accepted connection.
@@ -52,18 +74,21 @@ public:
   // Methods for |SocketBase|
   //
 
   void Close() override;
   void OnConnectSuccess() override;
   void OnConnectError() override;
   void OnDisconnect() override;
 
+protected:
+  virtual ~ListenSocket();
+
 private:
+  ListenSocketIO* mIO;
   ListenSocketConsumer* mConsumer;
   int mIndex;
-  ListenSocketIO* mIO;
 };
 
 } // namespace ipc
 } // namepsace mozilla
 
 #endif // mozilla_ipc_listensocket_h
--- a/ipc/unixsocket/ListenSocketConsumer.h
+++ b/ipc/unixsocket/ListenSocketConsumer.h
@@ -14,31 +14,31 @@ namespace ipc {
  * |ListenSocketConsumer| handles socket events.
  */
 class ListenSocketConsumer
 {
 public:
   virtual ~ListenSocketConsumer();
 
   /**
-   * Callback for socket success. Main-thread only.
+   * Callback for socket success. Consumer-thread only.
    *
    * @param aIndex The index that has been given to the listening socket.
    */
   virtual void OnConnectSuccess(int aIndex) = 0;
 
   /**
-   * Callback for socket errors. Main-thread only.
+   * Callback for socket errors. Consumer-thread only.
    *
    * @param aIndex The index that has been given to the listening socket.
    */
   virtual void OnConnectError(int aIndex) = 0;
 
   /**
-   * Callback for socket disconnect. Main-thread only.
+   * Callback for socket disconnect. Consumer-thread only.
    *
    * @param aIndex The index that has been given to the listeing socket.
    */
   virtual void OnDisconnect(int aIndex) = 0;
 };
 
 }
 }
--- a/ipc/unixsocket/SocketBase.cpp
+++ b/ipc/unixsocket/SocketBase.cpp
@@ -181,66 +181,54 @@ UnixSocketRawData::Send(int aFd)
 
 //
 // SocketBase
 //
 
 SocketConnectionStatus
 SocketBase::GetConnectionStatus() const
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   return mConnectionStatus;
 }
 
 int
 SocketBase::GetSuggestedConnectDelayMs() const
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   return mConnectDelayMs;
 }
 
 void
 SocketBase::NotifySuccess()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConnectionStatus = SOCKET_CONNECTED;
   mConnectTimestamp = PR_IntervalNow();
   OnConnectSuccess();
 }
 
 void
 SocketBase::NotifyError()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConnectionStatus = SOCKET_DISCONNECTED;
   mConnectDelayMs = CalculateConnectDelayMs();
   mConnectTimestamp = 0;
   OnConnectError();
 }
 
 void
 SocketBase::NotifyDisconnect()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConnectionStatus = SOCKET_DISCONNECTED;
   mConnectDelayMs = CalculateConnectDelayMs();
   mConnectTimestamp = 0;
   OnDisconnect();
 }
 
 uint32_t
 SocketBase::CalculateConnectDelayMs() const
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   uint32_t connectDelayMs = mConnectDelayMs;
 
   if (mConnectTimestamp && (PR_IntervalNow()-mConnectTimestamp) > connectDelayMs) {
     // reset delay if connection has been opened for a while, or...
     connectDelayMs = 0;
   } else if (!connectDelayMs) {
     // ...start with a delay of ~1 sec, or...
     connectDelayMs = 1<<10;
@@ -267,40 +255,59 @@ SocketBase::SetConnectionStatus(SocketCo
 {
   mConnectionStatus = aConnectionStatus;
 }
 
 //
 // SocketIOBase
 //
 
-SocketIOBase::SocketIOBase()
-{ }
+SocketIOBase::SocketIOBase(nsIThread* aConsumerThread)
+  : mConsumerThread(aConsumerThread)
+{
+  MOZ_ASSERT(mConsumerThread);
+}
 
 SocketIOBase::~SocketIOBase()
 { }
 
+nsIThread*
+SocketIOBase::GetConsumerThread() const
+{
+  return mConsumerThread;
+}
+
+bool
+SocketIOBase::IsConsumerThread() const
+{
+  nsIThread* thread = nullptr;
+  if (NS_FAILED(NS_GetCurrentThread(&thread))) {
+    return false;
+  }
+  return thread == GetConsumerThread();
+}
+
 //
 // SocketIOEventRunnable
 //
 
 SocketIOEventRunnable::SocketIOEventRunnable(SocketIOBase* aIO,
                                              SocketEvent aEvent)
   : SocketIORunnable<SocketIOBase>(aIO)
   , mEvent(aEvent)
 { }
 
 NS_METHOD
 SocketIOEventRunnable::Run()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   SocketIOBase* io = SocketIORunnable<SocketIOBase>::GetIO();
 
-  if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
+  MOZ_ASSERT(io->IsConsumerThread());
+
+  if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
     // Since we've already explicitly closed and the close
     // happened before this, this isn't really an error.
     return NS_OK;
   }
 
   SocketBase* socketBase = io->GetSocketBase();
   MOZ_ASSERT(socketBase);
 
@@ -322,21 +329,21 @@ SocketIOEventRunnable::Run()
 SocketIORequestClosingRunnable::SocketIORequestClosingRunnable(
   SocketIOBase* aIO)
   : SocketIORunnable<SocketIOBase>(aIO)
 { }
 
 NS_METHOD
 SocketIORequestClosingRunnable::Run()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   SocketIOBase* io = SocketIORunnable<SocketIOBase>::GetIO();
 
-  if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
+  MOZ_ASSERT(io->IsConsumerThread());
+
+  if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
     // Since we've already explicitly closed and the close
     // happened before this, this isn't really an error.
     return NS_OK;
   }
 
   SocketBase* socketBase = io->GetSocketBase();
   MOZ_ASSERT(socketBase);
 
@@ -368,25 +375,25 @@ SocketIODeleteInstanceRunnable::Run()
 
 SocketIOShutdownTask::SocketIOShutdownTask(SocketIOBase* aIO)
   : SocketIOTask<SocketIOBase>(aIO)
 { }
 
 void
 SocketIOShutdownTask::Run()
 {
-  MOZ_ASSERT(!NS_IsMainThread());
+  SocketIOBase* io = SocketIOTask<SocketIOBase>::GetIO();
 
-  SocketIOBase* io = SocketIOTask<SocketIOBase>::GetIO();
+  MOZ_ASSERT(!io->IsConsumerThread());
+  MOZ_ASSERT(!io->IsShutdownOnIOThread());
 
   // At this point, there should be no new events on the I/O thread
   // after this one with the possible exception of an accept task,
   // which ShutdownOnIOThread will cancel for us. We are now fully
-  // shut down, so we can send a message to the main thread to delete
-  // |io| safely knowing that it's not reference any longer.
-  MOZ_ASSERT(!io->IsShutdownOnIOThread());
+  // shut down, so we can send a message to the consumer thread to
+  // delete |io| safely knowing that it's not reference any longer.
   io->ShutdownOnIOThread();
-
-  NS_DispatchToMainThread(new SocketIODeleteInstanceRunnable(io));
+  io->GetConsumerThread()->Dispatch(new SocketIODeleteInstanceRunnable(io),
+                                    NS_DISPATCH_NORMAL);
 }
 
 }
 }
--- a/ipc/unixsocket/SocketBase.h
+++ b/ipc/unixsocket/SocketBase.h
@@ -251,33 +251,33 @@ public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SocketBase)
 
   SocketConnectionStatus GetConnectionStatus() const;
 
   int GetSuggestedConnectDelayMs() const;
 
   /**
    * Queues the internal representation of socket for deletion. Can be called
-   * from main thread.
+   * from consumer thread.
    */
   virtual void Close() = 0;
 
   /**
    * Callback for socket connect/accept success. Called after connect/accept has
-   * finished. Will be run on main thread, before any reads take place.
+   * finished. Will be run on consumer thread before any reads take place.
    */
   virtual void OnConnectSuccess() = 0;
 
   /**
-   * Callback for socket connect/accept error. Will be run on main thread.
+   * Callback for socket connect/accept error. Will be run on consumer thread.
    */
   virtual void OnConnectError() = 0;
 
   /**
-   * Callback for socket disconnect. Will be run on main thread.
+   * Callback for socket disconnect. Will be run on consumer thread.
    */
   virtual void OnDisconnect() = 0;
 
   /**
    * Called by implementation to notify consumer of success.
    */
   void NotifySuccess();
 
@@ -335,39 +335,55 @@ public:
   virtual bool IsShutdownOnIOThread() const = 0;
 
   /**
    * Implemented by socket I/O classes to signal that socket class has
    * been shut down.
    *
    * @return True if the socket class has been shut down, false otherwise.
    */
-  virtual bool IsShutdownOnMainThread() const = 0;
+  virtual bool IsShutdownOnConsumerThread() const = 0;
 
   /**
    * Signals to the socket I/O classes that it has been shut down.
    */
   virtual void ShutdownOnIOThread() = 0;
 
   /**
    * Signals to the socket I/O classes that the socket class has been
    * shut down.
    */
-  virtual void ShutdownOnMainThread() = 0;
+  virtual void ShutdownOnConsumerThread() = 0;
+
+  /**
+   * Returns the consumer thread.
+   *
+   * @return A pointer to the consumer thread.
+   */
+  nsIThread* GetConsumerThread() const;
+
+  /**
+   * @return True if the current thread is thre consumer thread, or false
+   *         otherwise.
+   */
+  bool IsConsumerThread() const;
 
 protected:
-  SocketIOBase();
+  SocketIOBase(nsIThread* nsConsumerThread);
+
+private:
+  nsCOMPtr<nsIThread> mConsumerThread;
 };
 
 //
 // Socket I/O runnables
 //
 
 /* |SocketIORunnable| is a runnable for sending a message from
- * the I/O thread to the main thread.
+ * the I/O thread to the consumer thread.
  */
 template <typename T>
 class SocketIORunnable : public nsRunnable
 {
 public:
   virtual ~SocketIORunnable()
   { }
 
@@ -384,17 +400,17 @@ protected:
   }
 
 private:
   T* mIO;
 };
 
 /**
  * |SocketIOEventRunnable| reports the connection state on the
- * I/O thread back to the main thread.
+ * I/O thread back to the consumer thread.
  */
 class SocketIOEventRunnable final : public SocketIORunnable<SocketIOBase>
 {
 public:
   enum SocketEvent {
     CONNECT_SUCCESS,
     CONNECT_ERROR,
     DISCONNECT
@@ -405,29 +421,29 @@ public:
   NS_IMETHOD Run() override;
 
 private:
   SocketEvent mEvent;
 };
 
 /**
  * |SocketIORequestClosingRunnable| closes an instance of |SocketBase|
- * to the main thread.
+ * to the consumer thread.
  */
 class SocketIORequestClosingRunnable final
   : public SocketIORunnable<SocketIOBase>
 {
 public:
   SocketIORequestClosingRunnable(SocketIOBase* aIO);
 
   NS_IMETHOD Run() override;
 };
 
 /**
- * |SocketIODeleteInstanceRunnable| deletes an object on the main thread.
+ * |SocketIODeleteInstanceRunnable| deletes an object on the consumer thread.
  */
 class SocketIODeleteInstanceRunnable final : public nsRunnable
 {
 public:
   SocketIODeleteInstanceRunnable(SocketIOBase* aIO);
 
   NS_IMETHOD Run() override;
 
@@ -472,17 +488,17 @@ protected:
   }
 
 private:
   Tio* mIO;
 };
 
 /**
  * |SocketIOShutdownTask| signals shutdown to the socket I/O class on
- * the I/O thread and sends it to the main thread for destruction.
+ * the I/O thread and sends it to the consumer thread for destruction.
  */
 class SocketIOShutdownTask final : public SocketIOTask<SocketIOBase>
 {
 public:
   SocketIOShutdownTask(SocketIOBase* aIO);
 
   void Run() override;
 };
--- a/ipc/unixsocket/StreamSocket.cpp
+++ b/ipc/unixsocket/StreamSocket.cpp
@@ -24,20 +24,22 @@ class StreamSocketIO final
   : public UnixSocketWatcher
   , public ConnectionOrientedSocketIO
 {
 public:
   class ConnectTask;
   class DelayedConnectTask;
   class ReceiveRunnable;
 
-  StreamSocketIO(MessageLoop* mIOLoop,
+  StreamSocketIO(nsIThread* aConsumerThread,
+                 MessageLoop* mIOLoop,
                  StreamSocket* aStreamSocket,
                  UnixSocketConnector* aConnector);
-  StreamSocketIO(MessageLoop* mIOLoop, int aFd,
+  StreamSocketIO(nsIThread* aConsumerThread,
+                 MessageLoop* mIOLoop, int aFd,
                  ConnectionStatus aConnectionStatus,
                  StreamSocket* aStreamSocket,
                  UnixSocketConnector* aConnector);
   ~StreamSocketIO();
 
   StreamSocket* GetStreamSocket();
   DataSocket* GetDataSocket();
 
@@ -81,29 +83,29 @@ public:
   void ConsumeBuffer() override;
   void DiscardBuffer() override;
 
   // Methods for |SocketIOBase|
   //
 
   SocketBase* GetSocketBase() override;
 
-  bool IsShutdownOnMainThread() const override;
+  bool IsShutdownOnConsumerThread() const override;
   bool IsShutdownOnIOThread() const override;
 
-  void ShutdownOnMainThread() override;
+  void ShutdownOnConsumerThread() override;
   void ShutdownOnIOThread() override;
 
 private:
   void FireSocketError();
 
   /**
    * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
-   * directly from main thread. All non-main-thread accesses should happen with
-   * mIO as container.
+   * directly from consumer thread. All non-consumer-thread accesses should
+   * happen with mIO as container.
    */
   RefPtr<StreamSocket> mStreamSocket;
 
   /**
    * Connector object used to create the connection we are currently using.
    */
   nsAutoPtr<UnixSocketConnector> mConnector;
 
@@ -118,59 +120,64 @@ private:
   socklen_t mAddressLength;
 
   /**
    * Address structure of the socket currently in use
    */
   struct sockaddr_storage mAddress;
 
   /**
-   * Task member for delayed connect task. Should only be access on main thread.
+   * Task member for delayed connect task. Should only be access on consumer
+   * thread.
    */
   CancelableTask* mDelayedConnectTask;
 
   /**
    * I/O buffer for received data
    */
   nsAutoPtr<UnixSocketRawData> mBuffer;
 };
 
-StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop,
+StreamSocketIO::StreamSocketIO(nsIThread* aConsumerThread,
+                               MessageLoop* aIOLoop,
                                StreamSocket* aStreamSocket,
                                UnixSocketConnector* aConnector)
-  : UnixSocketWatcher(mIOLoop)
+  : UnixSocketWatcher(aIOLoop)
+  , ConnectionOrientedSocketIO(aConsumerThread)
   , mStreamSocket(aStreamSocket)
   , mConnector(aConnector)
   , mShuttingDownOnIOThread(false)
   , mAddressLength(0)
   , mDelayedConnectTask(nullptr)
 {
   MOZ_ASSERT(mStreamSocket);
   MOZ_ASSERT(mConnector);
 }
 
-StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop, int aFd,
-                               ConnectionStatus aConnectionStatus,
+StreamSocketIO::StreamSocketIO(nsIThread* aConsumerThread,
+                               MessageLoop* aIOLoop,
+                               int aFd, ConnectionStatus aConnectionStatus,
                                StreamSocket* aStreamSocket,
                                UnixSocketConnector* aConnector)
-  : UnixSocketWatcher(mIOLoop, aFd, aConnectionStatus)
+  : UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
+  , ConnectionOrientedSocketIO(aConsumerThread)
   , mStreamSocket(aStreamSocket)
   , mConnector(aConnector)
   , mShuttingDownOnIOThread(false)
   , mAddressLength(0)
   , mDelayedConnectTask(nullptr)
 {
   MOZ_ASSERT(mStreamSocket);
   MOZ_ASSERT(mConnector);
 }
 
 StreamSocketIO::~StreamSocketIO()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(IsShutdownOnMainThread());
+  MOZ_ASSERT(IsConsumerThread());
+  MOZ_ASSERT(IsShutdownOnConsumerThread());
 }
 
 StreamSocket*
 StreamSocketIO::GetStreamSocket()
 {
   return mStreamSocket.get();
 }
 
@@ -178,33 +185,33 @@ DataSocket*
 StreamSocketIO::GetDataSocket()
 {
   return mStreamSocket.get();
 }
 
 void
 StreamSocketIO::SetDelayedConnectTask(CancelableTask* aTask)
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsConsumerThread());
 
   mDelayedConnectTask = aTask;
 }
 
 void
 StreamSocketIO::ClearDelayedConnectTask()
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsConsumerThread());
 
   mDelayedConnectTask = nullptr;
 }
 
 void
 StreamSocketIO::CancelDelayedConnectTask()
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsConsumerThread());
 
   if (!mDelayedConnectTask) {
     return;
   }
 
   mDelayedConnectTask->Cancel();
   ClearDelayedConnectTask();
 }
@@ -241,18 +248,19 @@ StreamSocketIO::Send(UnixSocketIOBuffer*
 }
 
 void
 StreamSocketIO::OnConnected()
 {
   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
   MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
 
-  NS_DispatchToMainThread(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
+  GetConsumerThread()->Dispatch(
+    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
+    NS_DISPATCH_NORMAL);
 
   AddWatchers(READ_WATCHER, true);
   if (HasPendingData()) {
     AddWatchers(WRITE_WATCHER, false);
   }
 }
 
 void
@@ -307,19 +315,20 @@ StreamSocketIO::OnSocketCanSendWithoutBl
 void
 StreamSocketIO::FireSocketError()
 {
   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
 
   // Clean up watchers, statuses, fds
   Close();
 
-  // Tell the main thread we've errored
-  NS_DispatchToMainThread(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR));
+  // Tell the consumer thread we've errored
+  GetConsumerThread()->Dispatch(
+    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
+    NS_DISPATCH_NORMAL);
 }
 
 // |ConnectionOrientedSocketIO|
 
 nsresult
 StreamSocketIO::Accept(int aFd,
                        const struct sockaddr* aAddress,
                        socklen_t aAddressLength)
@@ -329,18 +338,19 @@ StreamSocketIO::Accept(int aFd,
 
   SetSocket(aFd, SOCKET_IS_CONNECTED);
 
   // Address setup
   mAddressLength = aAddressLength;
   memcpy(&mAddress, aAddress, mAddressLength);
 
   // Signal success
-  NS_DispatchToMainThread(
-    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
+  GetConsumerThread()->Dispatch(
+    new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
+    NS_DISPATCH_NORMAL);
 
   AddWatchers(READ_WATCHER, true);
   if (HasPendingData()) {
     AddWatchers(WRITE_WATCHER, false);
   }
 
   return NS_OK;
 }
@@ -357,34 +367,34 @@ StreamSocketIO::QueryReceiveBuffer(UnixS
   }
   *aBuffer = mBuffer.get();
 
   return NS_OK;
 }
 
 /**
  * |ReceiveRunnable| transfers data received on the I/O thread
- * to an instance of |StreamSocket| on the main thread.
+ * to an instance of |StreamSocket| on the consumer thread.
  */
 class StreamSocketIO::ReceiveRunnable final
   : public SocketIORunnable<StreamSocketIO>
 {
 public:
   ReceiveRunnable(StreamSocketIO* aIO, UnixSocketBuffer* aBuffer)
     : SocketIORunnable<StreamSocketIO>(aIO)
     , mBuffer(aBuffer)
   { }
 
   NS_IMETHOD Run() override
   {
-    MOZ_ASSERT(NS_IsMainThread());
-
     StreamSocketIO* io = SocketIORunnable<StreamSocketIO>::GetIO();
 
-    if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
+    MOZ_ASSERT(io->IsConsumerThread());
+
+    if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
       // Since we've already explicitly closed and the close
       // happened before this, this isn't really an error.
       return NS_OK;
     }
 
     StreamSocket* streamSocket = io->GetStreamSocket();
     MOZ_ASSERT(streamSocket);
 
@@ -395,17 +405,18 @@ public:
 
 private:
   nsAutoPtr<UnixSocketBuffer> mBuffer;
 };
 
 void
 StreamSocketIO::ConsumeBuffer()
 {
-  NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget()));
+  GetConsumerThread()->Dispatch(new ReceiveRunnable(this, mBuffer.forget()),
+                                NS_DISPATCH_NORMAL);
 }
 
 void
 StreamSocketIO::DiscardBuffer()
 {
   // Nothing to do.
 }
 
@@ -413,42 +424,42 @@ StreamSocketIO::DiscardBuffer()
 
 SocketBase*
 StreamSocketIO::GetSocketBase()
 {
   return GetDataSocket();
 }
 
 bool
-StreamSocketIO::IsShutdownOnMainThread() const
+StreamSocketIO::IsShutdownOnConsumerThread() const
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsConsumerThread());
 
   return mStreamSocket == nullptr;
 }
 
 bool
 StreamSocketIO::IsShutdownOnIOThread() const
 {
   return mShuttingDownOnIOThread;
 }
 
 void
-StreamSocketIO::ShutdownOnMainThread()
+StreamSocketIO::ShutdownOnConsumerThread()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!IsShutdownOnMainThread());
+  MOZ_ASSERT(IsConsumerThread());
+  MOZ_ASSERT(!IsShutdownOnConsumerThread());
 
   mStreamSocket = nullptr;
 }
 
 void
 StreamSocketIO::ShutdownOnIOThread()
 {
-  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(!IsConsumerThread());
   MOZ_ASSERT(!mShuttingDownOnIOThread);
 
   Close(); // will also remove fd from I/O loop
   mShuttingDownOnIOThread = true;
 }
 
 //
 // Socket tasks
@@ -459,170 +470,172 @@ class StreamSocketIO::ConnectTask final
 {
 public:
   ConnectTask(StreamSocketIO* aIO)
   : SocketIOTask<StreamSocketIO>(aIO)
   { }
 
   void Run() override
   {
-    MOZ_ASSERT(!NS_IsMainThread());
+    MOZ_ASSERT(!GetIO()->IsConsumerThread());
     MOZ_ASSERT(!IsCanceled());
 
     GetIO()->Connect();
   }
 };
 
 class StreamSocketIO::DelayedConnectTask final
   : public SocketIOTask<StreamSocketIO>
 {
 public:
   DelayedConnectTask(StreamSocketIO* aIO)
-  : SocketIOTask<StreamSocketIO>(aIO)
+    : SocketIOTask<StreamSocketIO>(aIO)
   { }
 
   void Run() override
   {
-    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(GetIO()->IsConsumerThread());
 
     if (IsCanceled()) {
       return;
     }
 
     StreamSocketIO* io = GetIO();
-    if (io->IsShutdownOnMainThread()) {
+    if (io->IsShutdownOnConsumerThread()) {
       return;
     }
 
     io->ClearDelayedConnectTask();
-    XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new ConnectTask(io));
+    io->GetIOLoop()->PostTask(FROM_HERE, new ConnectTask(io));
   }
 };
 
 //
 // StreamSocket
 //
 
 StreamSocket::StreamSocket(StreamSocketConsumer* aConsumer, int aIndex)
-  : mConsumer(aConsumer)
+  : mIO(nullptr)
+  , mConsumer(aConsumer)
   , mIndex(aIndex)
-  , mIO(nullptr)
 {
   MOZ_ASSERT(mConsumer);
 }
 
 StreamSocket::~StreamSocket()
 {
   MOZ_ASSERT(!mIO);
 }
 
 void
 StreamSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConsumer->ReceiveSocketData(mIndex, aBuffer);
 }
 
 nsresult
-StreamSocket::Connect(UnixSocketConnector* aConnector,
-                      int aDelayMs)
+StreamSocket::Connect(UnixSocketConnector* aConnector, int aDelayMs,
+                      nsIThread* aConsumerThread, MessageLoop* aIOLoop)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mIO);
 
-  MessageLoop* ioLoop = XRE_GetIOMessageLoop();
-  mIO = new StreamSocketIO(ioLoop, this, aConnector);
+  mIO = new StreamSocketIO(aConsumerThread, aIOLoop, this, aConnector);
   SetConnectionStatus(SOCKET_CONNECTING);
 
   if (aDelayMs > 0) {
     StreamSocketIO::DelayedConnectTask* connectTask =
       new StreamSocketIO::DelayedConnectTask(mIO);
     mIO->SetDelayedConnectTask(connectTask);
     MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs);
   } else {
-    ioLoop->PostTask(FROM_HERE, new StreamSocketIO::ConnectTask(mIO));
+    aIOLoop->PostTask(FROM_HERE, new StreamSocketIO::ConnectTask(mIO));
   }
+
   return NS_OK;
 }
 
+nsresult
+StreamSocket::Connect(UnixSocketConnector* aConnector, int aDelayMs)
+{
+  nsIThread* consumerThread = nullptr;
+  nsresult rv = NS_GetCurrentThread(&consumerThread);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  return Connect(aConnector, aDelayMs, consumerThread, XRE_GetIOMessageLoop());
+}
+
 // |ConnectionOrientedSocket|
 
 nsresult
 StreamSocket::PrepareAccept(UnixSocketConnector* aConnector,
+                            nsIThread* aConsumerThread,
+                            MessageLoop* aIOLoop,
                             ConnectionOrientedSocketIO*& aIO)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mIO);
   MOZ_ASSERT(aConnector);
 
   SetConnectionStatus(SOCKET_CONNECTING);
 
-  mIO = new StreamSocketIO(XRE_GetIOMessageLoop(),
+  mIO = new StreamSocketIO(aConsumerThread, aIOLoop,
                            -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
                            this, aConnector);
   aIO = mIO;
 
   return NS_OK;
 }
 
 // |DataSocket|
 
 void
 StreamSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mIO);
+  MOZ_ASSERT(mIO->IsConsumerThread());
+  MOZ_ASSERT(!mIO->IsShutdownOnConsumerThread());
 
-  MOZ_ASSERT(!mIO->IsShutdownOnMainThread());
-  XRE_GetIOMessageLoop()->PostTask(
+  mIO->GetIOLoop()->PostTask(
     FROM_HERE,
     new SocketIOSendTask<StreamSocketIO, UnixSocketIOBuffer>(mIO, aBuffer));
 }
 
 // |SocketBase|
 
 void
 StreamSocket::Close()
 {
-  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mIO);
+  MOZ_ASSERT(mIO->IsConsumerThread());
 
   mIO->CancelDelayedConnectTask();
 
   // From this point on, we consider |mIO| as being deleted. We sever
   // the relationship here so any future calls to |Connect| will create
   // a new I/O object.
-  mIO->ShutdownOnMainThread();
-
-  XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
-
+  mIO->ShutdownOnConsumerThread();
+  mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
   mIO = nullptr;
 
   NotifyDisconnect();
 }
 
 void
 StreamSocket::OnConnectSuccess()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConsumer->OnConnectSuccess(mIndex);
 }
 
 void
 StreamSocket::OnConnectError()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConsumer->OnConnectError(mIndex);
 }
 
 void
 StreamSocket::OnDisconnect()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   mConsumer->OnDisconnect(mIndex);
 }
 
 } // namespace ipc
 } // namespace mozilla
--- a/ipc/unixsocket/StreamSocket.h
+++ b/ipc/unixsocket/StreamSocket.h
@@ -4,49 +4,72 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ipc_streamsocket_h
 #define mozilla_ipc_streamsocket_h
 
 #include "ConnectionOrientedSocket.h"
 
+class MessageLoop;
+
 namespace mozilla {
 namespace ipc {
 
 class StreamSocketConsumer;
 class StreamSocketIO;
 class UnixSocketConnector;
 
 class StreamSocket final : public ConnectionOrientedSocket
 {
 public:
+  /**
+   * Constructs an instance of |StreamSocket|.
+   *
+   * @param aConsumer The consumer for the socket.
+   * @param aIndex An arbitrary index.
+   */
   StreamSocket(StreamSocketConsumer* aConsumer, int aIndex);
 
   /**
-   * Method to be called whenever data is received. Main-thread only.
+   * Method to be called whenever data is received. Consumer-thread only.
    *
    * @param aBuffer Data received from the socket.
    */
   void ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer);
 
   /**
    * Starts a task on the socket that will try to connect to a socket in a
    * non-blocking manner.
    *
    * @param aConnector Connector object for socket type specific functions
    * @param aDelayMs Time delay in milliseconds.
+   * @param aConsumerThread The socket's consumer thread.
+   * @param aIOLoop The socket's I/O thread.
+   * @return NS_OK on success, or an XPCOM error code otherwise.
+   */
+  nsresult Connect(UnixSocketConnector* aConnector, int aDelayMs,
+                   nsIThread* aConsumerThread, MessageLoop* aIOLoop);
+
+  /**
+   * Starts a task on the socket that will try to connect to a socket in a
+   * non-blocking manner.
+   *
+   * @param aConnector Connector object for socket type specific functions
+   * @param aDelayMs Time delay in milliseconds.
    * @return NS_OK on success, or an XPCOM error code otherwise.
    */
   nsresult Connect(UnixSocketConnector* aConnector, int aDelayMs = 0);
 
   // Methods for |ConnectionOrientedSocket|
   //
 
   nsresult PrepareAccept(UnixSocketConnector* aConnector,
+                         nsIThread* aConsumerThread,
+                         MessageLoop* aIOLoop,
                          ConnectionOrientedSocketIO*& aIO) override;
 
   // Methods for |DataSocket|
   //
 
   void SendSocketData(UnixSocketIOBuffer* aBuffer) override;
 
   // Methods for |SocketBase|
@@ -56,17 +79,17 @@ public:
   void OnConnectSuccess() override;
   void OnConnectError() override;
   void OnDisconnect() override;
 
 protected:
   virtual ~StreamSocket();
 
 private:
+  StreamSocketIO* mIO;
   StreamSocketConsumer* mConsumer;
   int mIndex;
-  StreamSocketIO* mIO;
 };
 
 } // namespace ipc
 } // namepsace mozilla
 
 #endif // mozilla_ipc_streamsocket_h
--- a/ipc/unixsocket/StreamSocketConsumer.h
+++ b/ipc/unixsocket/StreamSocketConsumer.h
@@ -16,40 +16,40 @@ class UnixSocketBuffer;
 
 /**
  * |StreamSocketConsumer| handles socket events and received data.
  */
 class StreamSocketConsumer
 {
 public:
   /**
-   * Method to be called whenever data is received. Main-thread only.
+   * Method to be called whenever data is received. Consumer-thread only.
    *
    * @param aIndex The index that has been given to the stream socket.
    * @param aBuffer Data received from the socket.
    */
   virtual void ReceiveSocketData(int aIndex,
                                  nsAutoPtr<UnixSocketBuffer>& aBuffer) = 0;
 
   /**
-   * Callback for socket success. Main-thread only.
+   * Callback for socket success. Consumer-thread only.
    *
    * @param aIndex The index that has been given to the stream socket.
    */
   virtual void OnConnectSuccess(int aIndex) = 0;
 
   /**
-   * Callback for socket errors. Main-thread only.
+   * Callback for socket errors. Consumer-thread only.
    *
    * @param aIndex The index that has been given to the stream socket.
    */
   virtual void OnConnectError(int aIndex) = 0;
 
   /**
-   * Callback for socket disconnect. Main-thread only.
+   * Callback for socket disconnect. Consumer-thread only.
    *
    * @param aIndex The index that has been given to the stream socket.
    */
   virtual void OnDisconnect(int aIndex) = 0;
 
 protected:
   virtual ~StreamSocketConsumer();
 };