Merge m-c to fx-team a=merge
authorWes Kocher <wkocher@mozilla.com>
Fri, 27 Jun 2014 17:54:18 -0700
changeset 191280 2f5df65e366299b8a51dd7e5565a06cbd285a2f3
parent 191279 1d77b632bcd23002a7c2b51badc943ef69a9ac80 (current diff)
parent 191271 286b6cb59c3e62aafc0f2e38384e230db4764eb8 (diff)
child 191281 9035e11b95476a33a80369c8a1a7d90692cfec33
child 191417 dcec428a089e82c5c5cca064c67da79f8b629fee
push id27038
push userttaubert@mozilla.com
push dateSat, 28 Jun 2014 06:24:40 +0000
treeherdermozilla-central@2f5df65e3662 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone33.0a1
first release with
nightly linux32
2f5df65e3662 / 33.0a1 / 20140628030201 / files
nightly linux64
2f5df65e3662 / 33.0a1 / 20140628030201 / files
nightly mac
2f5df65e3662 / 33.0a1 / 20140628030201 / files
nightly win32
2f5df65e3662 / 33.0a1 / 20140628030201 / files
nightly win64
2f5df65e3662 / 33.0a1 / 20140628030201 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fx-team a=merge
js/jsd/README
js/jsd/idl/jsdIDebuggerService.idl
js/jsd/idl/moz.build
js/jsd/jsd.h
js/jsd/jsd1640.def
js/jsd/jsd1640.rc
js/jsd/jsd3240.rc
js/jsd/jsd_atom.cpp
js/jsd/jsd_high.cpp
js/jsd/jsd_hook.cpp
js/jsd/jsd_lock.cpp
js/jsd/jsd_lock.h
js/jsd/jsd_obj.cpp
js/jsd/jsd_scpt.cpp
js/jsd/jsd_stak.cpp
js/jsd/jsd_step.cpp
js/jsd/jsd_text.cpp
js/jsd/jsd_val.cpp
js/jsd/jsd_xpc.cpp
js/jsd/jsd_xpc.h
js/jsd/jsdebug.cpp
js/jsd/jsdebug.h
js/jsd/jsdstubs.cpp
js/jsd/jshash.cpp
js/jsd/jshash.h
js/jsd/mkshell.bat
js/jsd/moz.build
js/jsd/resource.h
js/jsd/test/bug507448.js
js/jsd/test/jsd-test.js
js/jsd/test/mochitest.ini
js/jsd/test/moz.build
js/jsd/test/test-bug617870-callhooks.js
js/jsd/test/test-bug638178-execlines.js
js/jsd/test/test_bug507448.html
js/jsd/test/test_bug617870-callhooks.html
js/jsd/test/test_bug638178-execlines.html
js/jsd/test/test_evalCached.js
js/jsd/test/test_jsval_retval.js
js/jsd/test/xpcshell.ini
xpcom/analysis/MDC-attach.py
xpcom/analysis/MDC-upload.py
xpcom/analysis/Makefile.in
xpcom/analysis/deki.py
xpcom/analysis/fix-srcrefs.py
xpcom/analysis/flow.js
xpcom/analysis/mayreturn.js
xpcom/analysis/moz.build
xpcom/analysis/must-override.js
xpcom/analysis/outparams.js
xpcom/analysis/stack.js
xpcom/analysis/static-init.js
xpcom/analysis/type-printer.cpp
xpcom/analysis/type-printer.js
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,11 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Clobber to make sure any residual damage from bug 975011 is gone.
+Bug 800200: Removing the old JavaScript debugging API, js/jsd. I'm advised
+that our build system doesn't cope well with deletions, and that a spoonful
+of clobber helps the medicine go down (in a most delightful way).
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="b8f36518696f3191a56e4f33447ee9d6ec820da1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b3324d031fe91b864090461ffcacc6ca605a2903"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="3326b51017252e09ccdd715dec6c5e12a7d1ecfe"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="cc67f31dc638c0b7edba3cf7e3d87cadf0ed52bf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="b8f36518696f3191a56e4f33447ee9d6ec820da1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b3324d031fe91b864090461ffcacc6ca605a2903"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="b8f36518696f3191a56e4f33447ee9d6ec820da1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b3324d031fe91b864090461ffcacc6ca605a2903"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="b8f36518696f3191a56e4f33447ee9d6ec820da1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b3324d031fe91b864090461ffcacc6ca605a2903"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="3326b51017252e09ccdd715dec6c5e12a7d1ecfe"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="cc67f31dc638c0b7edba3cf7e3d87cadf0ed52bf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="b8f36518696f3191a56e4f33447ee9d6ec820da1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b3324d031fe91b864090461ffcacc6ca605a2903"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "921a8c7dd926cccc2c17f4c4bc16f2ed92684daa", 
+    "revision": "e3956f470dd934c6a749913e5cb45337c4503003", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="b8f36518696f3191a56e4f33447ee9d6ec820da1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b3324d031fe91b864090461ffcacc6ca605a2903"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="b8f36518696f3191a56e4f33447ee9d6ec820da1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b3324d031fe91b864090461ffcacc6ca605a2903"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="cc67f31dc638c0b7edba3cf7e3d87cadf0ed52bf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="b8f36518696f3191a56e4f33447ee9d6ec820da1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b3324d031fe91b864090461ffcacc6ca605a2903"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="b8f36518696f3191a56e4f33447ee9d6ec820da1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b3324d031fe91b864090461ffcacc6ca605a2903"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/components/loop/content/shared/js/models.js
+++ b/browser/components/loop/content/shared/js/models.js
@@ -134,45 +134,53 @@ loop.shared.models = (function() {
     /**
      * Starts a SDK session and subscribe to call events.
      */
     startSession: function() {
       if (!this.isSessionReady()) {
         throw new Error("Can't start session as it's not ready");
       }
       this.session = this.sdk.initSession(this.get("sessionId"));
-      this.listenTo(this.session, "sessionConnected", this._sessionConnected);
       this.listenTo(this.session, "streamCreated", this._streamCreated);
       this.listenTo(this.session, "connectionDestroyed",
                                   this._connectionDestroyed);
       this.listenTo(this.session, "sessionDisconnected",
                                   this._sessionDisconnected);
       this.listenTo(this.session, "networkDisconnected",
                                   this._networkDisconnected);
-      this.session.connect(this.get("apiKey"), this.get("sessionToken"));
+      this.session.connect(this.get("apiKey"), this.get("sessionToken"),
+                           this._onConnectCompletion.bind(this));
     },
 
     /**
      * Ends current session.
      */
     endSession: function() {
       this.session.disconnect();
       this.once("session:ended", this.stopListening, this);
       this.set("ongoing", false);
     },
 
     /**
-     * Session is created.
+     * Manages connection status
+     * triggers apropriate event for connection error/success
+     * http://tokbox.com/opentok/tutorials/connect-session/js/
+     * http://tokbox.com/opentok/tutorials/hello-world/js/
      * http://tokbox.com/opentok/libraries/client/js/reference/SessionConnectEvent.html
      *
-     * @param  {SessionConnectEvent} event
+     * @param {error|null} error
      */
-    _sessionConnected: function(event) {
-      this.trigger("session:connected", event);
-      this.set("ongoing", true);
+    _onConnectCompletion: function(error) {
+      if (error) {
+        this.trigger("session:connection-error", error);
+        this.endSession();
+      } else {
+        this.trigger("session:connected");
+        this.set("ongoing", true);
+      }
     },
 
     /**
      * New created streams are available.
      * http://tokbox.com/opentok/libraries/client/js/reference/StreamEvent.html
      *
      * @param  {StreamEvent} event
      */
--- a/browser/components/loop/content/shared/js/router.js
+++ b/browser/components/loop/content/shared/js/router.js
@@ -98,21 +98,33 @@ loop.shared.router = (function(l10n) {
       this._conversation = options.conversation;
 
       this.listenTo(this._conversation, "session:ready", this._onSessionReady);
       this.listenTo(this._conversation, "session:ended", this._onSessionEnded);
       this.listenTo(this._conversation, "session:peer-hungup",
                                         this._onPeerHungup);
       this.listenTo(this._conversation, "session:network-disconnected",
                                         this._onNetworkDisconnected);
+      this.listenTo(this._conversation, "session:connection-error",
+                    this._notifyError);
 
       BaseRouter.apply(this, arguments);
     },
 
     /**
+     * Notify the user that the connection was not possible
+     * @param {{code: number, message: string}} error
+     */
+    _notifyError: function(error) {
+      console.log(error);
+      this._notifier.errorL10n("connection_error_see_console_notification");
+      this.endCall();
+    },
+
+    /**
      * Starts the call. This method should be overriden.
      */
     startCall: function() {},
 
     /**
      * Ends the call. This method should be overriden.
      */
     endCall: function() {},
--- a/browser/components/loop/standalone/content/l10n/data.ini
+++ b/browser/components/loop/standalone/content/l10n/data.ini
@@ -8,16 +8,17 @@ stop=Stop
 start_call=Start the call
 welcome=Welcome to the Loop web client.
 incompatible_browser=Incompatible Browser
 powered_by_webrtc=The audio and video components of Loop are powered by WebRTC.
 use_latest_firefox.innerHTML=To use Loop, please use the latest version of <a href="{{ff_url}}">Firefox</a>.
 incompatible_device=Incompatible device
 sorry_device_unsupported=Sorry, Loop does not currently support your device.
 use_firefox_windows_mac_linux=Please open this page using the latest Firefox on Windows, Android, Mac or Linux.
+connection_error_see_console_notification=Call failed; see console for details.
 
 [fr]
 call_has_ended=L'appel est terminé.
 missing_conversation_info=Informations de communication manquantes.
 network_disconnected=La connexion réseau semble avoir été interrompue.
 peer_ended_conversation=Votre correspondant a mis fin à la communication.
 unable_retrieve_call_info=Impossible de récupérer les informations liées à cet appel.
 stop=Arrêter
--- a/browser/components/loop/test/shared/models_test.js
+++ b/browser/components/loop/test/shared/models_test.js
@@ -21,17 +21,19 @@ describe("loop.shared.models", function(
       requests.push(xhr);
     };
     fakeSessionData = {
       sessionId:    "sessionId",
       sessionToken: "sessionToken",
       apiKey:       "apiKey"
     };
     fakeSession = _.extend({
-      connect: sandbox.spy(),
+      connect: function () {},
+      endSession: sandbox.stub(),
+      set: sandbox.stub(),
       disconnect: sandbox.spy(),
       unpublish: sandbox.spy()
     }, Backbone.Events);
     fakeSDK = {
       initPublisher: sandbox.spy(),
       initSession: sandbox.stub().returns(fakeSession)
     };
   });
@@ -158,22 +160,82 @@ describe("loop.shared.models", function(
           });
           model.startSession();
         });
 
         it("should start a session", function() {
           sinon.assert.calledOnce(fakeSDK.initSession);
         });
 
+        it("should call connect", function() {
+          fakeSession.connect = sandbox.stub();
+
+          model.startSession();
+
+          sinon.assert.calledOnce(fakeSession.connect);
+          sinon.assert.calledWithExactly(fakeSession.connect,
+                        sinon.match.string, sinon.match.string,
+                        sinon.match.func);
+        });
+
+        it("should set ongoing to true when no error is called back",
+            function() {
+              fakeSession.connect = function(key, token, cb) {
+                cb(null);
+              };
+              sinon.stub(model, "set");
+
+              model.startSession();
+
+              sinon.assert.calledWith(model.set, "ongoing", true);
+            });
+
+        it("should trigger session:connected when no error is called back",
+            function() {
+              fakeSession.connect = function(key, token, cb) {
+                cb(null);
+              };
+              sandbox.stub(model, "trigger");
+
+              model.startSession();
+
+              sinon.assert.calledWithExactly(model.trigger, "session:connected");
+            });
+
         describe("Session events", function() {
-          it("should trigger a session:connected event on sessionConnected",
-            function(done) {
-              model.once("session:connected", function(){ done(); });
+
+          it("should trigger a fail event when an error is called back",
+            function() {
+              fakeSession.connect = function(key, token, cb) {
+                cb({
+                  error: true
+                });
+              };
+              sinon.stub(model, "endSession");
+
+              model.startSession();
 
-              fakeSession.trigger("sessionConnected");
+              sinon.assert.calledOnce(model.endSession);
+              sinon.assert.calledWithExactly(model.endSession);
+            });
+
+          it("should trigger session:connection-error event when an error is" +
+            " called back", function() {
+              fakeSession.connect = function(key, token, cb) {
+                cb({
+                  error: true
+                });
+              };
+              sandbox.stub(model, "trigger");
+
+              model.startSession();
+
+              sinon.assert.calledOnce(model.trigger);
+              sinon.assert.calledWithExactly(model.trigger,
+                          "session:connection-error", sinon.match.object);
             });
 
           it("should trigger a session:ended event on sessionDisconnected",
             function(done) {
               model.once("session:ended", function(){ done(); });
 
               fakeSession.trigger("sessionDisconnected", {reason: "ko"});
             });
--- a/browser/components/loop/test/shared/router_test.js
+++ b/browser/components/loop/test/shared/router_test.js
@@ -120,16 +120,34 @@ describe("loop.shared.router", function(
           apiKey:       "apiKey"
         };
         router = new TestRouter({
           conversation: conversation,
           notifier: notifier
         });
       });
 
+      describe("session:connection-error", function() {
+
+        it("should warn the user when .connect() call fails", function() {
+          conversation.trigger("session:connection-error");
+
+          sinon.assert.calledOnce(notifier.errorL10n);
+          sinon.assert.calledWithExactly(notifier.errorL10n, sinon.match.string);
+        });
+
+        it("should invoke endCall()", function() {
+          conversation.trigger("session:connection-error");
+
+          sinon.assert.calledOnce(router.endCall);
+          sinon.assert.calledWithExactly(router.endCall);
+        });
+
+      });
+
       it("should call startCall() once the call session is ready", function() {
         conversation.trigger("session:ready");
 
         sinon.assert.calledOnce(router.startCall);
       });
 
       it("should call endCall() when conversation ended", function() {
         conversation.trigger("session:ended");
--- a/browser/config/mozconfigs/whitelist
+++ b/browser/config/mozconfigs/whitelist
@@ -6,17 +6,17 @@ whitelist = {
     }
 
 all_platforms = ['win64', 'win32', 'linux32', 'linux64', 'macosx-universal']
 
 for platform in all_platforms:
     whitelist['nightly'][platform] = [
         'ac_add_options --enable-update-channel=nightly',
         'ac_add_options --enable-profiling',
-        'mk_add_options CLIENT_PY_ARGS="--hg-options=\'--verbose --time\' --hgtool=../tools/buildfarm/utils/hgtool.py --skip-chatzilla --skip-comm --skip-inspector --skip-venkman --tinderbox-print"'
+        'mk_add_options CLIENT_PY_ARGS="--hg-options=\'--verbose --time\' --hgtool=../tools/buildfarm/utils/hgtool.py --skip-chatzilla --skip-comm --skip-inspector --tinderbox-print"'
     ]
 
 for platform in ['linux32', 'linux64', 'macosx-universal']:
     whitelist['nightly'][platform] += [
         'mk_add_options MOZ_MAKE_FLAGS="-j4"',
     ]
 
 for platform in ['linux32', 'linux64', 'macosx-universal', 'win32', 'win64']:
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -79,20 +79,16 @@ ifdef MOZ_NO_DEBUG_RTL
 DEFINES += -DMOZ_MSVC_REDIST=$(_MSC_VER)
 endif
 endif
 
 ifneq (,$(filter WINNT Darwin Android,$(OS_TARGET)))
 DEFINES += -DMOZ_SHARED_MOZGLUE=1
 endif
 
-ifdef MOZ_JSDEBUGGER
-DEFINES += -DMOZ_JSDEBUGGER
-endif
-
 ifdef NECKO_WIFI
 DEFINES += -DNECKO_WIFI
 endif
 
 ifdef GKMEDIAS_SHARED_LIBRARY
 DEFINES += -DGKMEDIAS_SHARED_LIBRARY
 endif
 
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -242,19 +242,16 @@
 @BINPATH@/components/html5.xpt
 @BINPATH@/components/htmlparser.xpt
 @BINPATH@/components/identity.xpt
 @BINPATH@/components/imglib2.xpt
 @BINPATH@/components/imgicon.xpt
 @BINPATH@/components/inspector.xpt
 @BINPATH@/components/intl.xpt
 @BINPATH@/components/jar.xpt
-#ifdef MOZ_JSDEBUGGER
-@BINPATH@/components/jsdservice.xpt
-#endif
 @BINPATH@/components/jsdebugger.xpt
 @BINPATH@/components/jsdownloads.xpt
 @BINPATH@/components/jsinspector.xpt
 @BINPATH@/components/layout_base.xpt
 #ifdef NS_PRINTING
 @BINPATH@/components/layout_printing.xpt
 #endif
 @BINPATH@/components/layout_xul_tree.xpt
--- a/browser/locales/en-US/chrome/browser/loop/loop.properties
+++ b/browser/locales/en-US/chrome/browser/loop/loop.properties
@@ -23,8 +23,10 @@ decline_button=Decline
 stop=Stop
 
 peer_ended_conversation=Your peer ended the conversation.
 call_has_ended=Your call has ended.
 close_window=Close this window
 
 cannot_start_call_session_not_ready=Can't start call, session is not ready.
 network_disconnected=The network connection terminated abruptly.
+
+connection_error_see_console_notification=Call failed; see console for details.
--- a/build/sanitizers/lsan_suppressions.txt
+++ b/build/sanitizers/lsan_suppressions.txt
@@ -26,21 +26,16 @@ leak:libfontconfig.so
 leak:GI___strdup
 # The symbol is really __GI___strdup, but if you have the leading _, it doesn't suppress it.
 
 
 ###
 ### Many leaks only affect some test suites.  The suite annotations are not checked.
 ###
 
-# Bug 800200 - JSD1 is leaking, but it is about to be removed, so ignore it. m4
-leak:jsd_CreateLock
-leak:jsdScript::GetExecutableLines
-leak:jsdService::ActivateDebugger
-
 # Bug 979928 - WebRTC is leaky. m2, m3
 leak:/media/mtransport/
 leak:/media/webrtc/signaling/
 
 # Bug 981195 - Small leak in the parser. m4
 leak:TypeCompartment::fixObjectType
 
 # Bug 982111 - WebM is leaking. m1
--- a/configure.in
+++ b/configure.in
@@ -3844,17 +3844,16 @@ dnl ====================================
 MOZ_ARG_HEADER(Application)
 
 ENABLE_TESTS=1
 ENABLE_SYSTEM_EXTENSION_DIRS=1
 MOZ_BRANDING_DIRECTORY=
 MOZ_OFFICIAL_BRANDING=
 MOZ_FEEDS=1
 MOZ_WEBAPP_RUNTIME=
-MOZ_JSDEBUGGER=1
 MOZ_AUTH_EXTENSION=1
 MOZ_RAW=
 MOZ_VORBIS=
 MOZ_TREMOR=
 MOZ_WAVE=1
 MOZ_SAMPLE_TYPE_FLOAT32=
 MOZ_SAMPLE_TYPE_S16=
 MOZ_OPUS=1
@@ -4940,25 +4939,16 @@ fi
 dnl ========================================================
 dnl = Enable NFC permission on Android
 dnl ========================================================
 if test -n "$MOZ_ANDROID_BEAM"; then
     AC_DEFINE(MOZ_ANDROID_BEAM)
 fi
 
 dnl ========================================================
-dnl = JS Debugger XPCOM component (js/jsd)
-dnl ========================================================
-MOZ_ARG_DISABLE_BOOL(jsd,
-[  --disable-jsd           Disable JavaScript debug library],
-    MOZ_JSDEBUGGER=,
-    MOZ_JSDEBUGGER=1)
-
-
-dnl ========================================================
 dnl = Enable IPDL's "expensive" unit tests
 dnl ========================================================
 MOZ_IPDL_TESTS=
 
 MOZ_ARG_ENABLE_BOOL(ipdl-tests,
 [  --enable-ipdl-tests     Enable expensive IPDL tests],
     MOZ_IPDL_TESTS=1,
     MOZ_IPDL_TESTS=)
@@ -6177,21 +6167,16 @@ if test -n "$LIBXUL_SDK_DIR" -a `echo "$
 fi
 
 if test `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
     MOZ_GIO_COMPONENT=1
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gio||'`
 fi
 AC_SUBST(MOZ_GIO_COMPONENT)
 
-if test -z "$MOZ_JSDEBUGGER" -a `echo "$MOZ_EXTENSIONS" | grep -c venkman` -ne 0; then
-    AC_MSG_WARN([Cannot build venkman without JavaScript debug library. Removing venkman from MOZ_EXTENSIONS.])
-    MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|venkman||'`
-fi
-
 dnl Remove dupes
 MOZ_EXTENSIONS=`${PERL} ${srcdir}/build/unix/uniq.pl ${MOZ_EXTENSIONS}`
 
 dnl Ensure every extension exists, to avoid mostly-inscrutable error messages
 dnl when trying to build a nonexistent extension.
 for extension in $MOZ_EXTENSIONS; do
     if test ! -d "${srcdir}/extensions/${extension}"; then
         AC_MSG_ERROR([Unrecognized extension provided to --enable-extensions: ${extension}.])
@@ -8190,17 +8175,17 @@ dnl disable xul
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(xul,
 [  --disable-xul           Disable XUL],
     MOZ_XUL= )
 if test "$MOZ_XUL"; then
   AC_DEFINE(MOZ_XUL)
 else
   dnl remove extensions that require XUL
-  MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's/inspector//' -e 's/venkman//' -e 's/irc//' -e 's/tasks//'`
+  MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's/inspector//' -e 's/irc//' -e 's/tasks//'`
 fi
 
 AC_SUBST(MOZ_XUL)
 
 dnl ========================================================
 dnl disable profile locking
 dnl   do no use this in applications that can have more than
 dnl   one process accessing the profile directory.
@@ -8424,17 +8409,16 @@ AC_SUBST(MOZ_PREF_EXTENSIONS)
 AC_SUBST(MOZ_JS_LIBS)
 AC_SUBST(MOZ_DEBUG)
 AC_SUBST(MOZ_DEBUG_SYMBOLS)
 AC_SUBST(MOZ_DEBUG_ENABLE_DEFS)
 AC_SUBST(MOZ_DEBUG_DISABLE_DEFS)
 AC_SUBST(MOZ_DEBUG_LDFLAGS)
 AC_SUBST(WARNINGS_AS_ERRORS)
 AC_SUBST(MOZ_EXTENSIONS)
-AC_SUBST(MOZ_JSDEBUGGER)
 AC_SUBST(MOZ_ENABLE_PROFILER_SPS)
 AC_SUBST(MOZ_JPROF)
 AC_SUBST(MOZ_SHARK)
 AC_SUBST(MOZ_INSTRUMENTS)
 AC_SUBST(MOZ_CALLGRIND)
 AC_SUBST(MOZ_VTUNE)
 AC_SUBST(MOZ_PROFILING)
 AC_SUBST(LIBICONV)
--- a/content/svg/content/src/SVGEllipseElement.cpp
+++ b/content/svg/content/src/SVGEllipseElement.cpp
@@ -120,15 +120,15 @@ SVGEllipseElement::BuildPath()
   GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
 
   if (rx <= 0.0f || ry <= 0.0f) {
     return nullptr;
   }
 
   RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
 
-  ArcToBezier(pathBuilder.get(), Point(x, y), Size(rx, ry), 0, Float(2*M_PI), false);
+  EllipseToBezier(pathBuilder.get(), Point(x, y), Size(rx, ry));
 
   return pathBuilder->Finish();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -177,14 +177,14 @@ include('/ipc/chromium/chromium-config.m
 
 FINAL_LIBRARY = 'gklayout'
 
 LOCAL_INCLUDES += [
     '/js/xpconnect/src',
     '/js/xpconnect/wrappers',
 ]
 
-for var in ('MOZ_JSDEBUGGER', 'MOZ_B2G_RIL', 'MOZ_B2G_FM'):
+for var in ('MOZ_B2G_RIL', 'MOZ_B2G_FM'):
     if CONFIG[var]:
         DEFINES[var] = True
 
 if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']:
     DEFINES['HAVE_SIDEBAR'] = True
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -225,20 +225,16 @@
 #ifdef HAVE_SIDEBAR
 #include "mozilla/dom/ExternalBinding.h"
 #endif
 
 #ifdef MOZ_WEBSPEECH
 #include "mozilla/dom/SpeechSynthesis.h"
 #endif
 
-#ifdef MOZ_JSDEBUGGER
-#include "jsdIDebuggerService.h"
-#endif
-
 #ifdef MOZ_B2G
 #include "nsPISocketTransportService.h"
 #endif
 
 // Apple system headers seem to have a check() macro.  <sigh>
 #ifdef check
 class nsIScriptTimeoutHandler;
 #undef check
@@ -10876,51 +10872,26 @@ nsGlobalWindow::ShowSlowScriptDialog()
 
   // Check if we should offer the option to debug
   JS::AutoFilename filename;
   unsigned lineno;
   bool hasFrame = JS::DescribeScriptedCaller(cx, &filename, &lineno);
 
   // Prioritize the SlowScriptDebug interface over JSD1.
   nsCOMPtr<nsISlowScriptDebugCallback> debugCallback;
-  bool oldDebugPossible = false;
 
   if (hasFrame) {
     const char *debugCID = "@mozilla.org/dom/slow-script-debug;1";
     nsCOMPtr<nsISlowScriptDebug> debugService = do_GetService(debugCID, &rv);
     if (NS_SUCCEEDED(rv)) {
       debugService->GetActivationHandler(getter_AddRefs(debugCallback));
     }
-
-    if (!debugCallback) {
-      oldDebugPossible = js::CanCallContextDebugHandler(cx);
-#ifdef MOZ_JSDEBUGGER
-      // Get the debugger service if necessary.
-      if (oldDebugPossible) {
-        bool jsds_IsOn = false;
-        const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1";
-        nsCOMPtr<jsdIExecutionHook> jsdHook;
-        nsCOMPtr<jsdIDebuggerService> jsds = do_GetService(jsdServiceCtrID, &rv);
-
-        // Check if there's a user for the debugger service that's 'on' for us
-        if (NS_SUCCEEDED(rv)) {
-          jsds->GetDebuggerHook(getter_AddRefs(jsdHook));
-          jsds->GetIsOn(&jsds_IsOn);
-        }
-
-        // If there is a debug handler registered for this runtime AND
-        // ((jsd is on AND has a hook) OR (jsd isn't on (something else debugs)))
-        // then something useful will be done with our request to debug.
-        oldDebugPossible = ((jsds_IsOn && (jsdHook != nullptr)) || !jsds_IsOn);
-      }
-#endif
-    }
-  }
-
-  bool showDebugButton = debugCallback || oldDebugPossible;
+  }
+
+  bool showDebugButton = !!debugCallback;
 
   // Get localizable strings
   nsXPIDLString title, msg, stopButton, waitButton, debugButton, neverShowDlg;
 
   rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
                                           "KillScriptTitle",
                                           title);
 
@@ -11019,20 +10990,16 @@ nsGlobalWindow::ShowSlowScriptDialog()
   if (NS_SUCCEEDED(rv) && (buttonPressed == 0)) {
     return neverShowDlgChk ? AlwaysContinueSlowScript : ContinueSlowScript;
   }
   if (buttonPressed == 2) {
     if (debugCallback) {
       rv = debugCallback->HandleSlowScriptDebug(this);
       return NS_SUCCEEDED(rv) ? ContinueSlowScript : KillSlowScript;
     }
-
-    if (oldDebugPossible) {
-      return js_CallContextDebugHandler(cx) ? ContinueSlowScript : KillSlowScript;
-    }
   }
   JS_ClearPendingException(cx);
   return KillSlowScript;
 }
 
 uint32_t
 nsGlobalWindow::FindInsertionIndex(IdleObserverHolder* aIdleObserver)
 {
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -65,19 +65,16 @@
 #include "nsJSPrincipals.h"
 
 #ifdef XP_MACOSX
 // AssertMacros.h defines 'check' and conflicts with AccessCheck.h
 #undef check
 #endif
 #include "AccessCheck.h"
 
-#ifdef MOZ_JSDEBUGGER
-#include "jsdIDebuggerService.h"
-#endif
 #ifdef MOZ_LOGGING
 // Force PR_LOGGING so we can get JS strict warnings even in release builds
 #define FORCE_PR_LOG 1
 #endif
 #include "prlog.h"
 #include "prthread.h"
 
 #include "mozilla/Preferences.h"
--- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
@@ -2,23 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 
 #include "BluetoothA2dpManager.h"
-
-#include <hardware/bluetooth.h>
-#include <hardware/bt_av.h>
-#if ANDROID_VERSION > 17
-#include <hardware/bt_rc.h>
-#endif
-
+#include "BluetoothInterface.h"
 #include "BluetoothCommon.h"
 #include "BluetoothService.h"
 #include "BluetoothSocket.h"
 #include "BluetoothUtils.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
@@ -32,19 +26,19 @@ USING_BLUETOOTH_NAMESPACE
 #define AVRC_ID_REWIND  0x48
 #define AVRC_ID_FAST_FOR 0x49
 #define AVRC_KEY_PRESS_STATE  1
 #define AVRC_KEY_RELEASE_STATE  0
 
 namespace {
   StaticRefPtr<BluetoothA2dpManager> sBluetoothA2dpManager;
   bool sInShutdown = false;
-  static const btav_interface_t* sBtA2dpInterface;
+  static BluetoothA2dpInterface* sBtA2dpInterface;
 #if ANDROID_VERSION > 17
-  static const btrc_interface_t* sBtAvrcpInterface;
+  static BluetoothAvrcpInterface* sBtAvrcpInterface;
 #endif
 } // anonymous namespace
 
 class SinkPropertyChangedHandler : public nsRunnable
 {
 public:
   SinkPropertyChangedHandler(const BluetoothSignal& aSignal)
     : mSignal(aSignal)
@@ -170,17 +164,17 @@ public:
     for (int i = 0; i < mNumAttr; i++) {
       nsAutoString attrText;
       attrs[i].attr_id = mPlayerAttrs[i];
       ConvertAttributeString(mPlayerAttrs[i], attrText);
       strcpy((char *)attrs[i].text, NS_ConvertUTF16toUTF8(attrText).get());
     }
 
     NS_ENSURE_TRUE(sBtAvrcpInterface, NS_OK);
-    sBtAvrcpInterface->get_element_attr_rsp(mNumAttr, attrs);
+    sBtAvrcpInterface->GetElementAttrRsp(mNumAttr, attrs);
 
     return NS_OK;
   }
 private:
   uint8_t mNumAttr;
   btrc_media_attr_t* mPlayerAttrs;
 };
 
@@ -503,34 +497,32 @@ static btrc_callbacks_t sBtAvrcpCallback
  * It is important to register a2dp callbacks before enable() gets called.
  * It is required to register a2dp callbacks before a2dp media task
  * starts up.
  */
 // static
 void
 BluetoothA2dpManager::InitA2dpInterface()
 {
-  const bt_interface_t* btInf = GetBluetoothInterface();
+  BluetoothInterface* btInf = BluetoothInterface::GetInstance();
   NS_ENSURE_TRUE_VOID(btInf);
 
-  sBtA2dpInterface = (btav_interface_t *)btInf->
-    get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID);
+  sBtA2dpInterface = btInf->GetBluetoothA2dpInterface();
   NS_ENSURE_TRUE_VOID(sBtA2dpInterface);
 
-  int ret = sBtA2dpInterface->init(&sBtA2dpCallbacks);
+  int ret = sBtA2dpInterface->Init(&sBtA2dpCallbacks);
   if (ret != BT_STATUS_SUCCESS) {
     BT_LOGR("Warning: failed to init a2dp module");
   }
 
 #if ANDROID_VERSION > 17
-  sBtAvrcpInterface = (btrc_interface_t *)btInf->
-    get_profile_interface(BT_PROFILE_AV_RC_ID);
+  sBtAvrcpInterface = btInf->GetBluetoothAvrcpInterface();
   NS_ENSURE_TRUE_VOID(sBtAvrcpInterface);
 
-  ret = sBtAvrcpInterface->init(&sBtAvrcpCallbacks);
+  ret = sBtAvrcpInterface->Init(&sBtAvrcpCallbacks);
   if (ret != BT_STATUS_SUCCESS) {
     BT_LOGR("Warning: failed to init avrcp module");
   }
 #endif
 }
 
 BluetoothA2dpManager::~BluetoothA2dpManager()
 {
@@ -605,22 +597,22 @@ BluetoothA2dpManager::Get()
 
 // static
 void
 BluetoothA2dpManager::DeinitA2dpInterface()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (sBtA2dpInterface) {
-    sBtA2dpInterface->cleanup();
+    sBtA2dpInterface->Cleanup();
     sBtA2dpInterface = nullptr;
   }
 #if ANDROID_VERSION > 17
   if (sBtAvrcpInterface) {
-    sBtAvrcpInterface->cleanup();
+    sBtAvrcpInterface->Cleanup();
     sBtAvrcpInterface = nullptr;
   }
 #endif
 }
 
 void
 BluetoothA2dpManager::HandleShutdown()
 {
@@ -656,17 +648,17 @@ BluetoothA2dpManager::Connect(const nsAS
     BT_LOGR("sBluetoothA2dpInterface is null");
     aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
     return;
   }
 
   bt_bdaddr_t remoteAddress;
   StringToBdAddressType(aDeviceAddress, &remoteAddress);
 
-  bt_status_t result = sBtA2dpInterface->connect(&remoteAddress);
+  bt_status_t result = sBtA2dpInterface->Connect(&remoteAddress);
   if (BT_STATUS_SUCCESS != result) {
     BT_LOGR("Failed to connect: %x", result);
     aController->NotifyCompletion(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
     return;
   }
 }
 
 void
@@ -698,17 +690,17 @@ BluetoothA2dpManager::Disconnect(Bluetoo
     BT_LOGR("sBluetoothA2dpInterface is null");
     aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
     return;
   }
 
   bt_bdaddr_t remoteAddress;
   StringToBdAddressType(mDeviceAddress, &remoteAddress);
 
-  bt_status_t result = sBtA2dpInterface->disconnect(&remoteAddress);
+  bt_status_t result = sBtA2dpInterface->Disconnect(&remoteAddress);
   if (BT_STATUS_SUCCESS != result) {
     BT_LOGR("Failed to disconnect: %x", result);
     aController->NotifyCompletion(NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
     return;
   }
 }
 
 void
@@ -933,24 +925,24 @@ BluetoothA2dpManager::UpdateMetaData(con
     btrc_register_notification_t param;
     // convert to network big endian format
     // since track stores as uint8[8]
     // 56 = 8 * (BTRC_UID_SIZE -1)
     for (int i = 0; i < BTRC_UID_SIZE; ++i) {
       param.track[i] = (aMediaNumber >> (56 - 8 * i));
     }
     mTrackChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
-    sBtAvrcpInterface->register_notification_rsp(BTRC_EVT_TRACK_CHANGE,
-                                                 BTRC_NOTIFICATION_TYPE_CHANGED,
-                                                 &param);
+    sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_TRACK_CHANGE,
+                                               BTRC_NOTIFICATION_TYPE_CHANGED,
+                                               &param);
     if (mPlayPosChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) {
       param.song_pos = mPosition;
       // EVENT_PLAYBACK_POS_CHANGED shall be notified if changed current track
       mPlayPosChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
-      sBtAvrcpInterface->register_notification_rsp(
+      sBtAvrcpInterface->RegisterNotificationRsp(
         BTRC_EVT_PLAY_POS_CHANGED,
         BTRC_NOTIFICATION_TYPE_CHANGED,
         &param);
     }
   }
 
   mTitle.Assign(aTitle);
   mArtist.Assign(aArtist);
@@ -970,37 +962,37 @@ BluetoothA2dpManager::UpdatePlayStatus(u
                                        uint32_t aPosition,
                                        ControlPlayStatus aPlayStatus)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
 #if ANDROID_VERSION > 17
   NS_ENSURE_TRUE_VOID(sBtAvrcpInterface);
   // always update playstatus first
-  sBtAvrcpInterface->get_play_status_rsp((btrc_play_status_t)aPlayStatus,
-                                         aDuration, aPosition);
+  sBtAvrcpInterface->GetPlayStatusRsp((btrc_play_status_t)aPlayStatus,
+                                      aDuration, aPosition);
   // when play status changed, send both play status and position
   if (mPlayStatus != aPlayStatus &&
       mPlayStatusChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) {
     btrc_register_notification_t param;
     param.play_status = (btrc_play_status_t)aPlayStatus;
     mPlayStatusChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
-    sBtAvrcpInterface->register_notification_rsp(BTRC_EVT_PLAY_STATUS_CHANGED,
-                                                 BTRC_NOTIFICATION_TYPE_CHANGED,
-                                                 &param);
+    sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_PLAY_STATUS_CHANGED,
+                                               BTRC_NOTIFICATION_TYPE_CHANGED,
+                                               &param);
   }
 
   if (mPosition != aPosition &&
       mPlayPosChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) {
     btrc_register_notification_t param;
     param.song_pos = aPosition;
     mPlayPosChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
-    sBtAvrcpInterface->register_notification_rsp(BTRC_EVT_PLAY_POS_CHANGED,
-                                                 BTRC_NOTIFICATION_TYPE_CHANGED,
-                                                 &param);
+    sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_PLAY_POS_CHANGED,
+                                               BTRC_NOTIFICATION_TYPE_CHANGED,
+                                               &param);
   }
 
   mDuration = aDuration;
   mPosition = aPosition;
   mPlayStatus = aPlayStatus;
 #endif
 }
 
@@ -1056,19 +1048,19 @@ BluetoothA2dpManager::UpdateRegisterNoti
         param.song_pos = 0xFFFFFFFF;
       }
       mPlaybackInterval = aParam;
       break;
     default:
       break;
   }
 
-  sBtAvrcpInterface->register_notification_rsp((btrc_event_id_t)aEventId,
-                                               BTRC_NOTIFICATION_TYPE_INTERIM,
-                                               &param);
+  sBtAvrcpInterface->RegisterNotificationRsp((btrc_event_id_t)aEventId,
+                                              BTRC_NOTIFICATION_TYPE_INTERIM,
+                                              &param);
 #endif
 }
 
 void
 BluetoothA2dpManager::GetAlbum(nsAString& aAlbum)
 {
   aAlbum.Assign(mAlbum);
 }
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothInterface.cpp
@@ -0,0 +1,659 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "BluetoothInterface.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+template<class T>
+struct interface_traits
+{ };
+
+//
+// Socket Interface
+//
+
+template<>
+struct interface_traits<BluetoothSocketInterface>
+{
+  typedef const btsock_interface_t const_interface_type;
+
+  static const char* profile_id()
+  {
+    return BT_PROFILE_SOCKETS_ID;
+  }
+};
+
+bt_status_t
+BluetoothSocketInterface::Listen(btsock_type_t aType,
+                                 const char* aServiceName,
+                                 const uint8_t* aServiceUuid, int aChannel,
+                                 int& aSockFd, int aFlags)
+{
+  return mInterface->listen(aType, aServiceName, aServiceUuid, aChannel,
+                           &aSockFd, aFlags);
+}
+
+bt_status_t
+BluetoothSocketInterface::Connect(const bt_bdaddr_t* aBdAddr,
+                                  btsock_type_t aType, const uint8_t* aUuid,
+                                  int aChannel, int& aSockFd, int aFlags)
+{
+  return mInterface->connect(aBdAddr, aType, aUuid, aChannel, &aSockFd,
+                             aFlags);
+}
+
+BluetoothSocketInterface::BluetoothSocketInterface(
+  const btsock_interface_t* aInterface)
+: mInterface(aInterface)
+{
+  MOZ_ASSERT(mInterface);
+}
+
+BluetoothSocketInterface::~BluetoothSocketInterface()
+{ }
+
+//
+// Handsfree Interface
+//
+
+template<>
+struct interface_traits<BluetoothHandsfreeInterface>
+{
+  typedef const bthf_interface_t const_interface_type;
+
+  static const char* profile_id()
+  {
+    return BT_PROFILE_HANDSFREE_ID;
+  }
+};
+
+BluetoothHandsfreeInterface::BluetoothHandsfreeInterface(
+  const bthf_interface_t* aInterface)
+: mInterface(aInterface)
+{
+  MOZ_ASSERT(mInterface);
+}
+
+BluetoothHandsfreeInterface::~BluetoothHandsfreeInterface()
+{ }
+
+bt_status_t
+BluetoothHandsfreeInterface::Init(bthf_callbacks_t* aCallbacks)
+{
+  return mInterface->init(aCallbacks);
+}
+
+void
+BluetoothHandsfreeInterface::Cleanup()
+{
+  mInterface->cleanup();
+}
+
+/* Connect / Disconnect */
+
+bt_status_t
+BluetoothHandsfreeInterface::Connect(bt_bdaddr_t* aBdAddr)
+{
+  return mInterface->connect(aBdAddr);
+}
+
+bt_status_t
+BluetoothHandsfreeInterface::Disconnect(bt_bdaddr_t* aBdAddr)
+{
+  return mInterface->disconnect(aBdAddr);
+}
+
+bt_status_t
+BluetoothHandsfreeInterface::ConnectAudio(bt_bdaddr_t* aBdAddr)
+{
+  return mInterface->connect_audio(aBdAddr);
+}
+
+bt_status_t
+BluetoothHandsfreeInterface::DisconnectAudio(bt_bdaddr_t* aBdAddr)
+{
+  return mInterface->disconnect_audio(aBdAddr);
+}
+
+/* Voice Recognition */
+
+bt_status_t
+BluetoothHandsfreeInterface::StartVoiceRecognition()
+{
+  return mInterface->start_voice_recognition();
+}
+
+bt_status_t
+BluetoothHandsfreeInterface::StopVoiceRecognition()
+{
+  return mInterface->stop_voice_recognition();
+}
+
+/* Volume */
+
+bt_status_t
+BluetoothHandsfreeInterface::VolumeControl(bthf_volume_type_t aType,
+                                           int aVolume)
+{
+  return mInterface->volume_control(aType, aVolume);
+}
+
+/* Device status */
+
+bt_status_t
+BluetoothHandsfreeInterface::DeviceStatusNotification(
+  bthf_network_state_t aNtkState, bthf_service_type_t aSvcType, int aSignal,
+  int aBattChg)
+{
+  return mInterface->device_status_notification(aNtkState, aSvcType, aSignal,
+                                                aBattChg);
+}
+
+/* Responses */
+
+bt_status_t
+BluetoothHandsfreeInterface::CopsResponse(const char* aCops)
+{
+  return mInterface->cops_response(aCops);
+}
+
+bt_status_t
+BluetoothHandsfreeInterface::CindResponse(int aSvc, int aNumActive,
+                                          int aNumHeld,
+                                          bthf_call_state_t aCallSetupState,
+                                          int aSignal, int aRoam, int aBattChg)
+{
+  return mInterface->cind_response(aSvc, aNumActive, aNumHeld,
+                                   aCallSetupState, aSignal, aRoam,
+                                   aBattChg);
+}
+
+bt_status_t
+BluetoothHandsfreeInterface::FormattedAtResponse(const char* aRsp)
+{
+  return mInterface->formatted_at_response(aRsp);
+}
+
+bt_status_t
+BluetoothHandsfreeInterface::AtResponse(bthf_at_response_t aResponseCode,
+                                        int aErrorCode)
+{
+  return mInterface->at_response(aResponseCode, aErrorCode);
+}
+
+bt_status_t
+BluetoothHandsfreeInterface::ClccResponse(int aIndex,
+                                          bthf_call_direction_t aDir,
+                                          bthf_call_state_t aState,
+                                          bthf_call_mode_t aMode,
+                                          bthf_call_mpty_type_t aMpty,
+                                          const char* aNumber,
+                                          bthf_call_addrtype_t aType)
+{
+  return mInterface->clcc_response(aIndex, aDir, aState, aMode, aMpty,
+                                   aNumber, aType);
+}
+
+/* Phone State */
+
+bt_status_t
+BluetoothHandsfreeInterface::PhoneStateChange(int aNumActive, int aNumHeld,
+  bthf_call_state_t aCallSetupState, const char* aNumber,
+  bthf_call_addrtype_t aType)
+{
+  return mInterface->phone_state_change(aNumActive, aNumHeld, aCallSetupState,
+                                        aNumber, aType);
+}
+
+//
+// Bluetooth Advanced Audio Interface
+//
+
+template<>
+struct interface_traits<BluetoothA2dpInterface>
+{
+  typedef const btav_interface_t const_interface_type;
+
+  static const char* profile_id()
+  {
+    return BT_PROFILE_ADVANCED_AUDIO_ID;
+  }
+};
+
+BluetoothA2dpInterface::BluetoothA2dpInterface(
+  const btav_interface_t* aInterface)
+: mInterface(aInterface)
+{
+  MOZ_ASSERT(mInterface);
+}
+
+BluetoothA2dpInterface::~BluetoothA2dpInterface()
+{ }
+
+bt_status_t
+BluetoothA2dpInterface::Init(btav_callbacks_t* aCallbacks)
+{
+  return mInterface->init(aCallbacks);
+}
+
+void
+BluetoothA2dpInterface::Cleanup()
+{
+  mInterface->cleanup();
+}
+
+bt_status_t
+BluetoothA2dpInterface::Connect(bt_bdaddr_t *aBdAddr)
+{
+  return mInterface->connect(aBdAddr);
+}
+
+bt_status_t
+BluetoothA2dpInterface::Disconnect(bt_bdaddr_t *aBdAddr)
+{
+  return mInterface->disconnect(aBdAddr);
+}
+
+//
+// Bluetooth AVRCP Interface
+//
+
+#if ANDROID_VERSION >= 18
+template<>
+struct interface_traits<BluetoothAvrcpInterface>
+{
+  typedef const btrc_interface_t const_interface_type;
+
+  static const char* profile_id()
+  {
+    return BT_PROFILE_AV_RC_ID;
+  }
+};
+
+BluetoothAvrcpInterface::BluetoothAvrcpInterface(
+  const btrc_interface_t* aInterface)
+: mInterface(aInterface)
+{
+  MOZ_ASSERT(mInterface);
+}
+
+BluetoothAvrcpInterface::~BluetoothAvrcpInterface()
+{ }
+
+bt_status_t
+BluetoothAvrcpInterface::Init(btrc_callbacks_t* aCallbacks)
+{
+  return mInterface->init(aCallbacks);
+}
+
+void
+BluetoothAvrcpInterface::Cleanup()
+{
+  mInterface->cleanup();
+}
+
+bt_status_t
+BluetoothAvrcpInterface::GetPlayStatusRsp(btrc_play_status_t aPlayStatus,
+                                          uint32_t aSongLen, uint32_t aSongPos)
+{
+  return mInterface->get_play_status_rsp(aPlayStatus, aSongLen, aSongPos);
+}
+
+bt_status_t
+BluetoothAvrcpInterface::ListPlayerAppAttrRsp(int aNumAttr,
+                                              btrc_player_attr_t* aPAttrs)
+{
+  return mInterface->list_player_app_attr_rsp(aNumAttr, aPAttrs);
+}
+
+bt_status_t
+BluetoothAvrcpInterface::ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals)
+{
+  return mInterface->list_player_app_value_rsp(aNumVal, aPVals);
+}
+
+bt_status_t
+BluetoothAvrcpInterface::GetPlayerAppValueRsp(btrc_player_settings_t* aPVals)
+{
+  return mInterface->get_player_app_value_rsp(aPVals);
+}
+
+bt_status_t
+BluetoothAvrcpInterface::GetPlayerAppAttrTextRsp(int aNumAttr,
+  btrc_player_setting_text_t* aPAttrs)
+{
+  return mInterface->get_player_app_attr_text_rsp(aNumAttr, aPAttrs);
+}
+
+bt_status_t
+BluetoothAvrcpInterface::GetPlayerAppValueTextRsp(int aNumVal,
+  btrc_player_setting_text_t* aPVals)
+{
+  return mInterface->get_player_app_value_text_rsp(aNumVal, aPVals);
+}
+
+bt_status_t
+BluetoothAvrcpInterface::GetElementAttrRsp(uint8_t aNumAttr,
+                                           btrc_element_attr_val_t* aPAttrs)
+{
+  return mInterface->get_element_attr_rsp(aNumAttr, aPAttrs);
+}
+
+bt_status_t
+BluetoothAvrcpInterface::SetPlayerAppValueRsp(btrc_status_t aRspStatus)
+{
+  return mInterface->set_player_app_value_rsp(aRspStatus);
+}
+
+bt_status_t
+BluetoothAvrcpInterface::RegisterNotificationRsp(btrc_event_id_t aEventId,
+  btrc_notification_type_t aType, btrc_register_notification_t* aPParam)
+{
+  return mInterface->register_notification_rsp(aEventId, aType, aPParam);
+}
+
+bt_status_t
+BluetoothAvrcpInterface::SetVolume(uint8_t aVolume)
+{
+#if ANDROID_VERSION >= 19
+  return mInterface->set_volume(aVolume);
+#else
+  return BT_STATUS_UNSUPPORTED;
+#endif
+}
+#endif
+
+//
+// Bluetooth Core Interface
+//
+
+/* returns the container structure of a variable; _t is the container's
+ * type, _v the name of the variable, and _m is _v's field within _t
+ */
+#define container(_t, _v, _m) \
+  ( (_t*)( ((const unsigned char*)(_v)) - offsetof(_t, _m) ) )
+
+BluetoothInterface*
+BluetoothInterface::GetInstance()
+{
+  static BluetoothInterface* sBluetoothInterface;
+
+  if (sBluetoothInterface) {
+    return sBluetoothInterface;
+  }
+
+  /* get driver module */
+
+  const hw_module_t* module;
+  int err = hw_get_module(BT_HARDWARE_MODULE_ID, &module);
+  if (err) {
+    BT_WARNING("hw_get_module failed: %s", strerror(err));
+    return nullptr;
+  }
+
+  /* get device */
+
+  hw_device_t* device;
+  err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+  if (err) {
+    BT_WARNING("open failed: %s", strerror(err));
+    return nullptr;
+  }
+
+  const bluetooth_device_t* bt_device =
+    container(bluetooth_device_t, device, common);
+
+  /* get interface */
+
+  const bt_interface_t* bt_interface = bt_device->get_bluetooth_interface();
+  if (!bt_interface) {
+    BT_WARNING("get_bluetooth_interface failed");
+    goto err_get_bluetooth_interface;
+  }
+
+  if (bt_interface->size != sizeof(*bt_interface)) {
+    BT_WARNING("interface of incorrect size");
+    goto err_bt_interface_size;
+  }
+
+  sBluetoothInterface = new BluetoothInterface(bt_interface);
+
+  return sBluetoothInterface;
+
+err_bt_interface_size:
+err_get_bluetooth_interface:
+  err = device->close(device);
+  if (err) {
+    BT_WARNING("close failed: %s", strerror(err));
+  }
+  return nullptr;
+}
+
+BluetoothInterface::BluetoothInterface(const bt_interface_t* aInterface)
+: mInterface(aInterface)
+{
+  MOZ_ASSERT(mInterface);
+}
+
+BluetoothInterface::~BluetoothInterface()
+{ }
+
+int
+BluetoothInterface::Init(bt_callbacks_t* aCallbacks)
+{
+  return mInterface->init(aCallbacks);
+}
+
+void
+BluetoothInterface::Cleanup()
+{
+  mInterface->cleanup();
+}
+
+int
+BluetoothInterface::Enable()
+{
+  return mInterface->enable();
+}
+
+int
+BluetoothInterface::Disable()
+{
+  return mInterface->disable();
+}
+
+/* Adapter Properties */
+
+int
+BluetoothInterface::GetAdapterProperties()
+{
+  return mInterface->get_adapter_properties();
+}
+
+int
+BluetoothInterface::GetAdapterProperty(bt_property_type_t aType)
+{
+  return mInterface->get_adapter_property(aType);
+}
+
+int
+BluetoothInterface::SetAdapterProperty(const bt_property_t* aProperty)
+{
+  return mInterface->set_adapter_property(aProperty);
+}
+
+/* Remote Device Properties */
+
+int
+BluetoothInterface::GetRemoteDeviceProperties(bt_bdaddr_t *aRemoteAddr)
+{
+  return mInterface->get_remote_device_properties(aRemoteAddr);
+}
+
+int
+BluetoothInterface::GetRemoteDeviceProperty(bt_bdaddr_t* aRemoteAddr,
+                                            bt_property_type_t aType)
+{
+  return mInterface->get_remote_device_property(aRemoteAddr, aType);
+}
+
+int
+BluetoothInterface::SetRemoteDeviceProperty(bt_bdaddr_t* aRemoteAddr,
+                                            const bt_property_t* aProperty)
+{
+  return mInterface->set_remote_device_property(aRemoteAddr, aProperty);
+}
+
+/* Remote Services */
+
+int
+BluetoothInterface::GetRemoteServiceRecord(bt_bdaddr_t* aRemoteAddr,
+                                           bt_uuid_t* aUuid)
+{
+  return mInterface->get_remote_service_record(aRemoteAddr, aUuid);
+}
+
+int
+BluetoothInterface::GetRemoteServices(bt_bdaddr_t* aRemoteAddr)
+{
+  return mInterface->get_remote_services(aRemoteAddr);
+}
+
+/* Discovery */
+
+int
+BluetoothInterface::StartDiscovery()
+{
+  return mInterface->start_discovery();
+}
+
+int
+BluetoothInterface::CancelDiscovery()
+{
+  return mInterface->cancel_discovery();
+}
+
+/* Bonds */
+
+int
+BluetoothInterface::CreateBond(const bt_bdaddr_t* aBdAddr)
+{
+  return mInterface->create_bond(aBdAddr);
+}
+
+int
+BluetoothInterface::RemoveBond(const bt_bdaddr_t* aBdAddr)
+{
+  return mInterface->remove_bond(aBdAddr);
+}
+
+int
+BluetoothInterface::CancelBond(const bt_bdaddr_t* aBdAddr)
+{
+  return mInterface->cancel_bond(aBdAddr);
+}
+
+/* Authentication */
+
+int
+BluetoothInterface::PinReply(const bt_bdaddr_t* aBdAddr, uint8_t aAccept,
+                             uint8_t aPinLen, bt_pin_code_t* aPinCode)
+{
+  return mInterface->pin_reply(aBdAddr, aAccept, aPinLen, aPinCode);
+}
+
+int
+BluetoothInterface::SspReply(const bt_bdaddr_t* aBdAddr,
+                             bt_ssp_variant_t aVariant,
+                             uint8_t aAccept, uint32_t aPasskey)
+{
+  return mInterface->ssp_reply(aBdAddr, aVariant, aAccept, aPasskey);
+}
+
+/* DUT Mode */
+
+int
+BluetoothInterface::DutModeConfigure(uint8_t aEnable)
+{
+  return mInterface->dut_mode_configure(aEnable);
+}
+
+int
+BluetoothInterface::DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen)
+{
+  return mInterface->dut_mode_send(aOpcode, aBuf, aLen);
+}
+
+/* LE Mode */
+
+int
+BluetoothInterface::LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen)
+{
+  return mInterface->le_test_mode(aOpcode, aBuf, aLen);
+}
+
+/* Profile Interfaces */
+
+template <class T>
+T*
+BluetoothInterface::GetProfileInterface()
+{
+  static T* sBluetoothProfileInterface;
+
+  if (sBluetoothProfileInterface) {
+    return sBluetoothProfileInterface;
+  }
+
+  typename interface_traits<T>::const_interface_type* interface =
+    reinterpret_cast<typename interface_traits<T>::const_interface_type*>(
+      mInterface->get_profile_interface(interface_traits<T>::profile_id()));
+
+  if (!interface) {
+    BT_WARNING("Bluetooth profile '%s' is not supported",
+               interface_traits<T>::profile_id());
+    return nullptr;
+  }
+
+  if (interface->size != sizeof(*interface)) {
+    BT_WARNING("interface of incorrect size");
+    return nullptr;
+  }
+
+  sBluetoothProfileInterface = new T(interface);
+
+  return sBluetoothProfileInterface;
+}
+
+BluetoothSocketInterface*
+BluetoothInterface::GetBluetoothSocketInterface()
+{
+  return GetProfileInterface<BluetoothSocketInterface>();
+}
+
+BluetoothHandsfreeInterface*
+BluetoothInterface::GetBluetoothHandsfreeInterface()
+{
+  return GetProfileInterface<BluetoothHandsfreeInterface>();
+}
+
+BluetoothA2dpInterface*
+BluetoothInterface::GetBluetoothA2dpInterface()
+{
+  return GetProfileInterface<BluetoothA2dpInterface>();
+}
+
+BluetoothAvrcpInterface*
+BluetoothInterface::GetBluetoothAvrcpInterface()
+{
+#if ANDROID_VERSION >= 18
+  return GetProfileInterface<BluetoothAvrcpInterface>();
+#else
+  return nullptr;
+#endif
+}
+
+END_BLUETOOTH_NAMESPACE
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothInterface.h
@@ -0,0 +1,263 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothinterface_h__
+#define mozilla_dom_bluetooth_bluedroid_bluetoothinterface_h__
+
+#include <hardware/bluetooth.h>
+#include <hardware/bt_sock.h>
+#include <hardware/bt_hf.h>
+#include <hardware/bt_av.h>
+#if ANDROID_VERSION >= 18
+#include <hardware/bt_rc.h>
+#endif
+#include "BluetoothCommon.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothInterface;
+
+//
+// Socket Interface
+//
+
+class BluetoothSocketInterface
+{
+public:
+  friend BluetoothInterface;
+
+  // Init and Cleanup is handled by BluetoothInterface
+
+  bt_status_t Listen(btsock_type_t aType,
+                     const char* aServiceName, const uint8_t* aServiceUuid,
+                     int aChannel, int& aSockFd, int aFlags);
+
+  bt_status_t Connect(const bt_bdaddr_t* aBdAddr, btsock_type_t aType,
+                      const uint8_t* aUuid, int aChannel, int& aSockFd,
+                      int aFlags);
+
+protected:
+  BluetoothSocketInterface(const btsock_interface_t* aInterface);
+  ~BluetoothSocketInterface();
+
+private:
+  const btsock_interface_t* mInterface;
+};
+
+//
+// Handsfree Interface
+//
+
+class BluetoothHandsfreeInterface
+{
+public:
+  friend BluetoothInterface;
+
+  bt_status_t Init(bthf_callbacks_t* aCallbacks);
+  void        Cleanup();
+
+  /* Connect / Disconnect */
+
+  bt_status_t Connect(bt_bdaddr_t* aBdAddr);
+  bt_status_t Disconnect(bt_bdaddr_t* aBdAddr);
+  bt_status_t ConnectAudio(bt_bdaddr_t* aBdAddr);
+  bt_status_t DisconnectAudio(bt_bdaddr_t* aBdAddr);
+
+  /* Voice Recognition */
+
+  bt_status_t StartVoiceRecognition();
+  bt_status_t StopVoiceRecognition();
+
+  /* Volume */
+
+  bt_status_t VolumeControl(bthf_volume_type_t aType, int aVolume);
+
+  /* Device status */
+
+  bt_status_t DeviceStatusNotification(bthf_network_state_t aNtkState,
+                                       bthf_service_type_t aSvcType,
+                                       int aSignal, int aBattChg);
+
+  /* Responses */
+
+  bt_status_t CopsResponse(const char* aCops);
+  bt_status_t CindResponse(int aSvc, int aNumActive, int aNumHeld,
+                           bthf_call_state_t aCallSetupState, int aSignal,
+                           int aRoam, int aBattChg);
+  bt_status_t FormattedAtResponse(const char* aRsp);
+  bt_status_t AtResponse(bthf_at_response_t aResponseCode, int aErrorCode);
+  bt_status_t ClccResponse(int aIndex, bthf_call_direction_t aDir,
+                           bthf_call_state_t aState, bthf_call_mode_t aMode,
+                           bthf_call_mpty_type_t aMpty, const char* aNumber,
+                           bthf_call_addrtype_t aType);
+
+  /* Phone State */
+
+  bt_status_t PhoneStateChange(int aNumActive, int aNumHeld,
+                               bthf_call_state_t aCallSetupState,
+                               const char* aNumber,
+                               bthf_call_addrtype_t aType);
+
+protected:
+  BluetoothHandsfreeInterface(const bthf_interface_t* aInterface);
+  ~BluetoothHandsfreeInterface();
+
+private:
+  const bthf_interface_t* mInterface;
+};
+
+//
+// Bluetooth Advanced Audio Interface
+//
+
+class BluetoothA2dpInterface
+{
+public:
+  friend BluetoothInterface;
+
+  bt_status_t Init(btav_callbacks_t *aCallbacks);
+  void        Cleanup();
+
+  bt_status_t Connect(bt_bdaddr_t *aBdAddr);
+  bt_status_t Disconnect(bt_bdaddr_t *aBdAddr);
+
+protected:
+  BluetoothA2dpInterface(const btav_interface_t* aInterface);
+  ~BluetoothA2dpInterface();
+
+private:
+  const btav_interface_t* mInterface;
+};
+
+//
+// Bluetooth AVRCP Interface
+//
+
+class BluetoothAvrcpInterface
+{
+#if ANDROID_VERSION >= 18
+public:
+  friend BluetoothInterface;
+
+  bt_status_t Init(btrc_callbacks_t* aCallbacks);
+  void        Cleanup();
+
+  bt_status_t GetPlayStatusRsp(btrc_play_status_t aPlayStatus,
+                               uint32_t aSongLen, uint32_t aSongPos);
+
+  bt_status_t ListPlayerAppAttrRsp(int aNumAttr, btrc_player_attr_t* aPAttrs);
+  bt_status_t ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals);
+
+  bt_status_t GetPlayerAppValueRsp(btrc_player_settings_t* aPVals);
+  bt_status_t GetPlayerAppAttrTextRsp(int aNumAttr,
+                                      btrc_player_setting_text_t* aPAttrs);
+  bt_status_t GetPlayerAppValueTextRsp(int aNumVal,
+                                       btrc_player_setting_text_t* aPVals);
+
+  bt_status_t GetElementAttrRsp(uint8_t aNumAttr,
+                                btrc_element_attr_val_t* aPAttrs);
+
+  bt_status_t SetPlayerAppValueRsp(btrc_status_t aRspStatus);
+
+  bt_status_t RegisterNotificationRsp(btrc_event_id_t aEventId,
+                                      btrc_notification_type_t aType,
+                                      btrc_register_notification_t* aPParam);
+
+  bt_status_t SetVolume(uint8_t aVolume);
+
+protected:
+  BluetoothAvrcpInterface(const btrc_interface_t* aInterface);
+  ~BluetoothAvrcpInterface();
+
+private:
+  const btrc_interface_t* mInterface;
+#endif
+};
+
+//
+// Bluetooth Core Interface
+//
+
+class BluetoothInterface
+{
+public:
+  static BluetoothInterface* GetInstance();
+
+  int  Init(bt_callbacks_t* aCallbacks);
+  void Cleanup();
+
+  int Enable();
+  int Disable();
+
+  /* Adapter Properties */
+
+  int GetAdapterProperties();
+  int GetAdapterProperty(bt_property_type_t aType);
+  int SetAdapterProperty(const bt_property_t* aProperty);
+
+  /* Remote Device Properties */
+
+  int GetRemoteDeviceProperties(bt_bdaddr_t *aRemoteAddr);
+  int GetRemoteDeviceProperty(bt_bdaddr_t* aRemoteAddr,
+                              bt_property_type_t aType);
+  int SetRemoteDeviceProperty(bt_bdaddr_t* aRemoteAddr,
+                              const bt_property_t* aProperty);
+
+  /* Remote Services */
+
+  int GetRemoteServiceRecord(bt_bdaddr_t* aRemoteAddr,
+                             bt_uuid_t* aUuid);
+  int GetRemoteServices(bt_bdaddr_t* aRemoteAddr);
+
+  /* Discovery */
+
+  int StartDiscovery();
+  int CancelDiscovery();
+
+  /* Bonds */
+
+  int CreateBond(const bt_bdaddr_t* aBdAddr);
+  int RemoveBond(const bt_bdaddr_t* aBdAddr);
+  int CancelBond(const bt_bdaddr_t* aBdAddr);
+
+  /* Authentication */
+
+  int PinReply(const bt_bdaddr_t* aBdAddr, uint8_t aAccept,
+               uint8_t aPinLen, bt_pin_code_t* aPinCode);
+
+  int SspReply(const bt_bdaddr_t* aBdAddr, bt_ssp_variant_t aVariant,
+               uint8_t aAccept, uint32_t aPasskey);
+
+  /* DUT Mode */
+
+  int DutModeConfigure(uint8_t aEnable);
+  int DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen);
+
+  /* LE Mode */
+
+  int LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen);
+
+  /* Profile Interfaces */
+
+  BluetoothSocketInterface* GetBluetoothSocketInterface();
+  BluetoothHandsfreeInterface* GetBluetoothHandsfreeInterface();
+  BluetoothA2dpInterface* GetBluetoothA2dpInterface();
+  BluetoothAvrcpInterface* GetBluetoothAvrcpInterface();
+
+protected:
+  BluetoothInterface(const bt_interface_t* aInterface);
+  ~BluetoothInterface();
+
+private:
+  template <class T>
+  T* GetProfileInterface();
+
+  const bt_interface_t* mInterface;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
--- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
@@ -13,21 +13,20 @@
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
 #include "BluetoothServiceBluedroid.h"
 
-#include <hardware/hardware.h>
-
 #include "BluetoothA2dpManager.h"
 #include "BluetoothHfpManager.h"
 #include "BluetoothOppManager.h"
+#include "BluetoothInterface.h"
 #include "BluetoothProfileController.h"
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothUtils.h"
 #include "BluetoothUuid.h"
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/ipc/UnixSocket.h"
 #include "mozilla/StaticMutex.h"
 #include "mozilla/StaticPtr.h"
@@ -53,17 +52,17 @@ using namespace mozilla::ipc;
 USING_BLUETOOTH_NAMESPACE
 
 // TODO: Non thread-safe static variables
 static nsString sAdapterBdAddress;
 static nsString sAdapterBdName;
 static InfallibleTArray<nsString> sAdapterBondedAddressArray;
 
 // Static variables below should only be used on *main thread*
-static const bt_interface_t* sBtInterface;
+static BluetoothInterface* sBtInterface;
 static nsTArray<nsRefPtr<BluetoothProfileController> > sControllerArray;
 static nsTArray<int> sRequestedDeviceCountArray;
 static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sSetPropertyRunnableArray;
 static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sGetDeviceRunnableArray;
 static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sBondingRunnableArray;
 static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sUnbondingRunnableArray;
 
 // Static variables below should only be used on *callback thread*
@@ -120,17 +119,17 @@ public:
     bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE;
     bt_property_t prop;
     prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
     prop.val = (void*)&mode;
     prop.len = sizeof(mode);
 
     NS_ENSURE_TRUE(sBtInterface, NS_ERROR_FAILURE);
 
-    int ret = sBtInterface->set_adapter_property(&prop);
+    int ret = sBtInterface->SetAdapterProperty(&prop);
     if (ret != BT_STATUS_SUCCESS) {
       BT_LOGR("Fail to set: BT_SCAN_MODE_CONNECTABLE");
     }
 
     // Try to fire event 'AdapterAdded' to fit the original behaviour when
     // we used BlueZ as backend.
     BluetoothService* bs = BluetoothService::Get();
     NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
@@ -154,17 +153,17 @@ public:
   NS_IMETHOD
   Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     // Cleanup bluetooth interfaces after BT state becomes BT_STATE_OFF.
     BluetoothHfpManager::DeinitHfpInterface();
     BluetoothA2dpManager::DeinitA2dpInterface();
-    sBtInterface->cleanup();
+    sBtInterface->Cleanup();
 
     return NS_OK;
   }
 };
 
 /**
  *  Static callback functions
  */
@@ -786,50 +785,38 @@ bt_callbacks_t sBluetoothCallbacks =
 };
 
 /**
  *  Static functions
  */
 static bool
 EnsureBluetoothHalLoad()
 {
-  hw_module_t* module;
-  hw_device_t* device;
-
-  int err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
-  if (err != 0) {
-    BT_LOGR("Error: %s", strerror(err));
-    return false;
-  }
-  module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
-  bluetooth_device_t* btDevice = (bluetooth_device_t *)device;
-  NS_ENSURE_TRUE(btDevice, false);
-
-  sBtInterface = btDevice->get_bluetooth_interface();
+  sBtInterface = BluetoothInterface::GetInstance();
   NS_ENSURE_TRUE(sBtInterface, false);
 
   return true;
 }
 
 static bool
 EnableInternal()
 {
-  int ret = sBtInterface->init(&sBluetoothCallbacks);
+  int ret = sBtInterface->Init(&sBluetoothCallbacks);
   if (ret != BT_STATUS_SUCCESS) {
     BT_LOGR("Error while setting the callbacks");
     sBtInterface = nullptr;
     return false;
   }
 
   // Register all the bluedroid callbacks before enable() get called
   // It is required to register a2dp callbacks before a2dp media task starts up.
   // If any interface cannot be initialized, turn on bluetooth core anyway.
   BluetoothHfpManager::InitHfpInterface();
   BluetoothA2dpManager::InitA2dpInterface();
-  return sBtInterface->enable();
+  return sBtInterface->Enable();
 }
 
 static nsresult
 StartStopGonkBluetooth(bool aShouldEnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_ENSURE_TRUE(sBtInterface, NS_ERROR_FAILURE);
@@ -842,17 +829,17 @@ StartStopGonkBluetooth(bool aShouldEnabl
     nsRefPtr<nsRunnable> runnable =
       new BluetoothService::ToggleBtAck(aShouldEnable);
     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
       BT_WARNING("Failed to dispatch to main thread!");
     }
     return NS_OK;
   }
 
-  int ret = aShouldEnable ? EnableInternal() : sBtInterface->disable();
+  int ret = aShouldEnable ? EnableInternal() : sBtInterface->Disable();
   NS_ENSURE_TRUE(ret == BT_STATUS_SUCCESS, NS_ERROR_FAILURE);
 
   return NS_OK;
 }
 
 static void
 ReplyStatusError(BluetoothReplyRunnable* aBluetoothReplyRunnable,
                  int aStatusCode, const nsAString& aCustomMsg)
@@ -997,17 +984,17 @@ BluetoothServiceBluedroid::GetConnectedD
     return NS_OK;
   }
 
   for (int i = 0; i < requestedDeviceCount; i++) {
     // Retrieve all properties of devices
     bt_bdaddr_t addressType;
     StringToBdAddressType(deviceAddresses[i], &addressType);
 
-    int ret = sBtInterface->get_remote_device_properties(&addressType);
+    int ret = sBtInterface->GetRemoteDeviceProperties(&addressType);
     if (ret != BT_STATUS_SUCCESS) {
       DispatchBluetoothReply(aRunnable, BluetoothValue(true),
                              NS_LITERAL_STRING("GetConnectedDeviceFailed"));
       return NS_OK;
     }
   }
 
   sRequestedDeviceCountArray.AppendElement(requestedDeviceCount);
@@ -1030,17 +1017,17 @@ BluetoothServiceBluedroid::GetPairedDevi
     DispatchBluetoothReply(aRunnable, BluetoothValue(emptyArr), EmptyString());
     return NS_OK;
   }
 
   for (int i = 0; i < requestedDeviceCount; i++) {
     // Retrieve all properties of devices
     bt_bdaddr_t addressType;
     StringToBdAddressType(aDeviceAddress[i], &addressType);
-    int ret = sBtInterface->get_remote_device_properties(&addressType);
+    int ret = sBtInterface->GetRemoteDeviceProperties(&addressType);
     if (ret != BT_STATUS_SUCCESS) {
       DispatchBluetoothReply(aRunnable, BluetoothValue(true),
                              NS_LITERAL_STRING("GetPairedDeviceFailed"));
       return NS_OK;
     }
   }
 
   sRequestedDeviceCountArray.AppendElement(requestedDeviceCount);
@@ -1052,17 +1039,17 @@ BluetoothServiceBluedroid::GetPairedDevi
 nsresult
 BluetoothServiceBluedroid::StartDiscoveryInternal(
   BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
 
-  int ret = sBtInterface->start_discovery();
+  int ret = sBtInterface->StartDiscovery();
   if (ret != BT_STATUS_SUCCESS) {
     ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("StartDiscovery"));
 
     return NS_OK;
   }
 
   DispatchBluetoothReply(aRunnable, true, EmptyString());
 
@@ -1072,17 +1059,17 @@ BluetoothServiceBluedroid::StartDiscover
 nsresult
 BluetoothServiceBluedroid::StopDiscoveryInternal(
   BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
 
-  int ret = sBtInterface->cancel_discovery();
+  int ret = sBtInterface->CancelDiscovery();
   if (ret != BT_STATUS_SUCCESS) {
     ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("StopDiscovery"));
     return NS_ERROR_FAILURE;
   }
 
   DispatchBluetoothReply(aRunnable, true, EmptyString());
 
   return NS_OK;
@@ -1131,17 +1118,17 @@ BluetoothServiceBluedroid::SetProperty(B
     prop.len = sizeof(scanMode);
   } else {
     BT_LOGR("SetProperty but the property cannot be recognized correctly.");
     return NS_OK;
   }
 
   sSetPropertyRunnableArray.AppendElement(aRunnable);
 
-  int ret = sBtInterface->set_adapter_property(&prop);
+  int ret = sBtInterface->SetAdapterProperty(&prop);
   if (ret != BT_STATUS_SUCCESS) {
     ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("SetProperty"));
   }
 
   return NS_OK;
 }
 
 nsresult
@@ -1168,17 +1155,17 @@ BluetoothServiceBluedroid::CreatePairedD
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
 
   bt_bdaddr_t remoteAddress;
   StringToBdAddressType(aDeviceAddress, &remoteAddress);
 
-  int ret = sBtInterface->create_bond(&remoteAddress);
+  int ret = sBtInterface->CreateBond(&remoteAddress);
   if (ret != BT_STATUS_SUCCESS) {
     ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("CreatedPairedDevice"));
   } else {
     sBondingRunnableArray.AppendElement(aRunnable);
   }
 
   return NS_OK;
 }
@@ -1189,17 +1176,17 @@ BluetoothServiceBluedroid::RemoveDeviceI
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
 
   bt_bdaddr_t remoteAddress;
   StringToBdAddressType(aDeviceAddress, &remoteAddress);
 
-  int ret = sBtInterface->remove_bond(&remoteAddress);
+  int ret = sBtInterface->RemoveBond(&remoteAddress);
   if (ret != BT_STATUS_SUCCESS) {
     ReplyStatusError(aRunnable, ret,
                      NS_LITERAL_STRING("RemoveDevice"));
   } else {
     sUnbondingRunnableArray.AppendElement(aRunnable);
   }
 
   return NS_OK;
@@ -1212,17 +1199,17 @@ BluetoothServiceBluedroid::SetPinCodeInt
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   ENSURE_BLUETOOTH_IS_READY(aRunnable, false);
 
   bt_bdaddr_t remoteAddress;
   StringToBdAddressType(aDeviceAddress, &remoteAddress);
 
-  int ret = sBtInterface->pin_reply(
+  int ret = sBtInterface->PinReply(
       &remoteAddress, true, aPinCode.Length(),
       (bt_pin_code_t*)NS_ConvertUTF16toUTF8(aPinCode).get());
 
   if (ret != BT_STATUS_SUCCESS) {
     ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("SetPinCode"));
   } else {
     DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
   }
@@ -1245,18 +1232,18 @@ BluetoothServiceBluedroid::SetPairingCon
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   ENSURE_BLUETOOTH_IS_READY(aRunnable, false);
 
   bt_bdaddr_t remoteAddress;
   StringToBdAddressType(aDeviceAddress, &remoteAddress);
 
-  int ret = sBtInterface->ssp_reply(&remoteAddress, (bt_ssp_variant_t)0,
-                                    aConfirm, 0);
+  int ret = sBtInterface->SspReply(&remoteAddress, (bt_ssp_variant_t)0,
+                                   aConfirm, 0);
   if (ret != BT_STATUS_SUCCESS) {
     ReplyStatusError(aRunnable, ret,
                      NS_LITERAL_STRING("SetPairingConfirmation"));
   } else {
     DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
   }
 
   return true;
@@ -1309,22 +1296,16 @@ ConnectDisconnect(bool aConnect, const n
    * that other request is pushed into the quene and is popped out after the
    * first one is completed. See NextBluetoothProfileController() for details.
    */
   if (sControllerArray.Length() == 1) {
     sControllerArray[0]->StartSession();
   }
 }
 
-const bt_interface_t*
-BluetoothServiceBluedroid::GetBluetoothInterface()
-{
-  return sBtInterface;
-}
-
 void
 BluetoothServiceBluedroid::Connect(const nsAString& aDeviceAddress,
                                    uint32_t aCod,
                                    uint16_t aServiceUuid,
                                    BluetoothReplyRunnable* aRunnable)
 {
   ConnectDisconnect(true, aDeviceAddress, aRunnable, aServiceUuid, aCod);
 }
--- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h
+++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h
@@ -2,28 +2,24 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothservicebluedroid_h__
 #define mozilla_dom_bluetooth_bluetoothservicebluedroid_h__
 
-#include <hardware/bluetooth.h>
-
 #include "BluetoothCommon.h"
 #include "BluetoothService.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothServiceBluedroid : public BluetoothService
 {
 public:
-  static const bt_interface_t* GetBluetoothInterface();
-
   BluetoothServiceBluedroid();
   ~BluetoothServiceBluedroid();
 
   virtual nsresult StartInternal();
   virtual nsresult StopInternal();
 
   virtual nsresult GetDefaultAdapterPathInternal(
                                              BluetoothReplyRunnable* aRunnable);
--- a/dom/bluetooth/bluedroid/BluetoothSocket.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothSocket.cpp
@@ -2,22 +2,21 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BluetoothSocket.h"
 
 #include <fcntl.h>
-#include <hardware/bluetooth.h>
-#include <hardware/bt_sock.h>
 #include <sys/socket.h>
 
 #include "base/message_loop.h"
 #include "BluetoothSocketObserver.h"
+#include "BluetoothInterface.h"
 #include "BluetoothUtils.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/RefPtr.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
 
 #define FIRST_SOCKET_INFO_MSG_LENGTH 4
 #define TOTAL_SOCKET_INFO_LENGTH 20
@@ -25,31 +24,30 @@
 using namespace mozilla::ipc;
 USING_BLUETOOTH_NAMESPACE
 
 static const size_t MAX_READ_SIZE = 1 << 16;
 static const uint8_t UUID_OBEX_OBJECT_PUSH[] = {
   0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00,
   0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
 };
-static const btsock_interface_t* sBluetoothSocketInterface = nullptr;
+static BluetoothSocketInterface* sBluetoothSocketInterface;
 
 // helper functions
 static bool
 EnsureBluetoothSocketHalLoad()
 {
   if (sBluetoothSocketInterface) {
     return true;
   }
 
-  const bt_interface_t* btInf = GetBluetoothInterface();
+  BluetoothInterface* btInf = BluetoothInterface::GetInstance();
   NS_ENSURE_TRUE(btInf, false);
 
-  sBluetoothSocketInterface =
-    (btsock_interface_t *) btInf->get_profile_interface(BT_PROFILE_SOCKETS_ID);
+  sBluetoothSocketInterface = btInf->GetBluetoothSocketInterface();
   NS_ENSURE_TRUE(sBluetoothSocketInterface, false);
 
   return true;
 }
 
 static int16_t
 ReadInt16(const uint8_t* aData, size_t* aOffset)
 {
@@ -441,21 +439,21 @@ DroidSocketImpl::Connect()
   MOZ_ASSERT(sBluetoothSocketInterface);
 
   bt_bdaddr_t remoteBdAddress;
   StringToBdAddressType(mDeviceAddress, &remoteBdAddress);
 
   // TODO: uuid as argument
   int fd = -1;
   bt_status_t status =
-    sBluetoothSocketInterface->connect(&remoteBdAddress,
+    sBluetoothSocketInterface->Connect(&remoteBdAddress,
                                        BTSOCK_RFCOMM,
                                        UUID_OBEX_OBJECT_PUSH,
                                        mChannel,
-                                       &fd,
+                                       fd,
                                        (BTSOCK_FLAG_ENCRYPT * mEncrypt) |
                                        (BTSOCK_FLAG_AUTH * mAuth));
   NS_ENSURE_TRUE_VOID(status == BT_STATUS_SUCCESS);
   NS_ENSURE_TRUE_VOID(fd >= 0);
 
   int flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
   NS_ENSURE_TRUE_VOID(flags >= 0);
 
@@ -474,21 +472,21 @@ void
 DroidSocketImpl::Listen()
 {
   MOZ_ASSERT(sBluetoothSocketInterface);
 
   // TODO: uuid and service name as arguments
 
   int fd = -1;
   bt_status_t status =
-    sBluetoothSocketInterface->listen(BTSOCK_RFCOMM,
+    sBluetoothSocketInterface->Listen(BTSOCK_RFCOMM,
                                       "OBEX Object Push",
                                       UUID_OBEX_OBJECT_PUSH,
                                       mChannel,
-                                      &fd,
+                                      fd,
                                       (BTSOCK_FLAG_ENCRYPT * mEncrypt) |
                                       (BTSOCK_FLAG_AUTH * mAuth));
   NS_ENSURE_TRUE_VOID(status == BT_STATUS_SUCCESS);
   NS_ENSURE_TRUE_VOID(fd >= 0);
 
   int flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
   NS_ENSURE_TRUE_VOID(flags >= 0);
 
--- a/dom/bluetooth/bluedroid/BluetoothUtils.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothUtils.cpp
@@ -18,22 +18,16 @@
 #include "nsIScriptContext.h"
 #include "nsISystemMessagesInternal.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsServiceManagerUtils.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
-const bt_interface_t*
-GetBluetoothInterface()
-{
-  return BluetoothServiceBluedroid::GetBluetoothInterface();
-}
-
 void
 StringToBdAddressType(const nsAString& aBdAddress,
                       bt_bdaddr_t *aRetBdAddressType)
 {
   NS_ConvertUTF16toUTF8 bdAddressUTF8(aBdAddress);
   const char* str = bdAddressUTF8.get();
 
   for (int i = 0; i < 6; i++) {
--- a/dom/bluetooth/bluedroid/BluetoothUtils.h
+++ b/dom/bluetooth/bluedroid/BluetoothUtils.h
@@ -13,19 +13,16 @@
 #include "js/TypeDecls.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothNamedValue;
 class BluetoothValue;
 class BluetoothReplyRunnable;
 
-const bt_interface_t*
-GetBluetoothInterface();
-
 void
 StringToBdAddressType(const nsAString& aBdAddress,
                       bt_bdaddr_t *aRetBdAddressType);
 
 void
 BdAddressTypeToString(bt_bdaddr_t* aBdAddressType,
                       nsAString& aRetBdAddress);
 
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -47,17 +47,17 @@
   } while(0)
 
 using namespace mozilla;
 using namespace mozilla::ipc;
 USING_BLUETOOTH_NAMESPACE
 
 namespace {
   StaticRefPtr<BluetoothHfpManager> sBluetoothHfpManager;
-  static const bthf_interface_t* sBluetoothHfpInterface = nullptr;
+  static BluetoothHandsfreeInterface* sBluetoothHfpInterface = nullptr;
 
   bool sInShutdown = false;
 
   // Wait for 2 seconds for Dialer processing event 'BLDN'. '2' seconds is a
   // magic number. The mechanism should be revised once we can get call history.
   static int sWaitingForDialingInterval = 2000; //unit: ms
 
   // Wait 3.7 seconds until Dialer stops playing busy tone. '3' seconds is the
@@ -433,30 +433,30 @@ BluetoothHfpManager::Init()
 
   return true;
 }
 
 // static
 void
 BluetoothHfpManager::InitHfpInterface()
 {
-  const bt_interface_t* btInf = GetBluetoothInterface();
+  BluetoothInterface* btInf = BluetoothInterface::GetInstance();
   NS_ENSURE_TRUE_VOID(btInf);
 
   if (sBluetoothHfpInterface) {
-    sBluetoothHfpInterface->cleanup();
+    sBluetoothHfpInterface->Cleanup();
     sBluetoothHfpInterface = nullptr;
   }
 
-  bthf_interface_t *interface = (bthf_interface_t *)
-    btInf->get_profile_interface(BT_PROFILE_HANDSFREE_ID);
+  BluetoothHandsfreeInterface *interface =
+    btInf->GetBluetoothHandsfreeInterface();
   NS_ENSURE_TRUE_VOID(interface);
 
   NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
-    interface->init(&sBluetoothHfpCallbacks));
+    interface->Init(&sBluetoothHfpCallbacks));
   sBluetoothHfpInterface = interface;
 }
 
 BluetoothHfpManager::~BluetoothHfpManager()
 {
   if (!mListener->Listen(false)) {
     BT_WARNING("Failed to stop listening RIL");
   }
@@ -472,20 +472,18 @@ BluetoothHfpManager::~BluetoothHfpManage
 
   hal::UnregisterBatteryObserver(this);
 }
 
 // static
 void
 BluetoothHfpManager::DeinitHfpInterface()
 {
-  NS_ENSURE_TRUE_VOID(GetBluetoothInterface());
-
   if (sBluetoothHfpInterface) {
-    sBluetoothHfpInterface->cleanup();
+    sBluetoothHfpInterface->Cleanup();
     sBluetoothHfpInterface = nullptr;
   }
 }
 
 //static
 BluetoothHfpManager*
 BluetoothHfpManager::Get()
 {
@@ -678,33 +676,33 @@ BluetoothHfpManager::ProcessAtCnum()
 void
 BluetoothHfpManager::ProcessAtCind()
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   int numActive = GetNumberOfCalls(nsITelephonyService::CALL_STATE_CONNECTED);
   int numHeld = GetNumberOfCalls(nsITelephonyService::CALL_STATE_HELD);
 
-  bt_status_t status = sBluetoothHfpInterface->cind_response(
+  bt_status_t status = sBluetoothHfpInterface->CindResponse(
                           mService,
                           numActive,
                           numHeld,
                           ConvertToBthfCallState(GetCallSetupState()),
                           mSignal,
                           mRoam,
                           mBattChg);
   NS_ENSURE_TRUE_VOID(status == BT_STATUS_SUCCESS);
 }
 
 void
 BluetoothHfpManager::ProcessAtCops()
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
   NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
-    sBluetoothHfpInterface->cops_response(
+    sBluetoothHfpInterface->CopsResponse(
       NS_ConvertUTF16toUTF8(mOperatorName).get()));
 }
 
 void
 BluetoothHfpManager::ProcessAtClcc()
 {
   uint32_t callNumbers = mCurrentCallArray.Length();
   uint32_t i;
@@ -724,17 +722,17 @@ BluetoothHfpManager::ProcessAtClcc()
 
 void
 BluetoothHfpManager::ProcessUnknownAt(char *aAtString)
 {
   BT_LOGR("[%s]", aAtString);
 
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
   NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
-    sBluetoothHfpInterface->at_response(BTHF_AT_RESPONSE_ERROR, 0));
+    sBluetoothHfpInterface->AtResponse(BTHF_AT_RESPONSE_ERROR, 0));
 }
 
 void
 BluetoothHfpManager::ProcessKeyPressed()
 {
   bool hasActiveCall =
     (FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED) > 0);
 
@@ -880,18 +878,18 @@ BluetoothHfpManager::HandleVolumeChanged
     mReceiveVgsFlag = false;
     return;
   }
 
   // Only send volume back when there's a connected headset
   if (IsConnected()) {
     NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
     NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
-      sBluetoothHfpInterface->volume_control(BTHF_VOLUME_TYPE_SPK,
-                                             mCurrentVgs));
+      sBluetoothHfpInterface->VolumeControl(BTHF_VOLUME_TYPE_SPK,
+                                            mCurrentVgs));
   }
 }
 
 void
 BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId)
 {
   nsCOMPtr<nsIMobileConnectionProvider> connection =
     do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
@@ -991,41 +989,41 @@ BluetoothHfpManager::SendCLCC(Call& aCal
                                                BTHF_CALL_STATE_ACTIVE;
   }
 
   if (callState == BTHF_CALL_STATE_INCOMING &&
       FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
     callState = BTHF_CALL_STATE_WAITING;
   }
 
-  bt_status_t status = sBluetoothHfpInterface->clcc_response(
+  bt_status_t status = sBluetoothHfpInterface->ClccResponse(
                           aIndex,
                           aCall.mDirection,
                           callState,
                           BTHF_CALL_TYPE_VOICE,
                           BTHF_CALL_MPTY_TYPE_SINGLE,
                           NS_ConvertUTF16toUTF8(aCall.mNumber).get(),
                           aCall.mType);
   NS_ENSURE_TRUE_VOID(status == BT_STATUS_SUCCESS);
 }
 
 void
 BluetoothHfpManager::SendLine(const char* aMessage)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
   NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
-    sBluetoothHfpInterface->formatted_at_response(aMessage));
+    sBluetoothHfpInterface->FormattedAtResponse(aMessage));
 }
 
 void
 BluetoothHfpManager::SendResponse(bthf_at_response_t aResponseCode)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
   NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
-    sBluetoothHfpInterface->at_response(aResponseCode, 0));
+    sBluetoothHfpInterface->AtResponse(aResponseCode, 0));
 }
 
 void
 BluetoothHfpManager::UpdatePhoneCIND(uint32_t aCallIndex)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   int numActive = GetNumberOfCalls(nsITelephonyService::CALL_STATE_CONNECTED);
@@ -1036,26 +1034,26 @@ BluetoothHfpManager::UpdatePhoneCIND(uin
     NS_ConvertUTF16toUTF8(mCurrentCallArray[aCallIndex].mNumber);
   bthf_call_addrtype_t type = mCurrentCallArray[aCallIndex].mType;
 
   BT_LOGR("[%d] state %d => BTHF: active[%d] held[%d] setupstate[%d]",
           aCallIndex, mCurrentCallArray[aCallIndex].mState,
           numActive, numHeld, callSetupState);
 
   NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
-    sBluetoothHfpInterface->phone_state_change(
+    sBluetoothHfpInterface->PhoneStateChange(
       numActive, numHeld, callSetupState, number.get(), type));
 }
 
 void
 BluetoothHfpManager::UpdateDeviceCIND()
 {
   if (sBluetoothHfpInterface) {
     NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
-      sBluetoothHfpInterface->device_status_notification(
+      sBluetoothHfpInterface->DeviceStatusNotification(
         (bthf_network_state_t) mService,
         (bthf_service_type_t) mRoam,
         mSignal,
         mBattChg));
   }
 }
 
 uint32_t
@@ -1297,31 +1295,31 @@ BluetoothHfpManager::ConnectSco()
 
   NS_ENSURE_TRUE(!sInShutdown, false);
   NS_ENSURE_TRUE(IsConnected() && !IsScoConnected(), false);
   NS_ENSURE_TRUE(sBluetoothHfpInterface, false);
 
   bt_bdaddr_t deviceBdAddress;
   StringToBdAddressType(mDeviceAddress, &deviceBdAddress);
   NS_ENSURE_TRUE(BT_STATUS_SUCCESS ==
-    sBluetoothHfpInterface->connect_audio(&deviceBdAddress), false);
+    sBluetoothHfpInterface->ConnectAudio(&deviceBdAddress), false);
 
   return true;
 }
 
 bool
 BluetoothHfpManager::DisconnectSco()
 {
   NS_ENSURE_TRUE(IsScoConnected(), false);
   NS_ENSURE_TRUE(sBluetoothHfpInterface, false);
 
   bt_bdaddr_t deviceBdAddress;
   StringToBdAddressType(mDeviceAddress, &deviceBdAddress);
   NS_ENSURE_TRUE(BT_STATUS_SUCCESS ==
-    sBluetoothHfpInterface->disconnect_audio(&deviceBdAddress), false);
+    sBluetoothHfpInterface->DisconnectAudio(&deviceBdAddress), false);
 
   return true;
 }
 
 bool
 BluetoothHfpManager::IsScoConnected()
 {
   return (mAudioState == BTHF_AUDIO_STATE_CONNECTED);
@@ -1349,17 +1347,17 @@ BluetoothHfpManager::Connect(const nsASt
     BT_LOGR("sBluetoothHfpInterface is null");
     aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
     return;
   }
 
   bt_bdaddr_t deviceBdAddress;
   StringToBdAddressType(aDeviceAddress, &deviceBdAddress);
 
-  bt_status_t result = sBluetoothHfpInterface->connect(&deviceBdAddress);
+  bt_status_t result = sBluetoothHfpInterface->Connect(&deviceBdAddress);
   if (BT_STATUS_SUCCESS != result) {
     BT_LOGR("Failed to connect: %x", result);
     aController->NotifyCompletion(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
     return;
   }
 
   mDeviceAddress = aDeviceAddress;
   mController = aController;
@@ -1375,17 +1373,17 @@ BluetoothHfpManager::Disconnect(Bluetoot
     BT_LOGR("sBluetoothHfpInterface is null");
     aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
     return;
   }
 
   bt_bdaddr_t deviceBdAddress;
   StringToBdAddressType(mDeviceAddress, &deviceBdAddress);
 
-  bt_status_t result = sBluetoothHfpInterface->disconnect(&deviceBdAddress);
+  bt_status_t result = sBluetoothHfpInterface->Disconnect(&deviceBdAddress);
   if (BT_STATUS_SUCCESS != result) {
     BT_LOGR("Failed to disconnect: %x", result);
     aController->NotifyCompletion(NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
     return;
   }
 
   mController = aController;
 }
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
@@ -2,19 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothhfpmanager_h__
 #define mozilla_dom_bluetooth_bluetoothhfpmanager_h__
 
-#include <hardware/bluetooth.h>
-#include <hardware/bt_hf.h>
-
+#include "BluetoothInterface.h"
 #include "BluetoothCommon.h"
 #include "BluetoothHfpManagerBase.h"
 #include "BluetoothRilListener.h"
 #include "BluetoothSocketObserver.h"
 #include "mozilla/ipc/UnixSocket.h"
 #include "mozilla/Hal.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
--- a/dom/bluetooth/moz.build
+++ b/dom/bluetooth/moz.build
@@ -39,16 +39,17 @@ if CONFIG['MOZ_B2G_BT']:
             ]
             LOCAL_INCLUDES += [
                 'bluez',
             ]
             DEFINES['MOZ_B2G_BT_BLUEZ'] = True
         elif CONFIG['MOZ_B2G_BT_BLUEDROID']:
             SOURCES += [
                 'bluedroid/BluetoothA2dpManager.cpp',
+                'bluedroid/BluetoothInterface.cpp',
                 'bluedroid/BluetoothOppManager.cpp',
                 'bluedroid/BluetoothServiceBluedroid.cpp',
                 'bluedroid/BluetoothSocket.cpp',
                 'bluedroid/BluetoothUtils.cpp',
             ]
             LOCAL_INCLUDES += [
                 'bluedroid',
             ]
--- a/dom/bluetooth2/BluetoothAdapter.cpp
+++ b/dom/bluetooth2/BluetoothAdapter.cpp
@@ -847,16 +847,20 @@ BluetoothAdapter::HandlePropertyChanged(
 }
 
 void
 BluetoothAdapter::DispatchAttributeEvent(const nsTArray<nsString>& aTypes)
 {
   NS_ENSURE_TRUE_VOID(aTypes.Length());
 
   AutoJSAPI jsapi;
+  if (!jsapi.Init(GetOwner())) {
+    BT_WARNING("Failed to initialise AutoJSAPI!");
+    return;
+  }
   JSContext* cx = jsapi.cx();
   JS::Rooted<JS::Value> value(cx);
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
   NS_ENSURE_TRUE_VOID(global);
 
   JS::Rooted<JSObject*> scope(cx, global->GetGlobalJSObject());
   NS_ENSURE_TRUE_VOID(scope);
 
--- a/dom/camera/CameraPreferences.cpp
+++ b/dom/camera/CameraPreferences.cpp
@@ -124,23 +124,19 @@ CameraPreferences::PreferenceChanged(con
       }
       break;
 
     default:
       MOZ_ASSERT_UNREACHABLE("Unhandled preference value type!");
       return;
   }
 
-#ifdef DEBUG
   if (NS_FAILED(rv)) {
-    nsCString msg;
-    msg.AppendPrintf("Failed to update pref '%s' (0x%x)\n", aPref, rv);
-    NS_WARNING(msg.get());
+    DOM_CAMERA_LOGE("Failed to get pref '%s' (0x%x)\n", aPref, rv);
   }
-#endif
 }
 
 /* static */
 bool
 CameraPreferences::Initialize()
 {
   DOM_CAMERA_LOGI("Initializing camera preference callbacks\n");
 
--- a/dom/events/EventListenerService.cpp
+++ b/dom/events/EventListenerService.cpp
@@ -1,17 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "EventListenerService.h"
-#ifdef MOZ_JSDEBUGGER
-#include "jsdIDebuggerService.h"
-#endif
 #include "mozilla/BasicEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/JSEventHandler.h"
 #include "mozilla/Maybe.h"
 #include "nsCOMArray.h"
 #include "nsCxPusher.h"
 #include "nsDOMClassInfoID.h"
@@ -127,45 +124,16 @@ EventListenerInfo::ToSource(nsAString& a
         aResult.Assign(depStr);
       }
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-EventListenerInfo::GetDebugObject(nsISupports** aRetVal)
-{
-  *aRetVal = nullptr;
-
-#ifdef MOZ_JSDEBUGGER
-  nsresult rv = NS_OK;
-  nsCOMPtr<jsdIDebuggerService> jsd =
-    do_GetService("@mozilla.org/js/jsd/debugger-service;1", &rv);
-  NS_ENSURE_SUCCESS(rv, NS_OK);
-
-  bool isOn = false;
-  jsd->GetIsOn(&isOn);
-  NS_ENSURE_TRUE(isOn, NS_OK);
-
-  AutoSafeJSContext cx;
-  Maybe<JSAutoCompartment> ac;
-  JS::Rooted<JS::Value> v(cx);
-  if (GetJSVal(cx, ac, &v)) {
-    nsCOMPtr<jsdIValue> jsdValue;
-    rv = jsd->WrapValue(v, getter_AddRefs(jsdValue));
-    NS_ENSURE_SUCCESS(rv, rv);
-    jsdValue.forget(aRetVal);
-  }
-#endif
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 EventListenerService::GetListenerInfoFor(nsIDOMEventTarget* aEventTarget,
                                          uint32_t* aCount,
                                          nsIEventListenerInfo*** aOutArray)
 {
   NS_ENSURE_ARG_POINTER(aEventTarget);
   *aCount = 0;
   *aOutArray = nullptr;
   nsCOMArray<nsIEventListenerInfo> listenerInfos;
--- a/dom/events/moz.build
+++ b/dom/events/moz.build
@@ -139,11 +139,8 @@ LOCAL_INCLUDES += [
     '/layout/xul',
     '/layout/xul/tree/',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     LOCAL_INCLUDES += [
         '/dom/wifi',
     ]
-
-if CONFIG['MOZ_JSDEBUGGER']:
-    DEFINES['MOZ_JSDEBUGGER'] = True
--- a/dom/events/nsIEventListenerService.idl
+++ b/dom/events/nsIEventListenerService.idl
@@ -7,17 +7,17 @@
 
 interface nsIDOMEventListener;
 interface nsIDOMEventTarget;
 
 /**
  * An instance of this interface describes how an event listener
  * was added to an event target.
  */
-[scriptable, uuid(c4776eb7-05bc-49ce-a0ca-6213a346d53a)]
+[scriptable, uuid(11ba5fd7-8db2-4b1a-9f67-342cfa11afad)]
 interface nsIEventListenerInfo : nsISupports
 {
   /**
    * The type of the event for which the listener was added.
    * Null if the listener is for all the events.
    */
   readonly attribute AString type;
   readonly attribute boolean capturing;
@@ -32,22 +32,16 @@ interface nsIEventListenerInfo : nsISupp
   readonly attribute jsval listenerObject;
 
   /**
    * Tries to serialize event listener to a string.
    * Returns null if serialization isn't possible
    * (for example with C++ listeners).
    */
   AString toSource();
-
-  /**
-   * If jsdIDebuggerService is active and the listener is implemented in JS,
-   * this returns the listener as a jsdIValue. Otherwise null.
-   */
-  nsISupports getDebugObject();
 };
 
 [scriptable, uuid(f6964bfb-dabe-4cab-9733-be0ee2bf8171)]
 interface nsIEventListenerService : nsISupports
 {
   /**
    * Returns an array of nsIEventListenerInfo objects.
    * If aEventTarget doesn't have any listeners, this returns null.
--- a/dom/events/test/test_bug448602.html
+++ b/dom/events/test/test_bug448602.html
@@ -17,22 +17,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 <pre id="test">          
 <script type="application/javascript">
 
 /** Test for Bug 448602 **/
 
 var els, root, l2, l3;
 
 function runTests() {
-/*
-  Disabled due to lack of present support for JSD in JM
-  var jsdIDebuggerService = SpecialPowers.Ci.jsdIDebuggerService;
-  var jsd = SpecialPowers.Components.classes['@mozilla.org/js/jsd/debugger-service;1']
-                      .getService(jsdIDebuggerService);
-*/
   els = SpecialPowers.Cc["@mozilla.org/eventlistenerservice;1"]
                      .getService(SpecialPowers.Ci.nsIEventListenerService);
 
   // Event listener info tests
   root = document.getElementById("testroot");
   var infos = els.getListenerInfoFor(root, {});
   is(infos.length, 0, "Element shouldn't have listeners (1)");
 
@@ -43,28 +37,16 @@ function runTests() {
   is(infos[0].toSource(), 'function onclick(event) {\n' + listenerSource + '\n}',
      "Unexpected serialization (1)");
   is(infos[0].type, "click", "Wrong type (1)");
   is(infos[0].capturing, false, "Wrong phase (1)");
   is(infos[0].allowsUntrusted, true, "Should allow untrusted events (1)");
   is(SpecialPowers.unwrap(infos[0].listenerObject), root.onclick,
      "Should have the right listener object (1)");
 
-/*
-  var jsdOn = jsd.isOn;
-  if (!jsdOn) {
-    is(infos[0].getDebugObject(), null,
-       "If JSD isn't running, getDebugObject() should return null.")
-    jsd.on();
-    ok(jsd.isOn, "JSD should be running.");
-  }
-  var jsdvalue = infos[0].getDebugObject().QueryInterface(SpecialPowers.Ci.jsdIValue);
-  is(jsdvalue.jsType, 3, "Event listener should be a function! (1)");
-*/
-
   root.removeAttribute("onclick");
   root.setAttribute("onclick", "...invalid script...");
   SimpleTest.expectUncaughtException(true);
   infos = els.getListenerInfoFor(root, {});
   SimpleTest.expectUncaughtException(false);
   is(infos.length, 1);
   is(infos[0].listenerObject, null);
 
@@ -79,35 +61,24 @@ function runTests() {
   is(infos.length, 2, "Element should have listeners (2)");
   is(infos[0].toSource(), "(function (e) { alert(e); })",
      "Unexpected serialization (2)");
   is(infos[0].type, "foo", "Wrong type (2)");
   is(infos[0].capturing, true, "Wrong phase (2)");
   is(infos[0].allowsUntrusted, true, "Should allow untrusted events (2)");
   is(SpecialPowers.unwrap(infos[0].listenerObject), l,
      "Should have the right listener object (2)");
-/*
-  jsdvalue = infos[0].getDebugObject().QueryInterface(SpecialPowers.Ci.jsdIValue);
-  is(jsdvalue.jsType, 3, "Event listener should be a function!(2)");
-  is(jsdvalue.getWrappedValue(), l, "Wrong JS value! (1)");
-*/
-
   is(infos[1].toSource(), "(function (e) { alert(e); })",
      "Unexpected serialization (3)");
   is(infos[1].type, "foo", "Wrong type (3)");
   is(infos[1].capturing, false, "Wrong phase (3)");
   is(infos[1].allowsUntrusted, false, "Shouldn't allow untrusted events (1)");
   is(SpecialPowers.unwrap(infos[1].listenerObject), l,
      "Should have the right listener object (3)");
 
-/*
-  jsdvalue2 = infos[1].getDebugObject().QueryInterface(SpecialPowers.Ci.jsdIValue);
-  is(jsdvalue2.jsType, 3, "Event listener should be a function! (3)");
-  is(jsdvalue2.getWrappedValue(), l, "Wrong JS value! (2)");
-*/
   root.removeEventListener("foo", l, true);
   root.removeEventListener("foo", l, false);
   infos = els.getListenerInfoFor(root, {});
   is(infos.length, 0, "Element shouldn't have listeners (3)");
 
   root.onclick = l;
   infos = els.getListenerInfoFor(root, {});
   is(infos.length, 1, "Element should have listeners (3)");
@@ -137,22 +108,16 @@ function runTests() {
       hasDocumentInChain = true;
     } else if (SpecialPowers.compare(chain[i], window)) {
       hasWindowInChain = true;
     }
   }
 
   ok(hasDocumentInChain, "Should have document in event target chain!");
   ok(hasWindowInChain, "Should have window in event target chain!");
-/*
-  if (!jsdOn) {
-    jsd.off();
-    ok(!jsd.isOn, "JSD shouldn't be running anymore.");
-  }
-*/	
 
   try {
     els.getListenerInfoFor(null, {});
     ok(false, "Should have thrown an exception.");
   } catch (ex) {
     ok(true, "We should be still running.");
   }
   setTimeout(testAllListener, 0);
--- a/dom/media/tests/mochitest/blacksilence.js
+++ b/dom/media/tests/mochitest/blacksilence.js
@@ -19,29 +19,41 @@
       if (audioData[i] !== 128) {
         silence = false;
       }
     }
     return silence;
   }
 
   function periodicCheck(type, checkFunc, successMessage, done) {
-    var interval = setInterval(function periodic() {
+    var num = 0;
+    var timeout;
+    function periodic() {
       if (checkFunc()) {
         ok(true, type + ' is ' + successMessage);
-        clearInterval(interval);
-        interval = null;
         done();
+      } else {
+        setupNext();
       }
-    }, 200);
+    }
+    function setupNext() {
+      // exponential backoff on the timer
+      // on a very slow system (like the b2g emulator) a long timeout is
+      // necessary, but we want to run fast if we can
+      timeout = setTimeout(periodic, 200 << num);
+      num++;
+    }
+
+    setupNext();
+
     return function cancel() {
-      if (interval) {
+      if (timeout) {
         ok(false, type + ' (' + successMessage + ')' +
            ' failed after waiting full duration');
-        clearInterval(interval);
+        clearTimeout(timeout);
         done();
       }
     };
   }
 
   function checkAudio(constraintApplied, stream, done) {
     var context = new AudioContext();
     var source = context.createMediaStreamSource(stream);
@@ -54,26 +66,32 @@
       info('got some audio samples: ' + sampleCount);
       var bucket = new ArrayBuffer(sampleCount);
       var view = new Uint8Array(bucket);
       analyser.getByteTimeDomainData(view);
 
       var silent = check(constraintApplied, isSilence(view), 'be silence for audio');
       return sampleCount > 0 && silent;
     }
+    function disconnect() {
+      source.disconnect();
+      analyser.disconnect();
+      done();
+    }
     return periodicCheck('audio', testAudio,
-                         (constraintApplied ? '' : 'not ') + 'silent', done);
+                         (constraintApplied ? '' : 'not ') + 'silent', disconnect);
   }
 
   function mkElement(type) {
-    var display = document.getElementById('display');
+    // this makes an unattached element
+    // it's not rendered to save the cycles that costs on b2g emulator
+    // and it gets droped (and GC'd) when the test is done
     var e = document.createElement(type);
     e.width = 32;
     e.height = 24;
-    display.appendChild(e);
     return e;
   }
 
   function checkVideo(constraintApplied, stream, done) {
     var video = mkElement('video');
     video.mozSrcObject = stream;
 
     var ready = false;
--- a/dom/media/tests/mochitest/templates.js
+++ b/dom/media/tests/mochitest/templates.js
@@ -183,16 +183,60 @@ var commandsPeerConnection = [
           send_message({"answer": test.pcRemote._last_answer,
                         "media_constraints": test.pcRemote.constraints});
         }
         test.next();
       });
     }
   ],
   [
+    'PC_REMOTE_CHECK_FOR_DUPLICATED_PORTS_IN_SDP',
+    function (test) {
+      var re = /a=candidate.* (UDP|TCP) [\d]+ ([\d\.]+) ([\d]+) typ host/g;
+
+      function _sdpCandidatesIntoArray(sdp) {
+        var regexArray = [];
+        var resultArray = [];
+        while ((regexArray = re.exec(sdp)) !== null) {
+          info("regexArray: " + regexArray);
+          if ((regexArray[1] === "TCP") && (regexArray[3] === "9")) {
+            // As both sides can advertise TCP active connection on port 9 lets
+            // ignore them all together
+            info("Ignoring TCP candidate on port 9");
+            continue;
+          }
+          const triple = regexArray[1] + ":" + regexArray[2] + ":" + regexArray[3];
+          info("triple: " + triple);
+          if (resultArray.indexOf(triple) !== -1) {
+            dump("SDP: " + sdp.replace(/[\r]/g, '') + "\n");
+            ok(false, "This Transport:IP:Port " + triple + " appears twice in the SDP above!");
+          }
+          resultArray.push(triple);
+        }
+        return resultArray;
+      }
+
+      const offerTriples = _sdpCandidatesIntoArray(test._local_offer.sdp);
+      info("Offer ICE host candidates: " + JSON.stringify(offerTriples));
+
+      const answerTriples = _sdpCandidatesIntoArray(test.pcRemote._last_answer.sdp);
+      info("Answer ICE host candidates: " + JSON.stringify(answerTriples));
+
+      for (var i=0; i< offerTriples.length; i++) {
+        if (answerTriples.indexOf(offerTriples[i]) !== -1) {
+          dump("SDP offer: " + test._local_offer.sdp.replace(/[\r]/g, '') + "\n");
+          dump("SDP answer: " + test.pcRemote._last_answer.sdp.replace(/[\r]/g, '') + "\n");
+          ok(false, "This IP:Port " + offerTriples[i] + " appears in SDP offer and answer!");
+        }
+      }
+
+      test.next();
+    }
+  ],
+  [
     'PC_REMOTE_SET_LOCAL_DESCRIPTION',
     function (test) {
       test.setLocalDescription(test.pcRemote, test.pcRemote._last_answer, STABLE, function () {
         is(test.pcRemote.signalingState, STABLE,
            "signalingState after remote setLocalDescription is 'stable'");
         test.next();
       });
     }
--- a/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html
@@ -31,18 +31,18 @@ function theTest() {
       function checkDone() {
         if (oneDone) {
           done();
         }
         oneDone = true;
       }
       var cancelAudioCheck = audioIsSilence(withConstraint, stream, checkDone);
       var cancelVideoCheck = videoIsBlack(withConstraint, stream, checkDone);
-      setTimeout(cancelAudioCheck, 20000);
-      setTimeout(cancelVideoCheck, 20000);
+      setTimeout(cancelAudioCheck, 3*60*1000);
+      setTimeout(cancelVideoCheck, 3*60*1000);
     }, function(e) {
       ok(false, 'gUM error: ' + e);
     });
   };
 
   // without constraint
   testPeerIdentityConstraint(false, function() {
     // with the constraint
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -1952,20 +1952,20 @@ function WifiWorker() {
       if (hasValidProperty("pin")) {
         net.pin = quote(net.pin);
       }
 
       if (hasValidProperty("phase1"))
         net.phase1 = quote(net.phase1);
 
       if (hasValidProperty("phase2")) {
-        if (net.eap === "PEAP") {
+        if (net.phase2 === "TLS") {
+          net.phase2 = quote("autheap=" + net.phase2);
+        } else { // PAP, MSCHAPV2, etc.
           net.phase2 = quote("auth=" + net.phase2);
-        } else {  // TLS, TTLS
-          net.phase2 = quote("autheap=" + net.phase2);
         }
       }
 
       if (hasValidProperty("serverCertificate"))
         net.ca_cert = quote("keystore://WIFI_SERVERCERT_" + net.serverCertificate);
 
       if (hasValidProperty("subjectMatch"))
         net.subject_match = quote(net.subjectMatch);
--- a/dom/workers/MessagePort.cpp
+++ b/dom/workers/MessagePort.cpp
@@ -2,26 +2,28 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MessagePort.h"
 
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/dom/MessagePortBinding.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "nsIDOMEvent.h"
 
 #include "SharedWorker.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 
 using mozilla::dom::EventHandlerNonNull;
 using mozilla::dom::MessagePortBase;
 using mozilla::dom::Optional;
 using mozilla::dom::Sequence;
+using mozilla::dom::AutoNoJSAPI;
 using namespace mozilla;
 
 USING_WORKERS_NAMESPACE
 
 namespace {
 
 class DelayedEventRunnable MOZ_FINAL : public WorkerRunnable
 {
@@ -37,16 +39,38 @@ public:
   {
     AssertIsOnMainThread();
     MOZ_ASSERT(aMessagePort);
     MOZ_ASSERT(aEvents.Length());
 
     mEvents.SwapElements(aEvents);
   }
 
+  bool PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
+  {
+    if (mBehavior == WorkerThreadModifyBusyCount) {
+      return aWorkerPrivate->ModifyBusyCount(aCx, true);
+    }
+
+    return true;
+  }
+
+  void PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
+                    bool aDispatchResult)
+  {
+    if (!aDispatchResult) {
+      if (mBehavior == WorkerThreadModifyBusyCount) {
+        aWorkerPrivate->ModifyBusyCount(aCx, false);
+      }
+      if (aCx) {
+        JS_ReportPendingException(aCx);
+      }
+    }
+  }
+
   bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
 };
 
 } // anonymous namespace
 
 MessagePort::MessagePort(nsPIDOMWindow* aWindow, SharedWorker* aSharedWorker,
                          uint64_t aSerial)
@@ -276,15 +300,17 @@ MessagePort::PreHandleEvent(EventChainPr
 
 bool
 DelayedEventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
 {
   MOZ_ASSERT(mMessagePort);
   mMessagePort->AssertCorrectThread();
   MOZ_ASSERT(mEvents.Length());
 
+  AutoNoJSAPI nojsapi;
+
   bool ignored;
   for (uint32_t i = 0; i < mEvents.Length(); i++) {
     mMessagePort->DispatchEvent(mEvents[i], &ignored);
   }
 
   return true;
 }
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -6,30 +6,252 @@
 
 #include "nsIDocument.h"
 #include "nsPIDOMWindow.h"
 
 #include "jsapi.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/DOMError.h"
+
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
 #include "nsNetUtil.h"
+#include "nsProxyRelease.h"
 #include "nsTArray.h"
 
 #include "RuntimeService.h"
 #include "ServiceWorker.h"
 #include "WorkerInlines.h"
+#include "WorkerPrivate.h"
+#include "WorkerRunnable.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 BEGIN_WORKERS_NAMESPACE
 
+NS_IMPL_ISUPPORTS0(ServiceWorkerRegistration)
+
+UpdatePromise::UpdatePromise()
+  : mState(Pending)
+{
+  MOZ_COUNT_CTOR(UpdatePromise);
+}
+
+UpdatePromise::~UpdatePromise()
+{
+  MOZ_COUNT_DTOR(UpdatePromise);
+}
+
+void
+UpdatePromise::AddPromise(Promise* aPromise)
+{
+  MOZ_ASSERT(mState == Pending);
+  mPromises.AppendElement(aPromise);
+}
+
+void
+UpdatePromise::ResolveAllPromises(const nsACString& aScriptSpec, const nsACString& aScope)
+{
+  AssertIsOnMainThread();
+  MOZ_ASSERT(mState == Pending);
+  mState = Resolved;
+  RuntimeService* rs = RuntimeService::GetOrCreateService();
+  MOZ_ASSERT(rs);
+
+  nsTArray<nsTWeakRef<Promise>> array;
+  array.SwapElements(mPromises);
+  for (uint32_t i = 0; i < array.Length(); ++i) {
+    nsTWeakRef<Promise>& pendingPromise = array.ElementAt(i);
+    if (pendingPromise) {
+      nsCOMPtr<nsIGlobalObject> go =
+        do_QueryInterface(pendingPromise->GetParentObject());
+      MOZ_ASSERT(go);
+
+      AutoSafeJSContext cx;
+      JS::Rooted<JSObject*> global(cx, go->GetGlobalJSObject());
+      JSAutoCompartment ac(cx, global);
+
+      GlobalObject domGlobal(cx, global);
+
+      nsRefPtr<ServiceWorker> serviceWorker;
+      nsresult rv = rs->CreateServiceWorker(domGlobal,
+                                            NS_ConvertUTF8toUTF16(aScriptSpec),
+                                            aScope,
+                                            getter_AddRefs(serviceWorker));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        pendingPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+        continue;
+      }
+
+      pendingPromise->MaybeResolve(serviceWorker);
+    }
+  }
+}
+
+void
+UpdatePromise::RejectAllPromises(nsresult aRv)
+{
+  AssertIsOnMainThread();
+  MOZ_ASSERT(mState == Pending);
+  mState = Rejected;
+
+  nsTArray<nsTWeakRef<Promise>> array;
+  array.SwapElements(mPromises);
+  for (uint32_t i = 0; i < array.Length(); ++i) {
+    nsTWeakRef<Promise>& pendingPromise = array.ElementAt(i);
+    if (pendingPromise) {
+      // Since ServiceWorkerContainer is only exposed to windows we can be
+      // certain about this cast.
+      nsCOMPtr<nsPIDOMWindow> window =
+        do_QueryInterface(pendingPromise->GetParentObject());
+      MOZ_ASSERT(window);
+      nsRefPtr<DOMError> domError = new DOMError(window, aRv);
+      pendingPromise->MaybeRejectBrokenly(domError);
+    }
+  }
+}
+
+class FinishFetchOnMainThreadRunnable : public nsRunnable
+{
+  nsMainThreadPtrHandle<ServiceWorkerUpdateInstance> mUpdateInstance;
+public:
+  FinishFetchOnMainThreadRunnable
+    (const nsMainThreadPtrHandle<ServiceWorkerUpdateInstance>& aUpdateInstance)
+    : mUpdateInstance(aUpdateInstance)
+  { }
+
+  NS_IMETHOD
+  Run() MOZ_OVERRIDE;
+};
+
+class FinishSuccessfulFetchWorkerRunnable : public WorkerRunnable
+{
+  nsMainThreadPtrHandle<ServiceWorkerUpdateInstance> mUpdateInstance;
+public:
+  FinishSuccessfulFetchWorkerRunnable(WorkerPrivate* aWorkerPrivate,
+                                      const nsMainThreadPtrHandle<ServiceWorkerUpdateInstance>& aUpdateInstance)
+    : WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
+      mUpdateInstance(aUpdateInstance)
+  {
+    AssertIsOnMainThread();
+  }
+
+  bool
+  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
+  {
+    aWorkerPrivate->AssertIsOnWorkerThread();
+    if (!aWorkerPrivate->WorkerScriptExecutedSuccessfully()) {
+      return true;
+    }
+
+    nsRefPtr<FinishFetchOnMainThreadRunnable> r =
+      new FinishFetchOnMainThreadRunnable(mUpdateInstance);
+    NS_DispatchToMainThread(r);
+    return true;
+  }
+};
+
+// Allows newer calls to Update() to 'abort' older calls.
+// Each call to Update() creates the instance which handles creating the
+// worker and queues up a runnable to resolve the update promise once the
+// worker has successfully been parsed.
+class ServiceWorkerUpdateInstance MOZ_FINAL : public nsISupports
+{
+  // Owner of this instance.
+  ServiceWorkerRegistration* mRegistration;
+  nsCString mScriptSpec;
+  nsCOMPtr<nsPIDOMWindow> mWindow;
+
+  bool mAborted;
+public:
+  NS_DECL_ISUPPORTS
+
+  ServiceWorkerUpdateInstance(ServiceWorkerRegistration *aRegistration,
+                              nsPIDOMWindow* aWindow)
+    : mRegistration(aRegistration),
+      // Capture the current script spec in case register() gets called.
+      mScriptSpec(aRegistration->mScriptSpec),
+      mWindow(aWindow),
+      mAborted(false)
+  {
+    AssertIsOnMainThread();
+  }
+
+  void
+  Abort()
+  {
+    MOZ_ASSERT(!mAborted);
+    mAborted = true;
+  }
+
+  void
+  Update()
+  {
+    AssertIsOnMainThread();
+    nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+    MOZ_ASSERT(swm);
+
+    nsRefPtr<ServiceWorker> serviceWorker;
+    nsresult rv = swm->CreateServiceWorkerForWindow(mWindow,
+                                                    mScriptSpec,
+                                                    mRegistration->mScope,
+                                                    getter_AddRefs(serviceWorker));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      swm->RejectUpdatePromiseObservers(mRegistration, rv);
+      return;
+    }
+
+    nsMainThreadPtrHandle<ServiceWorkerUpdateInstance> handle =
+      new nsMainThreadPtrHolder<ServiceWorkerUpdateInstance>(this);
+    // FIXME(nsm): Deal with error case (worker failed to download, redirect,
+    // parse) in error handler patch.
+    nsRefPtr<FinishSuccessfulFetchWorkerRunnable> r =
+      new FinishSuccessfulFetchWorkerRunnable(serviceWorker->GetWorkerPrivate(), handle);
+
+    AutoSafeJSContext cx;
+    if (!r->Dispatch(cx)) {
+      swm->RejectUpdatePromiseObservers(mRegistration, NS_ERROR_FAILURE);
+    }
+  }
+
+  void
+  FetchDone()
+  {
+    AssertIsOnMainThread();
+    if (mAborted) {
+      return;
+    }
+
+    nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+    MOZ_ASSERT(swm);
+    swm->FinishFetch(mRegistration, mWindow);
+  }
+};
+
+NS_IMPL_ISUPPORTS0(ServiceWorkerUpdateInstance)
+
+NS_IMETHODIMP
+FinishFetchOnMainThreadRunnable::Run()
+{
+  AssertIsOnMainThread();
+  mUpdateInstance->FetchDone();
+  return NS_OK;
+}
+
+ServiceWorkerRegistration::ServiceWorkerRegistration(const nsACString& aScope)
+  : mScope(aScope),
+    mPendingUninstall(false)
+{ }
+
+ServiceWorkerRegistration::~ServiceWorkerRegistration()
+{ }
+
 //////////////////////////
 // ServiceWorkerManager //
 //////////////////////////
 
 NS_IMPL_ADDREF(ServiceWorkerManager)
 NS_IMPL_RELEASE(ServiceWorkerManager)
 
 NS_INTERFACE_MAP_BEGIN(ServiceWorkerManager)
@@ -84,46 +306,45 @@ public:
     if (NS_WARN_IF(NS_FAILED(rv))) {
       mPromise->MaybeReject(rv);
       return NS_OK;
     }
 
     nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
     ServiceWorkerManager::ServiceWorkerDomainInfo* domainInfo =
       swm->mDomainMap.Get(domain);
-    // FIXME(nsm): Refactor this pattern.
+    // XXXnsm: This pattern can be refactored if we end up using it
+    // often enough.
     if (!swm->mDomainMap.Get(domain, &domainInfo)) {
       domainInfo = new ServiceWorkerManager::ServiceWorkerDomainInfo;
       swm->mDomainMap.Put(domain, domainInfo);
     }
 
-    nsRefPtr<ServiceWorkerRegistration> registration = domainInfo->GetRegistration(mScope);
+    nsRefPtr<ServiceWorkerRegistration> registration =
+      domainInfo->GetRegistration(mScope);
 
     nsCString spec;
     rv = mScriptURI->GetSpec(spec);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       mPromise->MaybeReject(rv);
       return NS_OK;
     }
 
     if (registration) {
       registration->mPendingUninstall = false;
       if (spec.Equals(registration->mScriptSpec)) {
-        // FIXME(nsm): Force update on Shift+Reload. Algorithm not specified for
-        // that yet.
-
         // There is an existing update in progress. Resolve with whatever it
         // results in.
         if (registration->HasUpdatePromise()) {
           registration->AddUpdatePromiseObserver(mPromise);
           return NS_OK;
         }
 
-        // There is no update in progress and since SW updating is upto the UA, we
-        // will not update right now. Simply resolve with whatever worker we
+        // There is no update in progress and since SW updating is upto the UA,
+        // we will not update right now. Simply resolve with whatever worker we
         // have.
         ServiceWorkerInfo info = registration->Newest();
         if (info.IsValid()) {
           nsRefPtr<ServiceWorker> serviceWorker;
           nsresult rv =
             swm->CreateServiceWorkerForWindow(mWindow,
                                               info.GetScriptSpec(),
                                               registration->mScope,
@@ -138,28 +359,35 @@ public:
         }
       }
     } else {
       registration = domainInfo->CreateNewRegistration(mScope);
     }
 
     registration->mScriptSpec = spec;
 
-    // FIXME(nsm): Call Update. Same bug, different patch.
-    // For now if the registration reaches this spot, the promise remains
-    // unresolved.
-    return NS_OK;
+    rv = swm->Update(registration, mWindow);
+    MOZ_ASSERT(registration->HasUpdatePromise());
+
+    // We append this register() call's promise after calling Update() because
+    // we don't want this one to be aborted when the others (existing updates
+    // for the same registration) are aborted. Update() sets a new
+    // UpdatePromise on the registration.
+    registration->mUpdatePromise->AddPromise(mPromise);
+
+    return rv;
   }
 };
 
 // If we return an error code here, the ServiceWorkerContainer will
 // automatically reject the Promise.
 NS_IMETHODIMP
 ServiceWorkerManager::Register(nsIDOMWindow* aWindow, const nsAString& aScope,
-                               const nsAString& aScriptURL, nsISupports** aPromise)
+                               const nsAString& aScriptURL,
+                               nsISupports** aPromise)
 {
   AssertIsOnMainThread();
   MOZ_ASSERT(aWindow);
 
   // XXXnsm Don't allow chrome callers for now, we don't support chrome
   // ServiceWorkers.
   MOZ_ASSERT(!nsContentUtils::IsCallerChrome());
 
@@ -201,20 +429,19 @@ ServiceWorkerManager::Register(nsIDOMWin
   }
 
   nsCOMPtr<nsIURI> scriptURI;
   rv = NS_NewURI(getter_AddRefs(scriptURI), aScriptURL, nullptr, documentURI);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  // https://github.com/slightlyoff/ServiceWorker/issues/262
-  // allowIfInheritsPrincipal: allow data: URLs for now.
+  // Data URLs are not allowed.
   rv = documentPrincipal->CheckMayLoad(scriptURI, true /* report */,
-                                       true /* allowIfInheritsPrincipal */);
+                                       false /* allowIfInheritsPrincipal */);
   if (NS_FAILED(rv)) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsCOMPtr<nsIURI> scopeURI;
   rv = NS_NewURI(getter_AddRefs(scopeURI), aScope, nullptr, documentURI);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return NS_ERROR_DOM_SECURITY_ERR;
@@ -233,21 +460,61 @@ ServiceWorkerManager::Register(nsIDOMWin
   }
 
   nsRefPtr<nsIRunnable> registerRunnable =
     new RegisterRunnable(window, cleanedScope, scriptURI, promise);
   promise.forget(aPromise);
   return NS_DispatchToCurrentThread(registerRunnable);
 }
 
+void
+ServiceWorkerManager::RejectUpdatePromiseObservers(ServiceWorkerRegistration* aRegistration,
+                                                   nsresult aRv)
+{
+  AssertIsOnMainThread();
+  MOZ_ASSERT(aRegistration->HasUpdatePromise());
+  aRegistration->mUpdatePromise->RejectAllPromises(aRv);
+  aRegistration->mUpdatePromise = nullptr;
+}
+
+/*
+ * Update() does not return the Promise that the spec says it should. Callers
+ * may access the registration's (new) Promise after calling this method.
+ */
 NS_IMETHODIMP
 ServiceWorkerManager::Update(ServiceWorkerRegistration* aRegistration,
                              nsPIDOMWindow* aWindow)
 {
-  // FIXME(nsm): Same bug, different patch.
+  if (aRegistration->HasUpdatePromise()) {
+    NS_WARNING("Already had a UpdatePromise. Aborting that one!");
+    RejectUpdatePromiseObservers(aRegistration, NS_ERROR_DOM_ABORT_ERR);
+    MOZ_ASSERT(aRegistration->mUpdateInstance);
+    aRegistration->mUpdateInstance->Abort();
+    aRegistration->mUpdateInstance = nullptr;
+  }
+
+  if (aRegistration->mInstallingWorker.IsValid()) {
+    // FIXME(nsm): Terminate the worker. We still haven't figured out worker
+    // instance ownership when not associated with a window, so let's wait on
+    // this.
+    // FIXME(nsm): We should be setting the state on the actual worker
+    // instance.
+    // FIXME(nsm): Fire "statechange" on installing worker instance.
+    aRegistration->mInstallingWorker.Invalidate();
+  }
+
+  aRegistration->mUpdatePromise = new UpdatePromise();
+  // FIXME(nsm): Bug 931249. If we don't need to fetch & install, resolve
+  // promise and skip this.
+  // FIXME(nsm): Bug 931249. Force cache update if > 1 day.
+
+  aRegistration->mUpdateInstance =
+    new ServiceWorkerUpdateInstance(aRegistration, aWindow);
+  aRegistration->mUpdateInstance->Update();
+
   return NS_OK;
 }
 
 // If we return an error, ServiceWorkerContainer will reject the Promise.
 NS_IMETHODIMP
 ServiceWorkerManager::Unregister(nsIDOMWindow* aWindow, const nsAString& aScope,
                                  nsISupports** aPromise)
 {
@@ -261,21 +528,79 @@ ServiceWorkerManager::Unregister(nsIDOMW
 
   return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
 }
 
 /* static */
 already_AddRefed<ServiceWorkerManager>
 ServiceWorkerManager::GetInstance()
 {
-  nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
+  nsCOMPtr<nsIServiceWorkerManager> swm =
+    do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
   nsRefPtr<ServiceWorkerManager> concrete = do_QueryObject(swm);
   return concrete.forget();
 }
 
+void
+ServiceWorkerManager::ResolveRegisterPromises(ServiceWorkerRegistration* aRegistration,
+                                              const nsACString& aWorkerScriptSpec)
+{
+  AssertIsOnMainThread();
+  MOZ_ASSERT(aRegistration->HasUpdatePromise());
+  if (aRegistration->mUpdatePromise->IsRejected()) {
+    aRegistration->mUpdatePromise = nullptr;
+    return;
+  }
+
+  aRegistration->mUpdatePromise->ResolveAllPromises(aWorkerScriptSpec,
+                                                    aRegistration->mScope);
+  aRegistration->mUpdatePromise = nullptr;
+}
+
+// Must NS_Free() aString
+void
+ServiceWorkerManager::FinishFetch(ServiceWorkerRegistration* aRegistration,
+                                  nsPIDOMWindow* aWindow)
+{
+  AssertIsOnMainThread();
+
+  MOZ_ASSERT(aRegistration->HasUpdatePromise());
+  MOZ_ASSERT(aRegistration->mUpdateInstance);
+  aRegistration->mUpdateInstance = nullptr;
+  if (aRegistration->mUpdatePromise->IsRejected()) {
+    aRegistration->mUpdatePromise = nullptr;
+    return;
+  }
+
+  // We have skipped Steps 3-8.3 of the Update algorithm here!
+
+  nsRefPtr<ServiceWorker> worker;
+  nsresult rv = CreateServiceWorkerForWindow(aWindow,
+                                             aRegistration->mScriptSpec,
+                                             aRegistration->mScope,
+                                             getter_AddRefs(worker));
+
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    RejectUpdatePromiseObservers(aRegistration, rv);
+    return;
+  }
+
+  ResolveRegisterPromises(aRegistration, aRegistration->mScriptSpec);
+
+  ServiceWorkerInfo info(aRegistration->mScriptSpec);
+  Install(aRegistration, info);
+}
+
+void
+ServiceWorkerManager::Install(ServiceWorkerRegistration* aRegistration,
+                              ServiceWorkerInfo aServiceWorkerInfo)
+{
+  // FIXME(nsm): Same bug, different patch.
+}
+
 NS_IMETHODIMP
 ServiceWorkerManager::CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
                                                    const nsACString& aScriptSpec,
                                                    const nsACString& aScope,
                                                    ServiceWorker** aServiceWorker)
 {
   AssertIsOnMainThread();
   MOZ_ASSERT(aWindow);
--- a/dom/workers/ServiceWorkerManager.h
+++ b/dom/workers/ServiceWorkerManager.h
@@ -18,89 +18,135 @@
 #include "nsTArrayForwardDeclare.h"
 #include "nsTWeakRef.h"
 
 namespace mozilla {
 namespace dom {
 namespace workers {
 
 class ServiceWorker;
+class ServiceWorkerUpdateInstance;
+
+/**
+ * UpdatePromise is a utility class that sort of imitates Promise, but not
+ * completely. Using DOM Promise from C++ is a pain when we know the precise types
+ * we're dealing with since it involves dealing with JSAPI. In this case we
+ * also don't (yet) need the 'thenables added after resolution should trigger
+ * immediately' support and other things like that. All we want is something
+ * that works reasonably Promise like and can resolve real DOM Promises added
+ * pre-emptively.
+ */
+class UpdatePromise MOZ_FINAL
+{
+public:
+  UpdatePromise();
+  ~UpdatePromise();
+
+  void AddPromise(Promise* aPromise);
+  void ResolveAllPromises(const nsACString& aScriptSpec, const nsACString& aScope);
+  void RejectAllPromises(nsresult aRv);
+
+  bool
+  IsRejected() const
+  {
+    return mState == Rejected;
+  }
+
+private:
+  enum {
+    Pending,
+    Resolved,
+    Rejected
+  } mState;
+
+  // XXXnsm: Right now we don't need to support AddPromise() after
+  // already being resolved (i.e. true Promise-like behaviour).
+  nsTArray<nsTWeakRef<Promise>> mPromises;
+};
 
 /*
  * Wherever the spec treats a worker instance and a description of said worker
  * as the same thing; i.e. "Resolve foo with
  * _GetNewestWorker(serviceWorkerRegistration)", we represent the description
  * by this class and spawn a ServiceWorker in the right global when required.
  */
 class ServiceWorkerInfo
 {
-  const nsCString mScriptSpec;
+  nsCString mScriptSpec;
 public:
 
   bool
   IsValid() const
   {
     return !mScriptSpec.IsVoid();
   }
 
+  void
+  Invalidate()
+  {
+    mScriptSpec.SetIsVoid(true);
+  }
+
   const nsCString&
   GetScriptSpec() const
   {
     MOZ_ASSERT(IsValid());
     return mScriptSpec;
   }
 
   ServiceWorkerInfo()
-  { }
+  {
+    Invalidate();
+  }
 
   explicit ServiceWorkerInfo(const nsACString& aScriptSpec)
     : mScriptSpec(aScriptSpec)
   { }
 };
 
-class ServiceWorkerRegistration
+// Needs to inherit from nsISupports because NS_ProxyRelease() does not support
+// non-ISupports classes.
+class ServiceWorkerRegistration MOZ_FINAL : public nsISupports
 {
-private:
-  ~ServiceWorkerRegistration() {}
+  virtual ~ServiceWorkerRegistration();
+
 public:
-  NS_INLINE_DECL_REFCOUNTING(ServiceWorkerRegistration)
+  NS_DECL_ISUPPORTS
 
   nsCString mScope;
   // The scriptURL for the registration. This may be completely different from
   // the URLs of the following three workers.
   nsCString mScriptSpec;
 
   ServiceWorkerInfo mCurrentWorker;
   ServiceWorkerInfo mWaitingWorker;
   ServiceWorkerInfo mInstallingWorker;
 
-  bool mHasUpdatePromise;
+  nsAutoPtr<UpdatePromise> mUpdatePromise;
+  nsRefPtr<ServiceWorkerUpdateInstance> mUpdateInstance;
 
   void
   AddUpdatePromiseObserver(Promise* aPromise)
   {
-    // FIXME(nsm): Same bug, different patch.
+    MOZ_ASSERT(HasUpdatePromise());
+    mUpdatePromise->AddPromise(aPromise);
   }
 
   bool
   HasUpdatePromise()
   {
-    return mHasUpdatePromise;
+    return mUpdatePromise;
   }
 
   // When unregister() is called on a registration, it is not immediately
   // removed since documents may be controlled. It is marked as
   // pendingUninstall and when all controlling documents go away, removed.
   bool mPendingUninstall;
 
-  explicit ServiceWorkerRegistration(const nsACString& aScope)
-    : mScope(aScope),
-      mHasUpdatePromise(false),
-      mPendingUninstall(false)
-  { }
+  explicit ServiceWorkerRegistration(const nsACString& aScope);
 
   ServiceWorkerInfo
   Newest() const
   {
     if (mInstallingWorker.IsValid()) {
       return mInstallingWorker;
     } else if (mWaitingWorker.IsValid()) {
       return mWaitingWorker;
@@ -121,16 +167,18 @@ public:
 /*
  * The ServiceWorkerManager is a per-process global that deals with the
  * installation, querying and event dispatch of ServiceWorkers for all the
  * origins in the process.
  */
 class ServiceWorkerManager MOZ_FINAL : public nsIServiceWorkerManager
 {
   friend class RegisterRunnable;
+  friend class CallInstallRunnable;
+  friend class ServiceWorkerUpdateInstance;
 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSISERVICEWORKERMANAGER
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_SERVICEWORKERMANAGER_IMPL_IID)
 
   static ServiceWorkerManager* FactoryCreate()
   {
@@ -169,33 +217,42 @@ public:
       // mServiceWorkerRegistrations.
       mServiceWorkerRegistrations.Put(aScope, registration);
       return registration;
     }
   };
 
   nsClassHashtable<nsCStringHashKey, ServiceWorkerDomainInfo> mDomainMap;
 
-  // FIXME(nsm): What do we do if a page calls for register("/foo_worker.js", { scope: "/*"
-  // }) and then another page calls register("/bar_worker.js", { scope: "/*" })
-  // while the install is in progress. The async install steps for register
-  // bar_worker.js could finish before foo_worker.js, but bar_worker still has
-  // to be the winning controller.
-  // FIXME(nsm): Move this into per domain?
+  void
+  ResolveRegisterPromises(ServiceWorkerRegistration* aRegistration,
+                          const nsACString& aWorkerScriptSpec);
+
+  void
+  RejectUpdatePromiseObservers(ServiceWorkerRegistration* aRegistration,
+                               nsresult aResult);
+
+  void
+  FinishFetch(ServiceWorkerRegistration* aRegistration,
+              nsPIDOMWindow* aWindow);
 
   static already_AddRefed<ServiceWorkerManager>
   GetInstance();
 
 private:
   ServiceWorkerManager();
   ~ServiceWorkerManager();
 
   NS_IMETHOD
   Update(ServiceWorkerRegistration* aRegistration, nsPIDOMWindow* aWindow);
 
+  void
+  Install(ServiceWorkerRegistration* aRegistration,
+          ServiceWorkerInfo aServiceWorkerInfo);
+
   NS_IMETHODIMP
   CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
                                const nsACString& aScriptSpec,
                                const nsACString& aScope,
                                ServiceWorker** aServiceWorker);
 
   static PLDHashOperator
   CleanupServiceWorkerInformation(const nsACString& aDomain,
--- a/dom/workers/SharedWorker.cpp
+++ b/dom/workers/SharedWorker.cpp
@@ -35,16 +35,17 @@ SharedWorker::SharedWorker(nsPIDOMWindow
   mSerial = aWorkerPrivate->NextMessagePortSerial();
 
   mMessagePort = new MessagePort(aWindow, this, mSerial);
 }
 
 SharedWorker::~SharedWorker()
 {
   AssertIsOnMainThread();
+  Close();
   MOZ_ASSERT(!mWorkerPrivate);
 }
 
 // static
 already_AddRefed<SharedWorker>
 SharedWorker::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
                           const nsAString& aScriptURL,
                           const mozilla::dom::Optional<nsAString>& aName,
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/bug998474_worker.js
@@ -0,0 +1,6 @@
+self.addEventListener("connect", function(e) {
+  var port = e.ports[0];
+  port.onmessage = function(e) {
+    port.postMessage(eval(e.data));
+  };
+});
--- a/dom/workers/test/mochitest.ini
+++ b/dom/workers/test/mochitest.ini
@@ -2,16 +2,17 @@
 support-files =
   WorkerTest_badworker.js
   atob_worker.js
   bug1014466_data1.txt
   bug1014466_data2.txt
   bug1014466_worker.js
   bug1020226_worker.js
   bug1020226_frame.html
+  bug998474_worker.js
   clearTimeouts_worker.js
   closeOnGC_server.sjs
   closeOnGC_worker.js
   close_worker.js
   content_worker.js
   console_worker.js
   consoleReplaceable_worker.js
   csp_worker.js
@@ -76,20 +77,22 @@ support-files =
   subdir/relativeLoad_sub_worker.js
   subdir/relativeLoad_sub_worker2.js
   subdir/relativeLoad_sub_import.js
 
 [test_404.html]
 [test_atob.html]
 [test_blobConstructor.html]
 [test_blobWorkers.html]
+[test_bug1002702.html]
 [test_bug949946.html]
 [test_bug1010784.html]
 [test_bug1014466.html]
 [test_bug1020226.html]
+[test_bug998474.html]
 [test_chromeWorker.html]
 [test_clearTimeouts.html]
 [test_close.html]
 [test_closeOnGC.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' #bug 881404 # b2g-debug(times out) b2g-desktop(times out)
 [test_console.html]
 [test_consoleReplaceable.html]
 [test_contentWorker.html]
@@ -116,16 +119,17 @@ skip-if = (toolkit == 'gonk' && debug) #
 [test_longThread.html]
 [test_multi_sharedWorker.html]
 [test_multi_sharedWorker_lifetimes.html]
 [test_navigator.html]
 [test_newError.html]
 [test_onLine.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only failure
 [test_promise.html]
+[test_promise_resolved_with_string.html]
 [test_recursion.html]
 [test_recursiveOnerror.html]
 [test_relativeLoad.html]
 skip-if = buildapp == 'b2g' # b2g(Failed to load script: relativeLoad_import.js) b2g-debug(Failed to load script: relativeLoad_import.js) b2g-desktop(Failed to load script: relativeLoad_import.js)
 [test_resolveWorker-assignment.html]
 [test_resolveWorker.html]
 [test_rvals.html]
 [test_sharedWorker.html]
--- a/dom/workers/test/serviceworkers/mochitest.ini
+++ b/dom/workers/test/serviceworkers/mochitest.ini
@@ -1,2 +1,8 @@
+[DEFAULT]
+support-files =
+  worker.js
+  worker2.js
+  worker3.js
+
 [test_installation_simple.html]
 [test_navigator.html]
--- a/dom/workers/test/serviceworkers/test_installation_simple.html
+++ b/dom/workers/test/serviceworkers/test_installation_simple.html
@@ -11,17 +11,17 @@
 </head>
 <body>
 <p id="display"></p>
 <div id="content" style="display: none"></div>
 <pre id="test"></pre>
 <script class="testbody" type="text/javascript">
 
   function simpleRegister() {
-    var p = navigator.serviceWorker.register("/fake_worker.js");
+    var p = navigator.serviceWorker.register("worker.js");
     ok(p instanceof Promise, "register() should return a Promise");
     return Promise.resolve();
   }
 
   function sameOriginWorker() {
     p = navigator.serviceWorker.register("http://some-other-origin/worker.js");
     return p.then(function(w) {
       ok(false, "Worker from different origin should fail");
@@ -45,24 +45,70 @@
     });
 
     return promise.then(function() {
       return navigator.serviceWorker.register("/worker.js");
     }).then(function(w) {
       ok(false, "non-HTTPS pages cannot register ServiceWorkers");
     }, function(e) {
       ok(e.name === "SecurityError", "Should fail with a SecurityError");
+    }).then(function() {
+      return new Promise((resolve) => SpecialPowers.popPrefEnv(resolve));
     });
   }
 
+  function realWorker() {
+    var p = navigator.serviceWorker.register("worker.js");
+    return p.then(function(w) {
+      ok(w instanceof ServiceWorker, "Register a ServiceWorker");
+      info(w.scope);
+      ok(w.scope == (new URL("/*", document.baseURI)).href, "Scope should match");
+      ok(w.url == (new URL("worker.js", document.baseURI)).href, "URL should be of the worker");
+    }, function(e) {
+      info(e.name);
+      ok(false, "Registration should have succeeded!");
+    });
+  }
+
+  function abortPrevious() {
+    var p = navigator.serviceWorker.register("worker2.js", { scope: "foo/*" });
+    var q = navigator.serviceWorker.register("worker3.js", { scope: "foo/*" });
+
+    return Promise.all([
+      p.then(function(w) {
+        ok(false, "First registration should fail with AbortError");
+      }, function(e) {
+        ok(e.name === "AbortError", "First registration should fail with AbortError");
+      }),
+
+      q.then(function(w) {
+        ok(w instanceof ServiceWorker, "Second registration should succeed");
+      }, function(e) {
+        ok(false, "Second registration should succeed");
+      })
+    ]);
+  }
+
+  function networkError404() {
+    return navigator.serviceWorker.register("404.js").then(function(w) {
+        todo(false, "Should fail with NetworkError");
+      }, function(e) {
+        todo(e.name === "NetworkError", "Should fail with NetworkError");
+      });
+  }
+
   function runTest() {
     simpleRegister()
       .then(sameOriginWorker)
       .then(sameOriginScope)
       .then(httpsOnly)
+      .then(realWorker)
+      .then(abortPrevious)
+      // FIXME(nsm): Uncomment once we have the error trapping patch from Bug 984048.
+      // .then(networkError404)
       // put more tests here.
       .then(function() {
         SimpleTest.finish();
       }).catch(function(e) {
         ok(false, "Some test failed with error " + e);
         SimpleTest.finish();
       });
   }
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/worker.js
@@ -0,0 +1,1 @@
+// empty worker, always succeed!
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/worker2.js
@@ -0,0 +1,1 @@
+// worker2.js
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/worker3.js
@@ -0,0 +1,1 @@
+// worker3.js
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_bug1002702.html
@@ -0,0 +1,27 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for bug 1002702</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+var port = new SharedWorker('data:application/javascript,1').port;
+port.close();
+SpecialPowers.forceGC();
+ok(true, "No crash \\o/");
+
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_bug998474.html
@@ -0,0 +1,39 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for bug 998474</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="boom();">
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+function boom()
+{
+  var worker = new SharedWorker("bug998474_worker.js");
+
+  setTimeout(function() {
+    port = worker.port;
+    port.postMessage("");
+
+    setTimeout(function() {
+      port.start();
+      ok(true, "Still alive!");
+      SimpleTest.finish();
+    }, 150);
+  }, 150);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_promise_resolved_with_string.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1027221
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1027221</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 1027221 **/
+    // Set up a permanent atom
+    SimpleTest.waitForExplicitFinish();
+    var x = "x";
+    // Trigger some incremental gc
+    SpecialPowers.Cu.getJSTestingFunctions().gcslice(0);
+
+    // Kick off a worker that uses this same atom
+    var w = new Worker("data:text/plain,Promise.resolve('x').then(function() { postMessage(1); });");
+    // Maybe trigger some more incremental gc
+    SpecialPowers.Cu.getJSTestingFunctions().gcslice(0);
+
+    w.onmessage = function() {
+      ok(true, "Got here");
+      SimpleTest.finish();
+    };
+
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1027221">Mozilla Bug 1027221</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -615,16 +615,18 @@ protected:
  */
 class DrawTarget : public RefCounted<DrawTarget>
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTarget)
   DrawTarget() : mTransformDirty(false), mPermitSubpixelAA(false) {}
   virtual ~DrawTarget() {}
 
+  virtual DrawTargetType GetType() const = 0;
+
   virtual BackendType GetBackendType() const = 0;
   /**
    * Returns a SourceSurface which is a snapshot of the current contents of the DrawTarget.
    * Multiple calls to Snapshot() without any drawing operations in between will
    * normally return the same SourceSurface object.
    */
   virtual TemporaryRef<SourceSurface> Snapshot() = 0;
   virtual IntSize GetSize() = 0;
--- a/gfx/2d/DrawTargetCG.cpp
+++ b/gfx/2d/DrawTargetCG.cpp
@@ -150,16 +150,23 @@ DrawTargetCG::~DrawTargetCG()
 
   // We need to conditionally release these because Init can fail without initializing these.
   if (mColorSpace)
     CGColorSpaceRelease(mColorSpace);
   if (mCg)
     CGContextRelease(mCg);
 }
 
+DrawTargetType
+DrawTargetCG::GetType() const
+{
+  return GetBackendType() == BackendType::COREGRAPHICS_ACCELERATED ?
+           DrawTargetType::HARDWARE_RASTER : DrawTargetType::SOFTWARE_RASTER;
+}
+
 BackendType
 DrawTargetCG::GetBackendType() const
 {
   // It may be worth spliting Bitmap and IOSurface DrawTarget
   // into seperate classes.
   if (GetContextType(mCg) == CG_CONTEXT_TYPE_IOSURFACE) {
     return BackendType::COREGRAPHICS_ACCELERATED;
   } else {
--- a/gfx/2d/DrawTargetCG.h
+++ b/gfx/2d/DrawTargetCG.h
@@ -95,16 +95,17 @@ SetStrokeOptions(CGContextRef cg, const 
 class DrawTargetCG : public DrawTarget
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetCG)
   friend class BorrowedCGContext;
   DrawTargetCG();
   virtual ~DrawTargetCG();
 
+  virtual DrawTargetType GetType() const MOZ_OVERRIDE;
   virtual BackendType GetBackendType() const;
   virtual TemporaryRef<SourceSurface> Snapshot();
 
   virtual void DrawSurface(SourceSurface *aSurface,
                            const Rect &aDest,
                            const Rect &aSource,
                            const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
                            const DrawOptions &aOptions = DrawOptions());
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -367,16 +367,66 @@ DrawTargetCairo::~DrawTargetCairo()
 {
   cairo_destroy(mContext);
   if (mSurface) {
     cairo_surface_destroy(mSurface);
   }
   MOZ_ASSERT(!mLockedBits);
 }
 
+DrawTargetType
+DrawTargetCairo::GetType() const
+{
+  if (mContext) {
+    cairo_surface_type_t type = cairo_surface_get_type(mSurface);
+    if (type == CAIRO_SURFACE_TYPE_TEE) {
+      type = cairo_surface_get_type(cairo_tee_surface_index(mSurface, 0));
+      MOZ_ASSERT(type != CAIRO_SURFACE_TYPE_TEE, "C'mon!");
+      MOZ_ASSERT(type == cairo_surface_get_type(cairo_tee_surface_index(mSurface, 1)),
+                 "What should we do here?");
+    }
+    switch (type) {
+    case CAIRO_SURFACE_TYPE_PDF:
+    case CAIRO_SURFACE_TYPE_PS:
+    case CAIRO_SURFACE_TYPE_SVG:
+    case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
+    case CAIRO_SURFACE_TYPE_XML:
+      return DrawTargetType::VECTOR;
+
+    case CAIRO_SURFACE_TYPE_VG:
+    case CAIRO_SURFACE_TYPE_GL:
+    case CAIRO_SURFACE_TYPE_GLITZ:
+    case CAIRO_SURFACE_TYPE_QUARTZ:
+    case CAIRO_SURFACE_TYPE_DIRECTFB:
+      return DrawTargetType::HARDWARE_RASTER;
+
+    case CAIRO_SURFACE_TYPE_SKIA:
+    case CAIRO_SURFACE_TYPE_QT:
+      MOZ_ASSERT(false, "Can't determine actual DrawTargetType for DrawTargetCairo - assuming SOFTWARE_RASTER");
+      // fallthrough
+    case CAIRO_SURFACE_TYPE_IMAGE:
+    case CAIRO_SURFACE_TYPE_XLIB:
+    case CAIRO_SURFACE_TYPE_XCB:
+    case CAIRO_SURFACE_TYPE_WIN32:
+    case CAIRO_SURFACE_TYPE_BEOS:
+    case CAIRO_SURFACE_TYPE_OS2:
+    case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE:
+    case CAIRO_SURFACE_TYPE_SCRIPT:
+    case CAIRO_SURFACE_TYPE_RECORDING:
+    case CAIRO_SURFACE_TYPE_DRM:
+    case CAIRO_SURFACE_TYPE_SUBSURFACE:
+    case CAIRO_SURFACE_TYPE_D2D:
+    case CAIRO_SURFACE_TYPE_TEE: // included to silence warning about unhandled enum value
+      return DrawTargetType::SOFTWARE_RASTER;
+    }
+  }
+  MOZ_ASSERT(false, "Could not determine DrawTargetType for DrawTargetCairo");
+  return DrawTargetType::SOFTWARE_RASTER;
+}
+
 IntSize
 DrawTargetCairo::GetSize()
 {
   return mSize;
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetCairo::Snapshot()
--- a/gfx/2d/DrawTargetCairo.h
+++ b/gfx/2d/DrawTargetCairo.h
@@ -53,16 +53,17 @@ class DrawTargetCairo : public DrawTarge
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetCairo)
   friend class BorrowedCairoContext;
 
   DrawTargetCairo();
   virtual ~DrawTargetCairo();
 
+  virtual DrawTargetType GetType() const MOZ_OVERRIDE;
   virtual BackendType GetBackendType() const { return BackendType::CAIRO; }
   virtual TemporaryRef<SourceSurface> Snapshot();
   virtual IntSize GetSize();
 
   virtual void SetPermitSubpixelAA(bool aPermitSubpixelAA);
 
   virtual bool LockBits(uint8_t** aData, IntSize* aSize,
                         int32_t* aStride, SurfaceFormat* aFormat);
--- a/gfx/2d/DrawTargetD2D.h
+++ b/gfx/2d/DrawTargetD2D.h
@@ -42,16 +42,17 @@ struct PrivateD3D10DataD2D
 
 class DrawTargetD2D : public DrawTarget
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D)
   DrawTargetD2D();
   virtual ~DrawTargetD2D();
 
+  virtual DrawTargetType GetType() const MOZ_OVERRIDE { return DrawTargetType::HARDWARE_RASTER; }
   virtual BackendType GetBackendType() const { return BackendType::DIRECT2D; }
   virtual TemporaryRef<SourceSurface> Snapshot();
   virtual IntSize GetSize() { return mSize; }
 
   virtual void Flush();
   virtual void DrawSurface(SourceSurface *aSurface,
                            const Rect &aDest,
                            const Rect &aSource,
--- a/gfx/2d/DrawTargetD2D1.h
+++ b/gfx/2d/DrawTargetD2D1.h
@@ -34,16 +34,17 @@ const int32_t kLayerCacheSize1 = 5;
 
 class DrawTargetD2D1 : public DrawTarget
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D1)
   DrawTargetD2D1();
   virtual ~DrawTargetD2D1();
 
+  virtual DrawTargetType GetType() const MOZ_OVERRIDE { return DrawTargetType::HARDWARE_RASTER; }
   virtual BackendType GetBackendType() const { return BackendType::DIRECT2D1_1; }
   virtual TemporaryRef<SourceSurface> Snapshot();
   virtual IntSize GetSize() { return mSize; }
 
   virtual void Flush();
   virtual void DrawSurface(SourceSurface *aSurface,
                            const Rect &aDest,
                            const Rect &aSource,
--- a/gfx/2d/DrawTargetDual.h
+++ b/gfx/2d/DrawTargetDual.h
@@ -38,16 +38,17 @@ public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetDual)
   DrawTargetDual(DrawTarget *aA, DrawTarget *aB)
     : mA(aA)
     , mB(aB)
   { 
     mFormat = aA->GetFormat();
   }
      
+  virtual DrawTargetType GetType() const MOZ_OVERRIDE { return mA->GetType(); }
   virtual BackendType GetBackendType() const { return mA->GetBackendType(); }
   virtual TemporaryRef<SourceSurface> Snapshot() { return new SourceSurfaceDual(mA, mB); }
   virtual IntSize GetSize() { return mA->GetSize(); }
      
   FORWARD_FUNCTION(Flush)
   FORWARD_FUNCTION1(PushClip, const Path *, aPath)
   FORWARD_FUNCTION1(PushClipRect, const Rect &, aRect)
   FORWARD_FUNCTION(PopClip)
--- a/gfx/2d/DrawTargetRecording.h
+++ b/gfx/2d/DrawTargetRecording.h
@@ -14,16 +14,17 @@ namespace gfx {
 
 class DrawTargetRecording : public DrawTarget
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetRecording)
   DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT, bool aHasData = false);
   ~DrawTargetRecording();
 
+  virtual DrawTargetType GetType() const MOZ_OVERRIDE { return mFinalDT->GetType(); }
   virtual BackendType GetBackendType() const { return mFinalDT->GetBackendType(); }
 
   virtual TemporaryRef<SourceSurface> Snapshot();
 
   virtual IntSize GetSize() { return mFinalDT->GetSize(); }
 
   /* Ensure that the DrawTarget backend has flushed all drawing operations to
    * this draw target. This must be called before using the backing surface of
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -272,22 +272,22 @@ struct AutoPaintSetup {
 
     // TODO: We could skip the temporary for operator_source and just
     // clear the clip rect. The other operators would be harder
     // but could be worth it to skip pushing a group.
     if (needsGroup) {
       mPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
       SkPaint temp;
       temp.setXfermodeMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
-      temp.setAlpha(U8CPU(aOptions.mAlpha*255+0.5));
+      temp.setAlpha(ColorFloatToByte(aOptions.mAlpha));
       //TODO: Get a rect here
       mCanvas->saveLayer(nullptr, &temp);
       mNeedsRestore = true;
     } else {
-      mPaint.setAlpha(U8CPU(aOptions.mAlpha*255.0+0.5));
+      mPaint.setAlpha(ColorFloatToByte(aOptions.mAlpha));
       mAlpha = aOptions.mAlpha;
     }
     mPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
   }
 
   // TODO: Maybe add an operator overload to access this easier?
   SkPaint mPaint;
   TempBitmap mTmpBitmap;
@@ -334,16 +334,27 @@ DrawTargetSkia::DrawSurface(SourceSurfac
   AutoPaintSetup paint(mCanvas.get(), aOptions, &aDest);
   if (aSurfOptions.mFilter == Filter::POINT) {
     paint.mPaint.setFilterLevel(SkPaint::kNone_FilterLevel);
   }
 
   mCanvas->drawBitmapRectToRect(bitmap.mBitmap, &sourceRect, destRect, &paint.mPaint);
 }
 
+DrawTargetType
+DrawTargetSkia::GetType() const
+{
+#ifdef USE_SKIA_GPU
+  if (mGrContext) {
+    return DrawTargetType::HARDWARE_RASTER;
+  }
+#endif
+  return DrawTargetType::SOFTWARE_RASTER;
+}
+
 void
 DrawTargetSkia::DrawFilter(FilterNode *aNode,
                            const Rect &aSourceRect,
                            const Point &aDestPoint,
                            const DrawOptions &aOptions)
 {
   FilterNodeSoftware* filter = static_cast<FilterNodeSoftware*>(aNode);
   filter->Draw(this, aSourceRect, aDestPoint, aOptions);
--- a/gfx/2d/DrawTargetSkia.h
+++ b/gfx/2d/DrawTargetSkia.h
@@ -26,16 +26,17 @@ class SourceSurfaceSkia;
 
 class DrawTargetSkia : public DrawTarget
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetSkia)
   DrawTargetSkia();
   virtual ~DrawTargetSkia();
 
+  virtual DrawTargetType GetType() const MOZ_OVERRIDE;
   virtual BackendType GetBackendType() const { return BackendType::SKIA; }
   virtual TemporaryRef<SourceSurface> Snapshot();
   virtual IntSize GetSize() { return mSize; }
   virtual void Flush();
   virtual void DrawSurface(SourceSurface *aSurface,
                            const Rect &aDest,
                            const Rect &aSource,
                            const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
--- a/gfx/2d/DrawTargetTiled.h
+++ b/gfx/2d/DrawTargetTiled.h
@@ -16,16 +16,17 @@ namespace gfx {
 
 class DrawTargetTiled : public DrawTarget
 {
 public:
   DrawTargetTiled();
 
   bool Init(const TileSet& mTiles);
 
+  virtual DrawTargetType GetType() const MOZ_OVERRIDE { return mTiles[0].mDrawTarget->GetType(); }
   virtual BackendType GetBackendType() const { return mTiles[0].mDrawTarget->GetBackendType(); }
   virtual TemporaryRef<SourceSurface> Snapshot();
   virtual IntSize GetSize() { return IntSize(mRect.XMost(), mRect.YMost()); }
 
   virtual void Flush();
   virtual void DrawSurface(SourceSurface *aSurface,
                            const Rect &aDest,
                            const Rect &aSource,
--- a/gfx/2d/HelpersSkia.h
+++ b/gfx/2d/HelpersSkia.h
@@ -230,21 +230,30 @@ GfxOpToSkiaOp(CompositionOp op)
       return SkXfermode::kColor_Mode;
     case CompositionOp::OP_LUMINOSITY:
       return SkXfermode::kLuminosity_Mode;
     default:
       return SkXfermode::kSrcOver_Mode;
   }
 }
 
-static inline SkColor ColorToSkColor(const Color &color, Float aAlpha)
+/* There's quite a bit of inconsistency about
+ * whether float colors should be rounded with .5f.
+ * We choose to do it to match cairo which also
+ * happens to match the Direct3D specs */
+static inline U8CPU ColorFloatToByte(Float color)
 {
   //XXX: do a better job converting to int
-  return SkColorSetARGB(U8CPU(color.a*aAlpha*255.0), U8CPU(color.r*255.0),
-                        U8CPU(color.g*255.0), U8CPU(color.b*255.0));
+  return U8CPU(color*255.f + .5f);
+};
+
+static inline SkColor ColorToSkColor(const Color &color, Float aAlpha)
+{
+  return SkColorSetARGB(ColorFloatToByte(color.a*aAlpha), ColorFloatToByte(color.r),
+                        ColorFloatToByte(color.g), ColorFloatToByte(color.b));
 }
 
 static inline SkRect
 RectToSkRect(const Rect& aRect)
 {
   return SkRect::MakeXYWH(SkFloatToScalar(aRect.x), SkFloatToScalar(aRect.y), 
                           SkFloatToScalar(aRect.width), SkFloatToScalar(aRect.height));
 }
--- a/gfx/2d/PathHelpers.h
+++ b/gfx/2d/PathHelpers.h
@@ -78,16 +78,61 @@ void ArcToBezier(T* aSink, const Point &
 
     aSink->BezierTo(cp1, cp2, currentEndPoint);
 
     arcSweepLeft -= Float(M_PI / 2.0f);
     currentStartAngle = currentEndAngle;
   }
 }
 
+/* This is basically the ArcToBezier with the parameters for drawing a circle
+ * inlined which vastly simplifies it and avoids a bunch of transcedental function
+ * calls which should make it faster. */
+template <typename T>
+void EllipseToBezier(T* aSink, const Point &aOrigin, const Size &aRadius)
+{
+  Point startPoint(aOrigin.x + aRadius.width,
+                   aOrigin.y);
+
+  aSink->LineTo(startPoint);
+
+  // Calculate kappa constant for partial curve. The sign of angle in the
+  // tangent will actually ensure this is negative for a counter clockwise
+  // sweep, so changing signs later isn't needed.
+  Float kappaFactor = (4.0f / 3.0f) * tan((M_PI/2.0f) / 4.0f);
+  Float kappaX = kappaFactor * aRadius.width;
+  Float kappaY = kappaFactor * aRadius.height;
+  Float cosStartAngle = 1;
+  Float sinStartAngle = 0;
+  for (int i = 0; i < 4; i++) {
+    // We guarantee here the current point is the start point of the next
+    // curve segment.
+    Point currentStartPoint(aOrigin.x + cosStartAngle * aRadius.width,
+                            aOrigin.y + sinStartAngle * aRadius.height);
+    Point currentEndPoint(aOrigin.x + -sinStartAngle * aRadius.width,
+                          aOrigin.y + cosStartAngle * aRadius.height);
+
+    Point tangentStart(-sinStartAngle, cosStartAngle);
+    Point cp1 = currentStartPoint;
+    cp1 += Point(tangentStart.x * kappaX, tangentStart.y * kappaY);
+
+    Point revTangentEnd(cosStartAngle, sinStartAngle);
+    Point cp2 = currentEndPoint;
+    cp2 += Point(revTangentEnd.x * kappaX, revTangentEnd.y * kappaY);
+
+    aSink->BezierTo(cp1, cp2, currentEndPoint);
+
+    // cos(x+pi/2) == -sin(x)
+    // sin(x+pi/2) == cos(x)
+    Float tmp = cosStartAngle;
+    cosStartAngle = -sinStartAngle;
+    sinStartAngle = tmp;
+  }
+}
+
 /**
  * Appends a path represending a rounded rectangle to the path being built by
  * aPathBuilder.
  *
  * aRect           The rectangle to append.
  * aCornerRadii    Contains the radii of the top-left, top-right, bottom-right
  *                 and bottom-left corners, in that order.
  * aDrawClockwise  If set to true, the path will start at the left of the top
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -67,16 +67,22 @@ MOZ_BEGIN_ENUM_CLASS(FilterType, int8_t)
   SPOT_SPECULAR,
   DISTANT_DIFFUSE,
   DISTANT_SPECULAR,
   CROP,
   PREMULTIPLY,
   UNPREMULTIPLY
 MOZ_END_ENUM_CLASS(FilterType)
 
+MOZ_BEGIN_ENUM_CLASS(DrawTargetType, int8_t)
+  SOFTWARE_RASTER = 0,
+  HARDWARE_RASTER,
+  VECTOR
+MOZ_END_ENUM_CLASS(DrawTargetType)
+
 MOZ_BEGIN_ENUM_CLASS(BackendType, int8_t)
   NONE = 0,
   DIRECT2D,
   COREGRAPHICS,
   COREGRAPHICS_ACCELERATED,
   CAIRO,
   SKIA,
   RECORDING,
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -9,17 +9,16 @@
 #include <algorithm>                    // for max, min
 #include "AnimationCommon.h"            // for ComputedTimingFunction
 #include "CompositableHost.h"           // for CompositableHost
 #include "ImageContainer.h"             // for ImageContainer, etc
 #include "ImageLayers.h"                // for ImageLayer
 #include "LayerSorter.h"                // for SortLayersBy3DZOrder
 #include "LayersLogging.h"              // for AppendToString
 #include "ReadbackLayer.h"              // for ReadbackLayer
-#include "gfxImageSurface.h"
 #include "gfxPlatform.h"                // for gfxPlatform
 #include "gfxUtils.h"                   // for gfxUtils, etc
 #include "gfx2DGlue.h"
 #include "mozilla/DebugOnly.h"          // for DebugOnly
 #include "mozilla/Telemetry.h"          // for Accumulate
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
@@ -1227,28 +1226,23 @@ void WriteSnapshotLinkToDumpFile(T* aObj
   string.Append('-');
   string.AppendInt((uint64_t)aObj);
   aStream << nsPrintfCString("href=\"javascript:ViewImage('%s')\"", string.BeginReading()).get();
 }
 
 template <typename T>
 void WriteSnapshotToDumpFile_internal(T* aObj, DataSourceSurface* aSurf)
 {
-  nsRefPtr<gfxImageSurface> deprecatedSurf =
-    new gfxImageSurface(aSurf->GetData(),
-                        ThebesIntSize(aSurf->GetSize()),
-                        aSurf->Stride(),
-                        SurfaceFormatToImageFormat(aSurf->GetFormat()));
   nsCString string(aObj->Name());
   string.Append('-');
   string.AppendInt((uint64_t)aObj);
   if (gfxUtils::sDumpPaintFile) {
     fprintf_stderr(gfxUtils::sDumpPaintFile, "array[\"%s\"]=\"", string.BeginReading());
   }
-  deprecatedSurf->DumpAsDataURL(gfxUtils::sDumpPaintFile);
+  gfxUtils::DumpAsDataURI(aSurf, gfxUtils::sDumpPaintFile);
   if (gfxUtils::sDumpPaintFile) {
     fprintf_stderr(gfxUtils::sDumpPaintFile, "\";");
   }
 }
 
 void WriteSnapshotToDumpFile(Layer* aLayer, DataSourceSurface* aSurf)
 {
   WriteSnapshotToDumpFile_internal(aLayer, aSurf);
--- a/gfx/layers/client/CompositableClient.cpp
+++ b/gfx/layers/client/CompositableClient.cpp
@@ -50,16 +50,27 @@ public:
     }
   }
 
   CompositableClient* mCompositableClient;
 
   uint64_t mAsyncID;
 };
 
+void
+RemoveTextureFromCompositableTracker::ReleaseTextureClient()
+{
+  if (mTextureClient) {
+    TextureClientReleaseTask* task = new TextureClientReleaseTask(mTextureClient);
+    RefPtr<ISurfaceAllocator> allocator = mTextureClient->GetAllocator();
+    mTextureClient = nullptr;
+    allocator->GetMessageLoop()->PostTask(FROM_HERE, task);
+  }
+}
+
 /* static */ void
 CompositableClient::TransactionCompleteted(PCompositableChild* aActor, uint64_t aTransactionId)
 {
   CompositableChild* child = static_cast<CompositableChild*>(aActor);
   child->TransactionCompleteted(aTransactionId);
 }
 
 /* static */ void
--- a/gfx/layers/client/CompositableClient.h
+++ b/gfx/layers/client/CompositableClient.h
@@ -37,42 +37,45 @@ public:
   RemoveTextureFromCompositableTracker()
   {
     MOZ_COUNT_CTOR(RemoveTextureFromCompositableTracker);
   }
 
   ~RemoveTextureFromCompositableTracker()
   {
     MOZ_COUNT_DTOR(RemoveTextureFromCompositableTracker);
+    ReleaseTextureClient();
   }
 
   virtual void Complete() MOZ_OVERRIDE
   {
-    // The TextureClient's recycling is postponed until the transaction
-    // complete.
-    mTextureClient = nullptr;
+    ReleaseTextureClient();
   }
 
   virtual void Cancel() MOZ_OVERRIDE
   {
-    mTextureClient = nullptr;
+    ReleaseTextureClient();
   }
 
   virtual void SetTextureClient(TextureClient* aTextureClient) MOZ_OVERRIDE
   {
+    ReleaseTextureClient();
     mTextureClient = aTextureClient;
   }
 
   virtual void SetReleaseFenceHandle(FenceHandle& aReleaseFenceHandle) MOZ_OVERRIDE
   {
     if (mTextureClient) {
       mTextureClient->SetReleaseFenceHandle(aReleaseFenceHandle);
     }
   }
 
+protected:
+  void ReleaseTextureClient();
+
 private:
   RefPtr<TextureClient> mTextureClient;
 };
 
 /**
  * CompositableClient manages the texture-specific logic for composite layers,
  * independently of the layer. It is the content side of a CompositableClient/
  * CompositableHost pair.
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -198,16 +198,17 @@ TextureClient::InitIPDLActor(Compositabl
   if (!ToSurfaceDescriptor(desc)) {
     return false;
   }
 
   mActor = static_cast<TextureChild*>(aForwarder->CreateTexture(desc, GetFlags()));
   MOZ_ASSERT(mActor);
   mActor->mForwarder = aForwarder;
   mActor->mTextureClient = this;
+  mAllocator = aForwarder;
   mShared = true;
   return mActor->IPCOpen();
 }
 
 PTextureChild*
 TextureClient::GetIPDLActor()
 {
   return mActor;
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -359,29 +359,55 @@ protected:
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
 
   void AddFlags(TextureFlags  aFlags)
   {
     MOZ_ASSERT(!IsSharedWithCompositor());
     mFlags |= aFlags;
   }
 
+  ISurfaceAllocator* GetAllocator()
+  {
+    return mAllocator;
+  }
+
   RefPtr<TextureChild> mActor;
+  RefPtr<ISurfaceAllocator> mAllocator;
   TextureFlags mFlags;
   bool mShared;
   bool mValid;
   FenceHandle mReleaseFenceHandle;
   FenceHandle mAcquireFenceHandle;
 
   friend class TextureChild;
+  friend class RemoveTextureFromCompositableTracker;
   friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);
   friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&);
 };
 
 /**
+ * Task that releases TextureClient pointer on a specified thread.
+ */
+class TextureClientReleaseTask : public Task
+{
+public:
+    TextureClientReleaseTask(TextureClient* aClient)
+        : mTextureClient(aClient) {
+    }
+
+    virtual void Run() MOZ_OVERRIDE
+    {
+        mTextureClient = nullptr;
+    }
+
+private:
+    mozilla::RefPtr<TextureClient> mTextureClient;
+};
+
+/**
  * TextureClient that wraps a random access buffer such as a Shmem or raw memory.
  * This class must be inherited to implement the memory allocation and access bits.
  * (see ShmemTextureClient and MemoryTextureClient)
  */
 class BufferTextureClient : public TextureClient
                           , public TextureClientYCbCr
 {
 public:
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CompositableHost.h"
 #include <map>                          // for _Rb_tree_iterator, map, etc
 #include <utility>                      // for pair
 #include "ContentHost.h"                // for ContentHostDoubleBuffered, etc
 #include "Effects.h"                    // for EffectMask, Effect, etc
+#include "gfxUtils.h"
 #include "ImageHost.h"                  // for ImageHostBuffered, etc
 #include "TiledContentHost.h"           // for TiledContentHost
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/TextureHost.h"  // for TextureHost, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_WARNING
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "gfxPlatform.h"                // for gfxPlatform
@@ -222,22 +223,18 @@ CompositableHost::DumpTextureHost(std::s
   if (!dSurf) {
     return;
   }
   gfxPlatform *platform = gfxPlatform::GetPlatform();
   RefPtr<gfx::DrawTarget> dt = platform->CreateDrawTargetForData(dSurf->GetData(),
                                                                  dSurf->GetSize(),
                                                                  dSurf->Stride(),
                                                                  dSurf->GetFormat());
-  nsRefPtr<gfxASurface> surf = platform->GetThebesSurfaceForDrawTarget(dt);
-  if (!surf) {
-    return;
-  }
   // TODO stream surface
-  surf->DumpAsDataURL(stderr);
+  gfxUtils::DumpAsDataURI(dt, stderr);
 }
 #endif
 
 namespace CompositableMap {
 
 typedef std::map<uint64_t, PCompositableParent*> CompositableMap_t;
 static CompositableMap_t* sCompositableMap = nullptr;
 bool IsCreated() {
--- a/gfx/layers/ipc/ISurfaceAllocator.h
+++ b/gfx/layers/ipc/ISurfaceAllocator.h
@@ -80,17 +80,19 @@ TemporaryRef<gfx::DataSourceSurface> Get
  * actors without a common polymorphic interface.
  * These methods should be only called in the ipdl implementor's thread, unless
  * specified otherwise in the implementing class.
  */
 class ISurfaceAllocator : public AtomicRefCountedWithFinalize<ISurfaceAllocator>
 {
 public:
   MOZ_DECLARE_REFCOUNTED_TYPENAME(ISurfaceAllocator)
-  ISurfaceAllocator() {}
+  ISurfaceAllocator()
+    : mDefaultMessageLoop(MessageLoop::current())
+  {}
 
   void Finalize();
 
   /**
    * Returns the type of backend that is used off the main thread.
    * We only don't allow changing the backend type at runtime so this value can
    * be queried once and will not change until Gecko is restarted.
    *
@@ -158,30 +160,37 @@ public:
                           uint32_t aUsage,
                           MaybeMagicGrallocBufferHandle* aHandle);
 
   void DeallocGrallocBuffer(MaybeMagicGrallocBufferHandle* aHandle);
 
   virtual bool IPCOpen() const { return true; }
   virtual bool IsSameProcess() const = 0;
 
+  virtual MessageLoop * GetMessageLoop() const
+  {
+    return mDefaultMessageLoop;
+  }
+
   // Returns true if aSurface wraps a Shmem.
   static bool IsShmem(SurfaceDescriptor* aSurface);
 
 protected:
 
   virtual bool IsOnCompositorSide() const = 0;
 
   virtual ~ISurfaceAllocator();
 
   void ShrinkShmemSectionHeap();
 
   // This is used to implement an extremely simple & naive heap allocator.
   std::vector<mozilla::ipc::Shmem> mUsedShmems;
 
+  MessageLoop* mDefaultMessageLoop;
+
   friend class AtomicRefCountedWithFinalize<ISurfaceAllocator>;
 };
 
 class GfxMemoryImageReporter MOZ_FINAL : public nsIMemoryReporter
 {
   ~GfxMemoryImageReporter() {}
 
 public:
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -165,17 +165,17 @@ public:
    */
   base::Thread * GetThread() const;
 
   /**
    * Returns the ImageBridgeChild's message loop.
    *
    * Can be called from any thread.
    */
-  MessageLoop * GetMessageLoop() const;
+  virtual MessageLoop * GetMessageLoop() const MOZ_OVERRIDE;
 
   PCompositableChild* AllocPCompositableChild(const TextureInfo& aInfo, uint64_t* aID) MOZ_OVERRIDE;
   bool DeallocPCompositableChild(PCompositableChild* aActor) MOZ_OVERRIDE;
 
   /**
    * This must be called by the static function DeleteImageBridgeSync defined
    * in ImageBridgeChild.cpp ONLY.
    */
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -256,17 +256,17 @@ ImageBridgeParent::RecvChildAsyncMessage
       default:
         NS_ERROR("unknown AsyncChildMessageData type");
         return false;
     }
   }
   return true;
 }
 
-MessageLoop * ImageBridgeParent::GetMessageLoop() {
+MessageLoop * ImageBridgeParent::GetMessageLoop() const {
   return mMessageLoop;
 }
 
 class ReleaseRunnable : public nsRunnable
 {
 public:
   ReleaseRunnable(ImageBridgeParent* aRef)
     : mRef(aRef)
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -83,17 +83,17 @@ public:
   virtual bool
   RecvChildAsyncMessages(const InfallibleTArray<AsyncChildMessageData>& aMessages) MOZ_OVERRIDE;
 
   // Shutdown step 1
   virtual bool RecvWillStop() MOZ_OVERRIDE;
   // Shutdown step 2
   virtual bool RecvStop() MOZ_OVERRIDE;
 
-  MessageLoop * GetMessageLoop();
+  virtual MessageLoop* GetMessageLoop() const MOZ_OVERRIDE;
 
 
   // ISurfaceAllocator
 
   bool AllocShmem(size_t aSize,
                   ipc::SharedMemory::SharedMemoryType aType,
                   ipc::Shmem* aShmem) MOZ_OVERRIDE
   {
--- a/gfx/src/nsITheme.h
+++ b/gfx/src/nsITheme.h
@@ -23,24 +23,24 @@ class nsPresContext;
 class nsRenderingContext;
 class nsDeviceContext;
 class nsIFrame;
 class nsIContent;
 class nsIAtom;
 class nsIWidget;
 
 // IID for the nsITheme interface
-// {b0f3efe9-0bd4-4f6b-8daa-0ec7f6006822}
+// {7a3474d9-3bd6-407c-8657-c5c7633639f0}
  #define NS_ITHEME_IID     \
-{ 0x4440b5c7, 0xd8bd, 0x4d9c, \
-  { 0x9c, 0x3e, 0xa5, 0xe6, 0x26, 0x81, 0x10, 0xa0 } }
-// {D930E29B-6909-44e5-AB4B-AF10D6923705}
+{ 0x7a3474d9, 0x3bd6, 0x407c, \
+  { 0x86, 0x57, 0xc5, 0xc7, 0x63, 0x36, 0x39, 0xf0 } }
+// {0ae05515-cf7a-45a8-9e02-6556de7685b1}
 #define NS_THEMERENDERER_CID \
-{ 0x9020805b, 0x14a3, 0x4125, \
-  { 0xa5, 0x63, 0x4a, 0x8c, 0x5d, 0xe0, 0xa9, 0xa3 } }
+{ 0x0ae05515, 0xcf7a, 0x45a8, \
+  { 0x9e, 0x02, 0x65, 0x56, 0xde, 0x76, 0x85, 0xb1 } }
 
 /**
  * nsITheme is a service that provides platform-specific native
  * rendering for widgets.  In other words, it provides the necessary
  * operations to draw a rendering object (an nsIFrame) as a native
  * widget.
  *
  * All the methods on nsITheme take a rendering context or device
@@ -108,17 +108,17 @@ public:
   { return false; }
 
   /**
    * Get the minimum border-box size of a widget, in *pixels* (in
    * |aResult|).  If |aIsOverridable| is set to true, this size is a
    * minimum size; if false, this size is the only valid size for the
    * widget.
    */
-  NS_IMETHOD GetMinimumWidgetSize(nsRenderingContext* aContext,
+  NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext,
                                   nsIFrame* aFrame,
                                   uint8_t aWidgetType,
                                   nsIntSize* aResult,
                                   bool* aIsOverridable)=0;
 
 
   enum Transparency {
     eOpaque = 0,
--- a/gfx/src/nsRenderingContext.cpp
+++ b/gfx/src/nsRenderingContext.cpp
@@ -15,18 +15,16 @@
 #include "mozilla/mozalloc.h"           // for operator delete[], etc
 #include "nsBoundingMetrics.h"          // for nsBoundingMetrics
 #include "nsCharTraits.h"               // for NS_IS_LOW_SURROGATE
 #include "nsDebug.h"                    // for NS_ERROR
 #include "nsPoint.h"                    // for nsPoint
 #include "nsRect.h"                     // for nsRect, nsIntRect
 #include "nsRegion.h"                   // for nsIntRegionRectIterator, etc
 
-class gfxASurface;
-
 // XXXTodo: rename FORM_TWIPS to FROM_APPUNITS
 #define FROM_TWIPS(_x)  ((gfxFloat)((_x)/(mP2A)))
 #define FROM_TWIPS_INT(_x)  (NSToIntRound((gfxFloat)((_x)/(mP2A))))
 #define TO_TWIPS(_x)    ((nscoord)((_x)*(mP2A)))
 #define GFX_RECT_FROM_TWIPS_RECT(_r)   (gfxRect(FROM_TWIPS((_r).x), FROM_TWIPS((_r).y), FROM_TWIPS((_r).width), FROM_TWIPS((_r).height)))
 
 // Hard limit substring lengths to 8000 characters ... this lets us statically
 // size the cluster buffer array in FindSafeLength
@@ -62,23 +60,16 @@ static int32_t FindSafeLength(const char
     return std::min(aLength, aMaxChunkLength);
 }
 
 //////////////////////////////////////////////////////////////////////
 //// nsRenderingContext
 
 void
 nsRenderingContext::Init(nsDeviceContext* aContext,
-                         gfxASurface *aThebesSurface)
-{
-    Init(aContext, new gfxContext(aThebesSurface));
-}
-
-void
-nsRenderingContext::Init(nsDeviceContext* aContext,
                          gfxContext *aThebesContext)
 {
     mDeviceContext = aContext;
     mThebes = aThebesContext;
 
     mThebes->SetLineWidth(1.0);
     mP2A = mDeviceContext->AppUnitsPerDevPixel();
 }
--- a/gfx/src/nsRenderingContext.h
+++ b/gfx/src/nsRenderingContext.h
@@ -17,17 +17,16 @@
 #include "nsColor.h"                    // for nscolor
 #include "nsCoord.h"                    // for nscoord, NSToIntRound
 #include "nsDeviceContext.h"            // for nsDeviceContext
 #include "nsFontMetrics.h"              // for nsFontMetrics
 #include "nsISupports.h"                // for NS_INLINE_DECL_REFCOUNTING, etc
 #include "nsString.h"               // for nsString
 #include "nscore.h"                     // for char16_t
 
-class gfxASurface;
 class nsIntRegion;
 struct nsPoint;
 struct nsRect;
 
 typedef enum {
     nsLineStyle_kNone   = 0,
     nsLineStyle_kSolid  = 1,
     nsLineStyle_kDashed = 2,
@@ -40,17 +39,16 @@ class nsRenderingContext MOZ_FINAL
     typedef mozilla::gfx::UserDataKey UserDataKey;
     typedef mozilla::gfx::DrawTarget DrawTarget;
 
 public:
     nsRenderingContext() : mP2A(0.) {}
 
     NS_INLINE_DECL_REFCOUNTING(nsRenderingContext)
 
-    void Init(nsDeviceContext* aContext, gfxASurface* aThebesSurface);
     void Init(nsDeviceContext* aContext, gfxContext* aThebesContext);
     void Init(nsDeviceContext* aContext, DrawTarget* aDrawTarget);
 
     // These accessors will never return null.
     gfxContext *ThebesContext() { return mThebes; }
     DrawTarget *GetDrawTarget() { return mThebes->GetDrawTarget(); }
     nsDeviceContext *DeviceContext() { return mDeviceContext; }
 
--- a/gfx/thebes/gfxASurface.cpp
+++ b/gfx/thebes/gfxASurface.cpp
@@ -679,189 +679,16 @@ gfxASurface::BytesPerPixel(gfxImageForma
     case gfxImageFormat::Unknown:
     default:
       NS_NOTREACHED("Not really sure what you want me to say here");
       return 0;
   }
 }
 
 void
-gfxASurface::WriteAsPNG(const char* aFile)
-{
-    FILE *file = fopen(aFile, "wb");
-    if (file) {
-      WriteAsPNG_internal(file, true);
-      fclose(file);
-    } else {
-      NS_WARNING("Failed to create file!\n");
-    }
-}
-
-void
-gfxASurface::DumpAsDataURL(FILE* aOutput)
-{
-  WriteAsPNG_internal(aOutput, false);
-}
-
-void
-gfxASurface::CopyAsDataURL()
-{
-  WriteAsPNG_internal(nullptr, false);
-}
-
-/**
- * Write to a PNG file. If aBinary is true, then it is written
- * as binary, otherwise as a data URL. If no file is specified then
- * data is copied to the clipboard (must not be binary!).
- */
-void
-gfxASurface::WriteAsPNG_internal(FILE* aFile, bool aBinary)
-{
-  nsRefPtr<gfxImageSurface> imgsurf = GetAsImageSurface();
-  nsIntSize size;
-
-  // FIXME/bug 831898: hack r5g6b5 for now.
-  if (!imgsurf || imgsurf->Format() == gfxImageFormat::RGB16_565) {
-    size = GetSize();
-    if (size.width == -1 && size.height == -1) {
-      printf("Could not determine surface size\n");
-      return;
-    }
-
-    imgsurf =
-      new gfxImageSurface(nsIntSize(size.width, size.height),
-                          gfxImageFormat::ARGB32);
-
-    if (!imgsurf || imgsurf->CairoStatus()) {
-      printf("Could not allocate image surface\n");
-      return;
-    }
-
-    nsRefPtr<gfxContext> ctx = new gfxContext(imgsurf);
-    if (!ctx || ctx->HasError()) {
-      printf("Could not allocate image context\n");
-      return;
-    }
-
-    ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
-    ctx->SetSource(this, gfxPoint(0, 0));
-    ctx->Paint();
-  }
-  size = imgsurf->GetSize();
-
-  nsCOMPtr<imgIEncoder> encoder =
-    do_CreateInstance("@mozilla.org/image/encoder;2?type=image/png");
-  if (!encoder) {
-    int32_t w = std::min(size.width, 8);
-    int32_t h = std::min(size.height, 8);
-    printf("Could not create encoder. Printing %dx%d pixels.\n", w, h);
-    for (int32_t y = 0; y < h; ++y) {
-      for (int32_t x = 0; x < w; ++x) {
-        printf("%x ", reinterpret_cast<uint32_t*>(imgsurf->Data())[y*imgsurf->Stride()+ x]);
-      }
-    }
-    return;
-  }
-
-  nsresult rv = encoder->InitFromData(imgsurf->Data(),
-                                      size.width * size.height * 4,
-                                      size.width,
-                                      size.height,
-                                      imgsurf->Stride(),
-                                      imgIEncoder::INPUT_FORMAT_HOSTARGB,
-                                      NS_LITERAL_STRING(""));
-  if (NS_FAILED(rv))
-    return;
-
-  nsCOMPtr<nsIInputStream> imgStream;
-  CallQueryInterface(encoder.get(), getter_AddRefs(imgStream));
-  if (!imgStream)
-    return;
-
-  uint64_t bufSize64;
-  rv = imgStream->Available(&bufSize64);
-  if (NS_FAILED(rv))
-    return;
-
-  if (bufSize64 > UINT32_MAX - 16)
-    return;
-
-  uint32_t bufSize = (uint32_t)bufSize64;
-
-  // ...leave a little extra room so we can call read again and make sure we
-  // got everything. 16 bytes for better padding (maybe)
-  bufSize += 16;
-  uint32_t imgSize = 0;
-  char* imgData = (char*)moz_malloc(bufSize);
-  if (!imgData)
-    return;
-  uint32_t numReadThisTime = 0;
-  while ((rv = imgStream->Read(&imgData[imgSize],
-                               bufSize - imgSize,
-                               &numReadThisTime)) == NS_OK && numReadThisTime > 0)
-  {
-    imgSize += numReadThisTime;
-    if (imgSize == bufSize) {
-      // need a bigger buffer, just double
-      bufSize *= 2;
-      char* newImgData = (char*)moz_realloc(imgData, bufSize);
-      if (!newImgData) {
-        moz_free(imgData);
-        return;
-      }
-      imgData = newImgData;
-    }
-  }
-
-  if (aBinary) {
-    if (aFile) {
-      fwrite(imgData, 1, imgSize, aFile);
-    } else {
-      NS_WARNING("Can't write binary image data without a file!");
-    }
-    return;
-  }
-
-  // base 64, result will be null-terminated
-  nsCString encodedImg;
-  rv = Base64Encode(Substring(imgData, imgSize), encodedImg);
-  moz_free(imgData);
-  if (NS_FAILED(rv)) // not sure why this would fail
-    return;
-
-  nsCString string("data:image/png;base64,");
-  string.Append(encodedImg);
-
-  if (aFile) {
-#ifdef ANDROID
-     if (aFile == stdout || aFile == stderr) {
-       // ADB logcat cuts off long strings so we will break it down
-       const char* cStr = string.BeginReading();
-       size_t len = strlen(cStr);
-       while (true) {
-         printf_stderr("IMG: %.140s\n", cStr);
-         if (len <= 140)
-           break;
-         len -= 140;
-         cStr += 140;
-       }
-     }
-#endif
-    fprintf_stderr(aFile, "%s", string.BeginReading());
-  } else {
-    nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
-    if (clipboard) {
-      clipboard->CopyString(NS_ConvertASCIItoUTF16(string), nullptr);
-    }
-  }
-
-  return;
-}
-
-void
 gfxASurface::SetOpaqueRect(const gfxRect& aRect)
 {
     if (aRect.IsEmpty()) {
         mOpaqueRect = nullptr;
     } else if (!!mOpaqueRect) {
         *mOpaqueRect = aRect;
     } else {
         mOpaqueRect = new gfxRect(aRect);
--- a/gfx/thebes/gfxASurface.h
+++ b/gfx/thebes/gfxASurface.h
@@ -170,37 +170,16 @@ public:
      * process's heap.
      */
     virtual gfxMemoryLocation GetMemoryLocation() const;
 
     static int32_t BytePerPixelFromFormat(gfxImageFormat format);
 
     virtual const nsIntSize GetSize() const;
 
-    /**
-     * Debug functions to encode the current image as a PNG and export it.
-     */
-
-    /**
-     * Writes a binary PNG file.
-     */
-    void WriteAsPNG(const char* aFile);
-
-    /**
-     * Write as a PNG encoded Data URL to a file.
-     */
-    void DumpAsDataURL(FILE* aOutput = stdout);
-
-    /**
-     * Copy a PNG encoded Data URL to the clipboard.
-     */
-    void CopyAsDataURL();
-
-    void WriteAsPNG_internal(FILE* aFile, bool aBinary);
-
     void SetOpaqueRect(const gfxRect& aRect);
 
     const gfxRect& GetOpaqueRect() {
         if (!!mOpaqueRect)
             return *mOpaqueRect;
         return GetEmptyOpaqueRect();
     }
 
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -11,16 +11,17 @@
 #include "mozilla/Alignment.h"
 
 #include "cairo.h"
 
 #include "gfxContext.h"
 
 #include "gfxColor.h"
 #include "gfxMatrix.h"
+#include "gfxUtils.h"
 #include "gfxASurface.h"
 #include "gfxPattern.h"
 #include "gfxPlatform.h"
 #include "gfxTeeSurface.h"
 #include "GeckoProfiler.h"
 #include "gfx2DGlue.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include <algorithm>
@@ -1952,44 +1953,41 @@ gfxContext::RoundedRectangle(const gfxRe
                      ToSize(corners[NS_CORNER_BOTTOM_LEFT]) };
     AppendRoundedRectToPath(mPathBuilder, ToRect(rect), radii, draw_clockwise);
   }
 }
 
 #ifdef MOZ_DUMP_PAINTING
 void
 gfxContext::WriteAsPNG(const char* aFile)
-{ 
-  nsRefPtr<gfxASurface> surf = CurrentSurface();
-  if (surf) {
-    surf->WriteAsPNG(aFile);
+{
+  if (mDT) {
+    gfxUtils::WriteAsPNG(mDT, aFile);
   } else {
-    NS_WARNING("No surface found!");
+    NS_WARNING("No DrawTarget found!");
   }
 }
 
 void 
-gfxContext::DumpAsDataURL()
-{ 
-  nsRefPtr<gfxASurface> surf = CurrentSurface();
-  if (surf) {
-    surf->DumpAsDataURL();
+gfxContext::DumpAsDataURI()
+{
+  if (mDT) {
+    gfxUtils::DumpAsDataURI(mDT);
   } else {
-    NS_WARNING("No surface found!");
+    NS_WARNING("No DrawTarget found!");
   }
 }
 
 void 
-gfxContext::CopyAsDataURL()
-{ 
-  nsRefPtr<gfxASurface> surf = CurrentSurface();
-  if (surf) {
-    surf->CopyAsDataURL();
+gfxContext::CopyAsDataURI()
+{
+  if (mDT) {
+    gfxUtils::CopyAsDataURI(mDT);
   } else {
-    NS_WARNING("No surface found!");
+    NS_WARNING("No DrawTarget found!");
   }
 }
 #endif
 
 void
 gfxContext::EnsurePath()
 {
   if (mPathBuilder) {
--- a/gfx/thebes/gfxContext.h
+++ b/gfx/thebes/gfxContext.h
@@ -702,22 +702,22 @@ public:
     /**
      * Writes a binary PNG file.
      */
     void WriteAsPNG(const char* aFile);
 
     /**
      * Write as a PNG encoded Data URL to stdout.
      */
-    void DumpAsDataURL();
+    void DumpAsDataURI();
 
     /**
      * Copy a PNG encoded Data URL to the clipboard.
      */
-    void CopyAsDataURL();
+    void CopyAsDataURI();
 #endif
 
     static mozilla::gfx::UserDataKey sDontUseAsSourceKey;
 
 private:
     ~gfxContext();
 
   friend class GeneralPattern;
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/MemoryReporting.h"
 
 #include "mozilla/dom/ContentChild.h"
 #include "gfxAndroidPlatform.h"
 #include "mozilla/Omnijar.h"
+#include "nsAutoPtr.h"
 #include "nsIInputStream.h"
 #include "nsNetUtil.h"
 #define gfxToolkitPlatform gfxAndroidPlatform
 
 #include "nsXULAppAPI.h"
 #include <dirent.h>
 #include <android/log.h>
 #define ALOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gecko" , ## args)
@@ -1079,17 +1080,18 @@ gfxFT2FontList::AppendFacesFromOmnijarEn
     }
 
     nsZipItem *item = aArchive->GetItem(aEntryName.get());
     NS_ASSERTION(item, "failed to find zip entry");
 
     uint32_t bufSize = item->RealSize();
     // We use fallible allocation here; if there's not enough RAM, we'll simply
     // ignore the bundled fonts and fall back to the device's installed fonts.
-    nsAutoPtr<uint8_t> buf(static_cast<uint8_t*>(moz_malloc(bufSize)));
+    static const fallible_t fallible = fallible_t();
+    nsAutoArrayPtr<uint8_t> buf(new (fallible) uint8_t[bufSize]);
     if (!buf) {
         return;
     }
 
     nsZipCursor cursor(item, aArchive, buf, bufSize);
     uint8_t* data = cursor.Copy(&bufSize);
     NS_ASSERTION(data && bufSize == item->RealSize(),
                  "error reading bundled font");
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -871,26 +871,42 @@ gfxUserFontSet::UserFontCache::Flusher::
         sUserFonts->EnumerateEntries(Entry::DisconnectSVG, nullptr);
     } else {
         NS_NOTREACHED("unexpected topic");
     }
 
     return NS_OK;
 }
 
+static bool
+IgnorePrincipal(nsIURI *aURI)
+{
+    nsresult rv;
+    bool inherits = false;
+    rv = NS_URIChainHasFlags(aURI,
+                             nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
+                             &inherits);
+    return NS_SUCCEEDED(rv) && inherits;
+}
+
 bool
 gfxUserFontSet::UserFontCache::Entry::KeyEquals(const KeyTypePointer aKey) const
 {
-    bool equal;
-    if (NS_FAILED(mURI->Equals(aKey->mURI, &equal)) || !equal) {
+    bool result;
+    if (NS_FAILED(mURI->Equals(aKey->mURI, &result)) || !result) {
         return false;
     }
 
-    if (NS_FAILED(mPrincipal->Equals(aKey->mPrincipal, &equal)) || !equal) {
-        return false;
+    // For data: URIs, we don't care about the principal; otherwise, check it.
+    if (!IgnorePrincipal(mURI)) {
+        NS_ASSERTION(mPrincipal && aKey->mPrincipal,
+                     "only data: URIs are allowed to omit the principal");
+        if (NS_FAILED(mPrincipal->Equals(aKey->mPrincipal, &result)) || !result) {
+            return false;
+        }
     }
 
     if (mPrivate != aKey->mPrivate) {
         return false;
     }
 
     const gfxFontEntry *fe = aKey->mFontEntry;
     if (mFontEntry->mItalic           != fe->mItalic          ||
@@ -920,17 +936,26 @@ gfxUserFontSet::UserFontCache::CacheFont
             obs->AddObserver(flusher, "cacheservice:empty-cache",
                              false);
             obs->AddObserver(flusher, "last-pb-context-exited", false);
             obs->AddObserver(flusher, "xpcom-shutdown", false);
         }
     }
 
     gfxUserFontData *data = aFontEntry->mUserFontData;
-    sUserFonts->PutEntry(Key(data->mURI, data->mPrincipal, aFontEntry,
+    // For data: URIs, the principal is ignored; anyone who has the same
+    // data: URI is able to load it and get an equivalent font.
+    // Otherwise, the principal is used as part of the cache key.
+    nsIPrincipal *principal;
+    if (IgnorePrincipal(data->mURI)) {
+        principal = nullptr;
+    } else {
+        principal = data->mPrincipal;
+    }
+    sUserFonts->PutEntry(Key(data->mURI, principal, aFontEntry,
                              data->mPrivate));
 
 #ifdef DEBUG_USERFONT_CACHE
     printf("userfontcache added fontentry: %p\n", aFontEntry);
     Dump();
 #endif
 }
 
@@ -960,17 +985,25 @@ gfxUserFontSet::UserFontCache::GetFont(n
                                        nsIPrincipal      *aPrincipal,
                                        gfxProxyFontEntry *aProxy,
                                        bool               aPrivate)
 {
     if (!sUserFonts) {
         return nullptr;
     }
 
-    Entry* entry = sUserFonts->GetEntry(Key(aSrcURI, aPrincipal, aProxy,
+    // Ignore principal when looking up a data: URI.
+    nsIPrincipal *principal;
+    if (IgnorePrincipal(aSrcURI)) {
+        principal = nullptr;
+    } else {
+        principal = aPrincipal;
+    }
+
+    Entry* entry = sUserFonts->GetEntry(Key(aSrcURI, principal, aProxy,
                                             aPrivate));
     if (entry) {
         return entry->GetFontEntry();
     }
 
     return nullptr;
 }
 
@@ -985,30 +1018,31 @@ gfxUserFontSet::UserFontCache::Shutdown(
 
 #ifdef DEBUG_USERFONT_CACHE
 
 PLDHashOperator
 gfxUserFontSet::UserFontCache::Entry::DumpEntry(Entry* aEntry, void* aUserData)
 {
     nsresult rv;
 
-    nsAutoCString principalURISpec;
+    nsAutoCString principalURISpec("(null)");
+    bool setDomain = false;
 
-    nsCOMPtr<nsIURI> principalURI;
-    rv = aEntry->mPrincipal->GetURI(getter_AddRefs(principalURI));
-    if (NS_SUCCEEDED(rv)) {
-        principalURI->GetSpec(principalURISpec);
-    }
+    if (aEntry->mPrincipal) {
+        nsCOMPtr<nsIURI> principalURI;
+        rv = aEntry->mPrincipal->GetURI(getter_AddRefs(principalURI));
+        if (NS_SUCCEEDED(rv)) {
+            principalURI->GetSpec(principalURISpec);
+        }
 
-    bool setDomain = false;
-    nsCOMPtr<nsIURI> domainURI;
-
-    aEntry->mPrincipal->GetDomain(getter_AddRefs(domainURI));
-    if (domainURI) {
-        setDomain = true;
+        nsCOMPtr<nsIURI> domainURI;
+        aEntry->mPrincipal->GetDomain(getter_AddRefs(domainURI));
+        if (domainURI) {
+            setDomain = true;
+        }
     }
 
     NS_ASSERTION(aEntry->mURI, "null URI in userfont cache entry");
 
     printf("userfontcache fontEntry: %p fonturihash: %8.8x family: %s domainset: %s principal: [%s]\n",
             aEntry->mFontEntry,
             nsURIHashKey::HashKey(aEntry->mURI),
             NS_ConvertUTF16toUTF8(aEntry->mFontEntry->FamilyName()).get(),
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -289,17 +289,17 @@ public:
         // Key used to look up entries in the user-font cache.
         // Note that key comparison does *not* use the mFontEntry field
         // as a whole; it only compares specific fields within the entry
         // (weight/width/style/features) that could affect font selection
         // or rendering, and that must match between a font-set's proxy
         // entry and the corresponding "real" font entry.
         struct Key {
             nsCOMPtr<nsIURI>        mURI;
-            nsCOMPtr<nsIPrincipal>  mPrincipal;
+            nsCOMPtr<nsIPrincipal>  mPrincipal; // use nullptr with data: URLs
             gfxFontEntry           *mFontEntry;
             bool                    mPrivate;
 
             Key(nsIURI* aURI, nsIPrincipal* aPrincipal,
                 gfxFontEntry* aFontEntry, bool aPrivate)
                 : mURI(aURI),
                   mPrincipal(aPrincipal),
                   mFontEntry(aFontEntry),
@@ -328,18 +328,20 @@ public:
 
             ~Entry() { }
 
             bool KeyEquals(const KeyTypePointer aKey) const;
 
             static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
 
             static PLDHashNumber HashKey(const KeyTypePointer aKey) {
-                uint32_t principalHash;
-                aKey->mPrincipal->GetHashValue(&principalHash);
+                uint32_t principalHash = 0;
+                if (aKey->mPrincipal) {
+                    aKey->mPrincipal->GetHashValue(&principalHash);
+                }
                 return mozilla::HashGeneric(principalHash + int(aKey->mPrivate),
                                             nsURIHashKey::HashKey(aKey->mURI),
                                             HashFeatures(aKey->mFontEntry->mFeatureSettings),
                                             mozilla::HashString(aKey->mFontEntry->mFamilyName),
                                             ((uint32_t)aKey->mFontEntry->mItalic |
                                              (aKey->mFontEntry->mWeight << 1) |
                                              (aKey->mFontEntry->mStretch << 10) ) ^
                                              aKey->mFontEntry->mLanguageOverride);
@@ -360,17 +362,17 @@ public:
         private:
             static uint32_t
             HashFeatures(const nsTArray<gfxFontFeature>& aFeatures) {
                 return mozilla::HashBytes(aFeatures.Elements(),
                                           aFeatures.Length() * sizeof(gfxFontFeature));
             }
 
             nsCOMPtr<nsIURI>       mURI;
-            nsCOMPtr<nsIPrincipal> mPrincipal;
+            nsCOMPtr<nsIPrincipal> mPrincipal; // or nullptr for data: URLs
 
             // The "real" font entry corresponding to this downloaded font.
             // The font entry MUST notify the cache when it is destroyed
             // (by calling Forget()).
             gfxFontEntry          *mFontEntry;
 
             // Whether this font was loaded from a private window.
             bool                   mPrivate;
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -5,19 +5,29 @@
 
 #include "gfxUtils.h"
 
 #include "cairo.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "gfxPlatform.h"
 #include "gfxDrawable.h"
+#include "imgIEncoder.h"
+#include "mozilla/Base64.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/DataSurfaceHelpers.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/Vector.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIClipboardHelper.h"
+#include "nsIFile.h"
+#include "nsIPresShell.h"
+#include "nsPresContext.h"
 #include "nsRegion.h"
+#include "nsServiceManagerUtils.h"
 #include "yuv_convert.h"
 #include "ycbcr_to_rgb565.h"
 #include "GeckoProfiler.h"
 #include "ImageContainer.h"
 #include "gfx2DGlue.h"
 #include "gfxPrefs.h"
 
 #ifdef XP_WIN
@@ -1100,93 +1110,268 @@ gfxUtils::GetColorForFrameNumber(uint64_
         colors[i++] = gfx::Color::FromABGR(0xff999999);
         MOZ_ASSERT(i == sNumFrameColors);
         initialized = true;
     }
 
     return colors[aFrameNumber % sNumFrameColors];
 }
 
-#ifdef MOZ_DUMP_PAINTING
-/* static */ void
-gfxUtils::WriteAsPNG(DrawTarget* aDT, const char* aFile)
+/* static */ nsresult
+gfxUtils::EncodeSourceSurface(SourceSurface* aSurface,
+                              const nsACString& aMimeType,
+                              const nsAString& aOutputOptions,
+                              BinaryOrData aBinaryOrData,
+                              FILE* aFile)
 {
-  aDT->Flush();
-  nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(aDT);
-  if (surf) {
-    surf->WriteAsPNG(aFile);
+  MOZ_ASSERT(aBinaryOrData == eDataURIEncode || aFile,
+             "Copying binary encoding to clipboard not currently supported");
+
+  const IntSize size = aSurface->GetSize();
+  if (size.IsEmpty()) {
+    return NS_ERROR_INVALID_ARG;
+  }
+  const Size floatSize(size.width, size.height);
+
+  RefPtr<DataSourceSurface> dataSurface;
+  if (aSurface->GetFormat() != SurfaceFormat::B8G8R8A8) {
+    // FIXME bug 995807 (B8G8R8X8), bug 831898 (R5G6B5)
+    dataSurface =
+      CopySurfaceToDataSourceSurfaceWithFormat(aSurface,
+                                               SurfaceFormat::B8G8R8A8);
   } else {
-    NS_WARNING("Failed to get Thebes surface!");
+    dataSurface = aSurface->GetDataSurface();
+  }
+  if (!dataSurface) {
+    return NS_ERROR_FAILURE;
+  }
+
+  DataSourceSurface::MappedSurface map;
+  if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsAutoCString encoderCID(
+    NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type=") + aMimeType);
+  nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(encoderCID.get());
+  if (!encoder) {
+#ifdef DEBUG
+    int32_t w = std::min(size.width, 8);
+    int32_t h = std::min(size.height, 8);
+    printf("Could not create encoder. Top-left %dx%d pixels contain:\n", w, h);
+    for (int32_t y = 0; y < h; ++y) {
+      for (int32_t x = 0; x < w; ++x) {
+        printf("%x ", reinterpret_cast<uint32_t*>(map.mData)[y*map.mStride+x]);
+      }
+    }
+#endif
+    dataSurface->Unmap();
+    return NS_ERROR_FAILURE;
+  }
+
+  nsresult rv = encoder->InitFromData(map.mData,
+                                      BufferSizeFromStrideAndHeight(map.mStride, size.height),
+                                      size.width,
+                                      size.height,
+                                      map.mStride,
+                                      imgIEncoder::INPUT_FORMAT_HOSTARGB,
+                                      aOutputOptions);
+  dataSurface->Unmap();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIInputStream> imgStream;
+  CallQueryInterface(encoder.get(), getter_AddRefs(imgStream));
+  if (!imgStream) {
+    return NS_ERROR_FAILURE;
   }
+
+  uint64_t bufSize64;
+  rv = imgStream->Available(&bufSize64);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  NS_ENSURE_TRUE(bufSize64 < UINT32_MAX - 16, NS_ERROR_FAILURE);
+
+  uint32_t bufSize = (uint32_t)bufSize64;
+
+  // ...leave a little extra room so we can call read again and make sure we
+  // got everything. 16 bytes for better padding (maybe)
+  bufSize += 16;
+  uint32_t imgSize = 0;
+  Vector<char> imgData;
+  if (!imgData.initCapacity(bufSize)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  uint32_t numReadThisTime = 0;
+  while ((rv = imgStream->Read(imgData.begin() + imgSize,
+                               bufSize - imgSize,
+                               &numReadThisTime)) == NS_OK && numReadThisTime > 0)
+  {
+    imgSize += numReadThisTime;
+    if (imgSize == bufSize) {
+      // need a bigger buffer, just double
+      bufSize *= 2;
+      if (!imgData.resizeUninitialized(bufSize)) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+    }
+  }
+
+  if (aBinaryOrData == eBinaryEncode) {
+    if (aFile) {
+      fwrite(imgData.begin(), 1, imgSize, aFile);
+    }
+    return NS_OK;
+  }
+
+  // base 64, result will be null-terminated
+  nsCString encodedImg;
+  rv = Base64Encode(Substring(imgData.begin(), imgSize), encodedImg);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCString string("data:");
+  string.Append(aMimeType);
+  string.Append(";base64,");
+  string.Append(encodedImg);
+
+  if (aFile) {
+#ifdef ANDROID
+    if (aFile == stdout || aFile == stderr) {
+      // ADB logcat cuts off long strings so we will break it down
+      const char* cStr = string.BeginReading();
+      size_t len = strlen(cStr);
+      while (true) {
+        printf_stderr("IMG: %.140s\n", cStr);
+        if (len <= 140)
+          break;
+        len -= 140;
+        cStr += 140;
+      }
+    }
+#endif
+    fprintf(aFile, "%s", string.BeginReading());
+  } else {
+    nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
+    if (clipboard) {
+      clipboard->CopyString(NS_ConvertASCIItoUTF16(string), nullptr);
+    }
+  }
+  return NS_OK;
 }
 
 /* static */ void
-gfxUtils::DumpAsDataURL(DrawTarget* aDT)
+gfxUtils::WriteAsPNG(SourceSurface* aSurface, const nsAString& aFile)
 {
-  aDT->Flush();
-  nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(aDT);
-  if (surf) {
-    surf->DumpAsDataURL();
-  } else {
-    NS_WARNING("Failed to get Thebes surface!");
-  }
+  WriteAsPNG(aSurface, NS_ConvertUTF16toUTF8(aFile).get());
 }
 
 /* static */ void
-gfxUtils::CopyAsDataURL(DrawTarget* aDT)
+gfxUtils::WriteAsPNG(SourceSurface* aSurface, const char* aFile)
 {
-  aDT->Flush();
-  nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(aDT);
-  if (surf) {
-    surf->CopyAsDataURL();
+  FILE* file = fopen(aFile, "wb");
+
+  if (!file) {
+    // Maybe the directory doesn't exist; try creating it, then fopen again.
+    nsresult rv = NS_ERROR_FAILURE;
+    nsCOMPtr<nsIFile> comFile = do_CreateInstance("@mozilla.org/file/local;1");
+    if (comFile) {
+      NS_ConvertUTF8toUTF16 utf16path((nsDependentCString(aFile)));
+      rv = comFile->InitWithPath(utf16path);
+      if (NS_SUCCEEDED(rv)) {
+        nsCOMPtr<nsIFile> dirPath;
+        comFile->GetParent(getter_AddRefs(dirPath));
+        if (dirPath) {
+          rv = dirPath->Create(nsIFile::DIRECTORY_TYPE, 0777);
+          if (NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_ALREADY_EXISTS) {
+            file = fopen(aFile, "wb");
+          }
+        }
+      }
+    }
+    if (!file) {
+      NS_WARNING("Failed to open file to create PNG!\n");
+      return;
+    }
+  }
+
+  EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
+                      EmptyString(), eBinaryEncode, file);
+  fclose(file);
+}
+
+/* static */ void
+gfxUtils::WriteAsPNG(DrawTarget* aDT, const nsAString& aFile)
+{
+  WriteAsPNG(aDT, NS_ConvertUTF16toUTF8(aFile).get());
+}
+
+/* static */ void
+gfxUtils::WriteAsPNG(DrawTarget* aDT, const char* aFile)
+{
+  RefPtr<SourceSurface> surface = aDT->Snapshot();
+  if (surface) {
+    WriteAsPNG(surface, aFile);
   } else {
-    NS_WARNING("Failed to get Thebes surface!");
+    NS_WARNING("Failed to get surface!");
   }
 }
 
 /* static */ void
-gfxUtils::WriteAsPNG(gfx::SourceSurface* aSourceSurface, const char* aFile)
+gfxUtils::WriteAsPNG(nsIPresShell* aShell, const char* aFile)
 {
-  RefPtr<gfx::DataSourceSurface> dataSurface = aSourceSurface->GetDataSurface();
-  RefPtr<gfx::DrawTarget> dt
-            = gfxPlatform::GetPlatform()
-                ->CreateDrawTargetForData(dataSurface->GetData(),
-                                          dataSurface->GetSize(),
-                                          dataSurface->Stride(),
-                                          aSourceSurface->GetFormat());
-  gfxUtils::WriteAsPNG(dt.get(), aFile);
+  int32_t width = 1000, height = 1000;
+  nsRect r(0, 0, aShell->GetPresContext()->DevPixelsToAppUnits(width),
+           aShell->GetPresContext()->DevPixelsToAppUnits(height));
+
+  RefPtr<mozilla::gfx::DrawTarget> dt = gfxPlatform::GetPlatform()->
+    CreateOffscreenContentDrawTarget(IntSize(width, height),
+                                     SurfaceFormat::B8G8R8A8);
+  NS_ENSURE_TRUE(dt, /*void*/);
+
+  nsRefPtr<gfxContext> context = new gfxContext(dt);
+  aShell->RenderDocument(r, 0, NS_RGB(255, 255, 0), context);
+  WriteAsPNG(dt.get(), aFile);
+}
+
+/* static */ void
+gfxUtils::DumpAsDataURI(SourceSurface* aSurface, FILE* aFile)
+{
+  EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
+                      EmptyString(), eDataURIEncode, aFile);
 }
 
 /* static */ void
-gfxUtils::DumpAsDataURL(gfx::SourceSurface* aSourceSurface)
+gfxUtils::DumpAsDataURI(DrawTarget* aDT, FILE* aFile)
 {
-  RefPtr<gfx::DataSourceSurface> dataSurface = aSourceSurface->GetDataSurface();
-  RefPtr<gfx::DrawTarget> dt
-            = gfxPlatform::GetPlatform()
-                ->CreateDrawTargetForData(dataSurface->GetData(),
-                                          dataSurface->GetSize(),
-                                          dataSurface->Stride(),
-                                          aSourceSurface->GetFormat());
-  gfxUtils::DumpAsDataURL(dt.get());
+  RefPtr<SourceSurface> surface = aDT->Snapshot();
+  if (surface) {
+    DumpAsDataURI(surface, aFile);
+  } else {
+    NS_WARNING("Failed to get surface!");
+  }
 }
 
 /* static */ void
-gfxUtils::CopyAsDataURL(gfx::SourceSurface* aSourceSurface)
+gfxUtils::CopyAsDataURI(SourceSurface* aSurface)
 {
-  RefPtr<gfx::DataSourceSurface> dataSurface = aSourceSurface->GetDataSurface();
-  RefPtr<gfx::DrawTarget> dt
-            = gfxPlatform::GetPlatform()
-                ->CreateDrawTargetForData(dataSurface->GetData(),
-                                          dataSurface->GetSize(),
-                                          dataSurface->Stride(),
-                                          aSourceSurface->GetFormat());
-
-  gfxUtils::CopyAsDataURL(dt.get());
+  EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
+                      EmptyString(), eDataURIEncode, nullptr);
 }
 
+/* static */ void
+gfxUtils::CopyAsDataURI(DrawTarget* aDT)
+{
+  RefPtr<SourceSurface> surface = aDT->Snapshot();
+  if (surface) {
+    CopyAsDataURI(surface);
+  } else {
+    NS_WARNING("Failed to get surface!");
+  }
+}
+
+#ifdef MOZ_DUMP_PAINTING
 static bool sDumpPaintList = getenv("MOZ_DUMP_PAINT_LIST") != 0;
 
 /* static */ bool
 gfxUtils::DumpPaintList() {
   return sDumpPaintList || gfxPrefs::LayoutDumpDisplayList();
 }
 
 bool gfxUtils::sDumpPainting = getenv("MOZ_DUMP_PAINT") != 0;
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -11,27 +11,30 @@
 #include "imgIContainer.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/RefPtr.h"
 #include "nsPrintfCString.h"
 
 class gfxASurface;
 class gfxDrawable;
 class nsIntRegion;
+class nsIPresShell;
+
 struct nsIntRect;
 
 namespace mozilla {
 namespace layers {
 struct PlanarYCbCrData;
 }
 }
 
 class gfxUtils {
 public:
     typedef mozilla::gfx::DataSourceSurface DataSourceSurface;
+    typedef mozilla::gfx::DrawTarget DrawTarget;
     typedef mozilla::gfx::IntPoint IntPoint;
     typedef mozilla::gfx::Matrix Matrix;
     typedef mozilla::gfx::SourceSurface SourceSurface;
     typedef mozilla::gfx::SurfaceFormat SurfaceFormat;
 
     /*
      * Premultiply or Unpremultiply aSourceSurface, writing the result
      * to aDestSurface or back into aSourceSurface if aDestSurface is null.
@@ -223,55 +226,88 @@ public:
     /**
      * Return a color that can be used to identify a frame with a given frame number.
      * The colors will cycle after sNumFrameColors.  You can query colors 0 .. sNumFrameColors-1
      * to get all the colors back.
      */
     static const mozilla::gfx::Color& GetColorForFrameNumber(uint64_t aFrameNumber);
     static const uint32_t sNumFrameColors;
 
-#ifdef MOZ_DUMP_PAINTING
-    /**
-     * Writes a binary PNG file.
-     */
-    static void WriteAsPNG(mozilla::gfx::DrawTarget* aDT, const char* aFile);
+
+    enum BinaryOrData {
+        eBinaryEncode,
+        eDataURIEncode
+    };
 
     /**
-     * Write as a PNG encoded Data URL to stdout.
+     * Encodes the given surface to PNG/JPEG/BMP/etc. using imgIEncoder.
+     *
+     * @param aMimeType The MIME-type of the image type that the surface is to
+     *   be encoded to. Used to create an appropriate imgIEncoder instance to
+     *   do the encoding.
+     *
+     * @param aOutputOptions Passed directly to imgIEncoder::InitFromData as
+     *   the value of the |outputOptions| parameter. Callers are responsible
+     *   for making sure that this is a sane value for the passed MIME-type
+     *   (i.e. for the type of encoder that will be created).
+     *
+     * @aBinaryOrData Flag used to determine if the surface is simply encoded
+     *   to the requested binary image format, or if the binary image is
+     *   further converted to base-64 and written out as a 'data:' URI.
+     *
+     * @aFile If specified, the encoded data is written out to aFile, otherwise
+     *   it is copied to the clipboard.
+     *
+     * TODO: Copying to the clipboard as a binary file is not currently
+     * supported.
      */
-    static void DumpAsDataURL(mozilla::gfx::DrawTarget* aDT);
+    static nsresult
+    EncodeSourceSurface(SourceSurface* aSurface,
+                        const nsACString& aMimeType,
+                        const nsAString& aOutputOptions,
+                        BinaryOrData aBinaryOrData,
+                        FILE* aFile);
 
     /**
-     * Copy a PNG encoded Data URL to the clipboard.
+     * Write as a PNG file to the path aFile.
+     */
+    static void WriteAsPNG(SourceSurface* aSurface, const nsAString& aFile);
+    static void WriteAsPNG(SourceSurface* aSurface, const char* aFile);
+    static void WriteAsPNG(DrawTarget* aDT, const nsAString& aFile);
+    static void WriteAsPNG(DrawTarget* aDT, const char* aFile);
+    static void WriteAsPNG(nsIPresShell* aShell, const char* aFile);
+
+    /**
+     * Dump as a PNG encoded Data URL to a FILE stream (using stdout by
+     * default).
+     *
+     * Rather than giving aFile a default argument we have separate functions
+     * to make them easier to use from a debugger.
      */
-    static void CopyAsDataURL(mozilla::gfx::DrawTarget* aDT);
+    static void DumpAsDataURI(SourceSurface* aSourceSurface, FILE* aFile);
+    static inline void DumpAsDataURI(SourceSurface* aSourceSurface) {
+        DumpAsDataURI(aSourceSurface, stdout);
+    }
+    static void DumpAsDataURI(DrawTarget* aDT, FILE* aFile);
+    static inline void DumpAsDataURI(DrawTarget* aDT) {
+        DumpAsDataURI(aDT, stdout);
+    }
 
+    /**
+     * Copy to the clipboard as a PNG encoded Data URL.
+     */
+    static void CopyAsDataURI(SourceSurface* aSourceSurface);
+    static void CopyAsDataURI(DrawTarget* aDT);
+
+#ifdef MOZ_DUMP_PAINTING
     static bool DumpPaintList();
 
     static bool sDumpPainting;
     static bool sDumpPaintingToFile;
     static FILE* sDumpPaintFile;
-
-    /**
-     * Writes a binary PNG file.
-     * Expensive. Creates a DataSourceSurface, then a DrawTarget, then passes to DrawTarget overloads
-     */
-    static void WriteAsPNG(mozilla::gfx::SourceSurface* aSourceSurface, const char* aFile);
-
-    /**
-     * Write as a PNG encoded Data URL to stdout.
-     * Expensive. Creates a DataSourceSurface, then a DrawTarget, then passes to DrawTarget overloads
-     */
-    static void DumpAsDataURL(mozilla::gfx::SourceSurface* aSourceSurface);
-
-    /**
-     * Copy a PNG encoded Data URL to the clipboard.
-     * Expensive. Creates a DataSourceSurface, then a DrawTarget, then passes to DrawTarget overloads
-     */
-    static void CopyAsDataURL(mozilla::gfx::SourceSurface* aSourceSurface);
 #endif
 };
 
 namespace mozilla {
 namespace gfx {
 
 
 /* These techniques are suggested by "Bit Twiddling Hacks"
deleted file mode 100644
--- a/js/jsd/README
+++ /dev/null
@@ -1,6 +0,0 @@
-js/jsd contains code for debugging support for the C-based JavaScript engine 
-in js/src.  jsd_xpc.cpp provides an XPCOM binding for the library.
-
-js/jsd/jsdb is a console debugger using only native code (see README in that 
-directory.)  This debugger is no longer being actively developed, though it
-should work.
deleted file mode 100644
--- a/js/jsd/idl/jsdIDebuggerService.idl
+++ /dev/null
@@ -1,1233 +0,0 @@
-/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-    
-#include "nsISupports.idl"
-
-%{ C++
-#include "jsdebug.h"
-#include "nsAString.h"
-%}
-    
-[ptr] native JSDContext(JSDContext);
-[ptr] native JSDObject(JSDObject);
-[ptr] native JSDProperty(JSDProperty);
-[ptr] native JSDScript(JSDScript);
-[ptr] native JSDStackFrameInfo(JSDStackFrameInfo);
-[ptr] native JSDThreadState(JSDThreadState);
-[ptr] native JSDValue(JSDValue);
-[ptr] native JSRuntime(JSRuntime);
-[ptr] native JSContext(JSContext);
-[ptr] native JSCompartment(JSCompartment);
-
-/* interfaces we declare in this file */
-interface jsdIDebuggerService;
-interface jsdIFilter;
-interface jsdINestCallback;
-interface jsdIFilterEnumerator;
-interface jsdIContextEnumerator;
-interface jsdIScriptEnumerator;
-interface jsdIScriptHook;
-interface jsdIErrorHook;
-interface jsdIExecutionHook;
-interface jsdICallHook;
-interface jsdIEphemeral;
-interface jsdIContext;
-interface jsdIStackFrame;
-interface jsdIScript;
-interface jsdIValue;
-interface jsdIObject;
-interface jsdIProperty;
-interface jsdIActivationCallback;
-
-/**
- * Debugger service. It is not a good idea to have more than one active client
- * of the debugger service.
- *
- * Note that all the APIs in this file are deprecated. All consumers of
- * these interfaces should switch to using the new Debugger API, documented
- * here: https://wiki.mozilla.org/Debugger
- */
-[scriptable, uuid(39609752-2d73-4019-a324-a374dee16d3c)]
-interface jsdIDebuggerService : nsISupports
-{
-    /** Internal use only. */
-    [noscript] readonly attribute JSDContext        JSDContext;
-
-    /**
-     * Called when an error or warning occurs.
-     */
-    attribute jsdIErrorHook     errorHook;
-    /**
-     * Called when a jsdIScript is created or destroyed.
-     */
-    attribute jsdIScriptHook    scriptHook;
-    /**
-     * Called when the engine encounters a breakpoint.
-     */
-    attribute jsdIExecutionHook breakpointHook;
-    /**
-     * Called when the engine encounters the debugger keyword.
-     */
-    attribute jsdIExecutionHook debuggerHook;
-    /**
-     * Called when the errorHook returns false.
-     */
-    attribute jsdIExecutionHook debugHook;
-    /**
-     * Called before the next PC is executed.
-     */
-    attribute jsdIExecutionHook interruptHook;
-    /**
-     * Called when an exception is thrown (even if it will be caught.)
-     */
-    attribute jsdIExecutionHook throwHook;
-    /**
-     * Called before and after a toplevel script is evaluated.
-     */
-    attribute jsdICallHook      topLevelHook;
-    /**
-     * Called before and after a function is called.
-     */
-    attribute jsdICallHook      functionHook;
-
-    /**
-     * Link native frames in call stacks.
-     */
-    const unsigned long ENABLE_NATIVE_FRAMES     = 0x01;
-    /**
-     * Normally, if a script has a 0 in JSD_SCRIPT_PROFILE_BIT it is included in
-     * profile data, otherwise it is not profiled. Setting the
-     * PROFILE_WHEN_SET flag reverses this convention.
-     */
-    const unsigned long PROFILE_WHEN_SET         = 0x02;
-    /**
-     * Normally, when the script in the top frame of a thread state has a 1 in
-     * JSD_SCRIPT_DEBUG_BIT, the execution hook is ignored. Setting the
-     * DEBUG_WHEN_SET flag reverses this convention.
-     */
-    const unsigned long DEBUG_WHEN_SET           = 0x04;
-    /**
-     * When this flag is set the internal call hook will collect profile data.
-     */
-    const unsigned long COLLECT_PROFILE_DATA     = 0x08;
-    /**
-     * When this flag is set, stack frames that are disabled for debugging
-     * will not appear in the call stack chain.
-     */
-    const unsigned long HIDE_DISABLED_FRAMES     = 0x10;
-    /**
-     * When this flag is set, the debugger will only check the
-     * JSD_SCRIPT_DEBUG_BIT on the top (most recent) stack frame. This
-     * makes it possible to stop in an enabled frame which was called from
-     * a stack that contains a disabled frame.
-     *
-     * When this flag is *not* set, any stack that contains a disabled frame
-     * will not be debugged (the execution hook will not be invoked.)
-     *
-     * This only applies when the reason for calling the hook would have
-     * been TYPE_INTERRUPTED or TYPE_THROW. TYPE_BREAKPOINT,
-     * TYPE_DEBUG_REQUESTED, and TYPE_DEBUGGER_KEYWORD always stop, regardless
-     * of this setting, as long as the top frame is not disabled.
-     *
-     * If HIDE_DISABLED_FRAMES is set, this is effectively set as well.
-     */
-    const unsigned long MASK_TOP_FRAME_ONLY     = 0x20;
-    /**
-     * This flag has been retired, do not re-use. It previously provided a hook
-     * for object allocation.
-     */
-    const unsigned long DISABLE_OBJECT_TRACE_RETIRED = 0x40;
-
-    /**
-     * Debugger service flags.
-     */
-    attribute unsigned long flags;
-    
-    /**
-     * Major version number of implementation.
-     */
-    readonly attribute unsigned long implementationMajor;
-    /**
-     * Minor version number of implementation.
-     */
-    readonly attribute unsigned long implementationMinor;
-    /**
-     * Free form AUTF8String identifier for implementation.
-     */
-    readonly attribute AUTF8String implementationString;
-    
-    /**
-     * |true| if the debugger service has been turned on. This does not
-     * necessarily mean another app is actively using the service, as the 
-     * autostart pref may have turned the service on.
-     */
-    readonly attribute boolean isOn;
-
-
-    /**
-     * Synchronous activation of the debugger is no longer supported,
-     * and will throw an exception.
-     */
-    void on();
-
-    /**
-     * Turn on the debugger. This function should only be called from
-     * JavaScript code. The debugger will be enabled on the runtime the call is
-     * made on, as determined by nsIXPCNativeCallContext.
-     *
-     * The debugger will be activated asynchronously, because there can be no
-     * JS on the stack when code is to be re-compiled for debug mode.
-     */
-    void asyncOn(in jsdIActivationCallback callback);
-    
-    /**
-     * Called by nsIXPConnect after it's had a chance to recompile for
-     * debug mode.
-     */
-    [noscript] void activateDebugger(in JSRuntime rt);
-
-    /**
-     * Called by nsIXPConnect to deactivate debugger on setup failure.
-     */
-    [noscript] void deactivateDebugger();
-
-    /**
-     * Recompile all active scripts in the runtime for debugMode.
-     */
-    [noscript] void recompileForDebugMode(in JSContext cx, in JSCompartment comp, in boolean mode);
-
-    /**
-     * Turn the debugger off. This will invalidate all of your jsdIEphemeral
-     * derived objects, and clear all of your breakpoints.
-     */
-    void off ();
-
-    /**
-     * Peek at the current pause depth of the debugger.
-     *
-     * @return depth Number of pause() calls still waiting to be unPause()d.
-     */
-    readonly attribute unsigned long pauseDepth;
-    /**
-     * Temporarily disable the debugger. Hooks will not be called while the
-     * debugger is paused. Multiple calls to pause will increase the "pause
-     * depth", and equal number of unPause calles must be made to resume
-     * normal debugging.
-     *
-     * @return depth Number of times pause has been called since the debugger
-     *               has been unpaused.
-     */
-    unsigned long pause();
-    /**
-     * Undo a pause.  Once this is called, the debugger won't start
-     * getting execution callbacks until the stack is fully unwound so
-     * that no JS scripts are live.  There is no way to query whether
-     * there are such scripts left to unwind at a given point in time.
-     *
-     * @return depth The number of remaining pending pause calls.
-     */
-    unsigned long unPause();
-    
-    /**
-     * Force the engine to perform garbage collection.
-     */
-    void GC();
-    
-    /**
-     * Clear profile data for all scripts.
-     */
-    void clearProfileData();
-    
-    /**
-     * Adds an execution hook filter. These filters are consulted each time one
-     * of the jsdIExecutionHooks is about to be called. Filters are matched in
-     * a first in, first compared fashion. The first filter to match determines
-     * whether or not the hook is called. Use swapFilter to reorder existing
-     * filters, and removeFilter to remove them.
-     *
-     * If |filter| is already present this method throws NS_ERROR_INVALID_ARG.
-     *
-     * @param filter Object representing the filter to add.
-     * @param after  Insert |filter| after this one. Pass null to insert at
-     *               the beginning.
-     */
-    void insertFilter(in jsdIFilter filter, in jsdIFilter after);
-    /**
-     * Same as insertFilter, except always add to the end of the list.
-     */
-    void appendFilter(in jsdIFilter filter);
-    /**
-     * Remove a filter.
-     *
-     * If |filter| is not present this method throws NS_ERROR_INVALID_ARG.
-     *
-     * @param filter Object representing the filter to remove. Must be the exact
-     * object passed to addFilter, not just a new object with the same
-     * properties.
-     */
-    void removeFilter(in jsdIFilter filter);
-    /**
-     * Swap position of two filters.
-     * 
-     * If |filter_a| is not present, this method throws NS_ERROR_INVALID_ARG.
-     * If |filter_b| is not present, filter_a is replaced by filter_b.
-     * If |filter_a| == |filter_b|, then filter is refreshed.
-     */
-    void swapFilters(in jsdIFilter filter_a, in jsdIFilter filter_b);
-    /**
-     * Enumerate registered filters. This routine refreshes each filter before
-     * passing them on to the enumeration function. Calling this with a null
-     * |enumerator| is equivalent to jsdIService::refreshFilters.
-     *
-     * @param enumerator jsdIFilterEnumerator instance to be called back for the
-     *                   enumeration.
-     */
-    void enumerateFilters(in jsdIFilterEnumerator enumerator);
-    /**
-     * Force the debugger to resync its internal filter cache with the
-     * actual values in the jsdIFilter objects. To refresh a single filter
-     * use jsdIService::swapFilters. This method is equivalent to
-     * jsdIService::enumerateFilters with a null enumerator.
-     */
-    void refreshFilters();
-    /**
-     * Clear the list of filters.
-     */
-    void clearFilters();
-
-    /**
-     * Enumerate all known contexts.
-     */
-    void enumerateContexts(in jsdIContextEnumerator enumerator);
-    
-    /**
-     * Enumerate all scripts the debugger knows about. Any scripts created
-     * before you turned the debugger on, or after turning the debugger off
-     * will not be available unless the autostart perf is set.
-     *
-     * @param enumerator jsdIScriptEnumerator instance to be called back for
-     *                   the enumeration.
-     */
-    void enumerateScripts(in jsdIScriptEnumerator enumerator);
-    /**
-     * Clear all breakpoints in all scripts.
-     */
-    void clearAllBreakpoints();
-
-    /**
-     * When called from JavaScript, this method returns the jsdIValue wrapper
-     * for the given value. If a wrapper does not exist one will be created.
-     * When called from another language this method returns an xpconnect
-     * defined error code.
-     */
-    jsdIValue wrapValue(in jsval value);
-
-    /* XXX these two routines are candidates for refactoring. The only problem
-     * is that it is not clear where and how they should land.
-     */
-
-    /**
-     * Push a new network queue, and enter a new UI event loop.
-     * @param callback jsdINestCallback instance to be called back after the
-     *                 network queue has been pushed, but before the
-     *                 UI loop starts.
-     * @return depth returns the current number of times the event loop has been
-     *               nested. your code can use it for sanity checks.
-     */
-    unsigned long enterNestedEventLoop(in jsdINestCallback callback);
-    /**
-     * Exit the current nested event loop after the current iteration completes,
-     * and pop the network event queue.
-     *
-     * @return depth returns the current number of times the event loop has been
-     *               nested. your code can use it for sanity checks.
-     */
-    unsigned long exitNestedEventLoop();
-
-    /**
-     * Output dump of JS heap.
-     *
-     * @param fileName Filename to dump the heap into.
-     */
-    void dumpHeap(in AUTF8String fileName);
-
-    /**
-     * Suppress console warnings about using JSD, which is a deprecated API.
-     *
-     * This applies only to the next call to asyncOn; any subsequent calls
-     * will elicit the warning, unless you call 'acknowledgeDeprecation'
-     * before each of them, too. This arrangement ensures that one add-on's
-     * acknowledgement doesn't suppress warnings for other add-ons.
-     */
-    void acknowledgeDeprecation();
-};
-
-/* callback interfaces */
-
-/**
- * Object representing a pattern of global object and/or url the debugger should
- * ignore. The debugger service itself will not modify properties of these
- * objects.
- */
-[scriptable, uuid(9ae587cd-b78c-47f0-a612-4b3a211a6a71)]
-interface jsdIFilter : nsISupports
-{
-    /**
-     * These two bytes of the flags attribute are reserved for interpretation
-     * by the jsdService implementation. You can do what you like with the
-     * remaining flags.
-     */
-    const unsigned long FLAG_RESERVED_MASK = 0xFF;
-    /**
-     * Filters without this flag set are ignored.
-     */
-    const unsigned long FLAG_ENABLED       = 0x01;
-    /**
-     * Filters with this flag set are "pass" filters, they allow matching hooks
-     * to continue. Filters without this flag block matching hooks.
-     */
-    const unsigned long FLAG_PASS          = 0x02;
-
-    /**
-     * FLAG_* values from above, OR'd together.
-     */
-    attribute unsigned long flags;
-
-    /**
-     * String representing the url pattern to be filtered. Supports limited
-     * glob matching, at the beginning and end of the pattern only. For example,
-     * "chrome://venkman*" filters all urls that start with chrome/venkman,
-     * "*.cgi" filters all cgi's, and "http://myserver/utils.js" filters only
-     * the utils.js file on "myserver". A null urlPattern matches all urls.
-     *
-     * The jsdIService caches this value internally, to if it changes you must
-     * swap the filter with itself using jsdIService::swapFilters.
-     */
-    attribute AUTF8String urlPattern;
-
-    /**
-     * Line number for the start of this filter. Line numbers are one based.
-     * Assigning a 0 to this attribute will tell the debugger to ignore the
-     * entire file.
-     */
-    attribute unsigned long startLine;
-
-    /**
-     * Line number for the end of this filter. Line numbers are one based.
-     * Assigning a 0 to this attribute will tell the debugger to ignore from
-     * |startLine| to the end of the file.
-     */
-    attribute unsigned long endLine;
-};
-
-/**
- * Notify client code that debugMode has been activated.
- */
-[scriptable, function, uuid(6da7f5fb-3a84-4abe-9e23-8b2045960732)]
-interface jsdIActivationCallback : nsISupports
-{
-    void onDebuggerActivated();
-};
-
-/**
- * Pass an instance of one of these to jsdIDebuggerService::enterNestedEventLoop.
- */
-[scriptable, function, uuid(88bea60f-9b5d-4b39-b08b-1c3a278782c6)]
-interface jsdINestCallback : nsISupports
-{
-    /**
-     * This method will be called after pre-nesting work has completed, such
-     * as pushing the js context and network event queue, but before the new
-     * event loop starts.
-     */
-    void onNest();
-};
-
-/**
- * Pass an instance of one of these to jsdIDebuggerService::enumerateFilters.
- */
-[scriptable, function, uuid(e391ba85-9379-4762-b387-558e38db730f)]
-interface jsdIFilterEnumerator : nsISupports
-{
-    /**
-     * The enumerateFilter method will be called once for every filter the
-     * debugger knows about.
-     */
-    void enumerateFilter(in jsdIFilter filter);
-};
-
-/**
- * Pass an instance of one of these to jsdIDebuggerService::enumerateScripts.
- */
-[scriptable, function, uuid(4eef60c2-9bbc-48fa-b196-646a832c6c81)]
-interface jsdIScriptEnumerator : nsISupports
-{
-    /**
-     * The enumerateScript method will be called once for every script the
-     * debugger knows about.
-     */
-    void enumerateScript(in jsdIScript script);
-};
-
-/**
- * Pass an instance of one of these to jsdIDebuggerService::enumerateContexts.
- */
-[scriptable, function, uuid(57d18286-550c-4ca9-ac33-56f12ebba91e)]
-interface jsdIContextEnumerator : nsISupports
-{
-    /**
-     * The enumerateContext method will be called once for every context
-     * currently in use.
-     */
-    void enumerateContext(in jsdIContext executionContext);
-};
-
-/**
- * Set jsdIDebuggerService::scriptHook to an instance of one of these.
- */
-[scriptable, uuid(d030d1a2-a58a-4f19-b9e3-96da4e2cdd09)]
-interface jsdIScriptHook : nsISupports
-{
-    /**
-     * Called when scripts are created.
-     */
-    void onScriptCreated(in jsdIScript script);
-    /**
-     * Called when the JavaScript engine destroys a script. The jsdIScript
-     * object passed in will already be invalidated.
-     */
-    void onScriptDestroyed(in jsdIScript script);
-};
-
-/**
- * Hook instances of this interface up to the
- * jsdIDebuggerService::functionHook and toplevelHook properties.
- */
-[scriptable, function, uuid(3eff1314-7ae3-4cf8-833b-c33c24a55633)]
-interface jsdICallHook : nsISupports
-{
-    /**
-     * TYPE_* values must be kept in sync with the JSD_HOOK_* #defines
-     * in jsdebug.h.
-     */
-
-    /**
-     * Toplevel script is starting.
-     */
-    const unsigned long TYPE_TOPLEVEL_START  = 0;
-    /**
-     * Toplevel script has completed.
-     */
-    const unsigned long TYPE_TOPLEVEL_END    = 1;
-    /**
-     * Function is being called.
-     */
-    const unsigned long TYPE_FUNCTION_CALL   = 2;
-    /**
-     * Function is returning.
-     */
-    const unsigned long TYPE_FUNCTION_RETURN = 3;
-    
-    /**
-     * Called before the JavaScript engine executes a top level script or calls
-     * a function.
-     */
-    void onCall(in jsdIStackFrame frame, in unsigned long type);
-};
-
-[scriptable, function, uuid(e6b45eee-d974-4d85-9d9e-f5a67218deb4)]
-interface jsdIErrorHook : nsISupports
-{
-    /**
-     * REPORT_* values must be kept in sync with JSREPORT_* #defines in
-     * jsapi.h
-     */
-    
-    /**
-     * Report is an error.
-     */
-    const unsigned long REPORT_ERROR     = 0x00;
-    /**
-     * Report is only a warning.
-     */
-    const unsigned long REPORT_WARNING   = 0x01;
-    /**
-     * Report represents an uncaught exception.
-     */
-    const unsigned long REPORT_EXCEPTION = 0x02;
-    /**
-     * Report is due to strict mode.
-     */
-    const unsigned long REPORT_STRICT    = 0x04;
-
-    /**
-     * Called when the JavaScript engine encounters an error. Return |true|
-     * to pass the error along, |false| to invoke the debugHook.
-     */
-    boolean onError(in AUTF8String message, in AUTF8String fileName,
-                    in unsigned long line, in unsigned long pos,
-                    in unsigned long flags, in unsigned long errnum,
-                    in jsdIValue exc);
-};
-
-/**
- * Hook instances of this interface up to the
- * jsdIDebuggerService::breakpointHook, debuggerHook, errorHook, interruptHook,
- * and throwHook properties.
- */
-[scriptable, function, uuid(3a722496-9d78-4f0a-a797-293d9e8cb8d2)]
-interface jsdIExecutionHook : nsISupports
-{
-    /**
-     * TYPE_* values must be kept in sync with JSD_HOOK_* #defines in jsdebug.h.
-     */
-
-    /**
-     * Execution stopped because we're in single step mode.
-     */
-    const unsigned long TYPE_INTERRUPTED      = 0;
-    /**
-     * Execution stopped by a trap instruction (i.e. breakoint.)
-     */
-    const unsigned long TYPE_BREAKPOINT       = 1;
-    /**
-     * Error handler returned an "invoke debugger" value.
-     */
-    const unsigned long TYPE_DEBUG_REQUESTED  = 2;
-    /**
-     * Debugger keyword encountered.
-     */
-    const unsigned long TYPE_DEBUGGER_KEYWORD = 3;
-    /**
-     * Exception was thrown.
-     */
-    const unsigned long TYPE_THROW            = 4;
-
-    /**
-     * RETURN_* values must be kept in sync with JSD_HOOK_RETURN_* #defines in
-     * jsdebug.h.
-     */
-
-    /**
-     * Indicates unrecoverable error processing the hook. This will cause
-     * the script being executed to be aborted without raising a JavaScript
-     * exception.
-     */
-    const unsigned long RETURN_HOOK_ERROR     = 0;
-    /**
-     * Continue processing normally. This is the "do nothing special" return
-     * value for all hook types *except* TYPE_THROW. Returning RETURN_CONTINUE
-     * from TYPE_THROW cause the exception to be ignored. Return
-     * RETURN_CONTINUE_THROW to continue exception processing from TYPE_THROW
-     * hooks.
-     */
-    const unsigned long RETURN_CONTINUE       = 1;
-    /**
-     * Same effect as RETURN_HOOK_ERROR.
-     */
-    const unsigned long RETURN_ABORT          = 2;
-    /**
-     * Return the value of the |val| parameter.
-     */
-    const unsigned long RETURN_RET_WITH_VAL   = 3;
-    /**
-     * Throw the value of the |val| parameter.
-     */
-    const unsigned long RETURN_THROW_WITH_VAL = 4;
-    /**
-     * Continue the current throw.
-     */
-    const unsigned long RETURN_CONTINUE_THROW = 5;
-
-    /**
-     * @param frame A jsdIStackFrame object representing the bottom stack frame.
-     * @param type  One of the jsdIExecutionHook::TYPE_ constants.
-     * @param val   in  - Current exception (if any) when this method is called.
-     *              out - If you return RETURN_THROW_WITH_VAL, value to be
-     *                    thrown.
-     *                    If you return RETURN_RET_WITH_VAL, value to return.
-     *                    All other return values, not significant.
-     * @retval      One of the jsdIExecutionHook::RETURN_* constants.
-     */
-    unsigned long onExecute(in jsdIStackFrame frame, 
-                            in unsigned long type, inout jsdIValue val);
-};
-
-/**
- * Objects which inherit this interface may go away, with (jsdIScript) or
- * without (all others) notification. These objects are generally wrappers
- * around JSD structures that go away when you call jsdService::Off().
- */
-[scriptable, uuid(46f1e23e-1dd2-11b2-9ceb-8285f2e95e69)]
-interface jsdIEphemeral : nsISupports
-{
-    /**
-     * |true| if this object is still valid. If not, many or all of the methods
-     * and/or properties of the inheritor may no longer be callable.
-     */
-    readonly attribute boolean isValid;
-    /**
-     * Mark this instance as invalid.
-     */
-    [noscript] void invalidate(); 
-};    
-
-/* handle objects */
-
-/**
- * Context object. Only context's which are also nsISupports objects can be
- * reflected by this interface.
- */
-[scriptable, uuid(3e5c934d-6863-4d81-96f5-76a3b962fc2b)]
-interface jsdIContext : jsdIEphemeral
-{
-    /* Internal use only. */
-    [noscript] readonly attribute JSContext   JSContext;
-
-    /**
-     * OPT_* values must be kept in sync with JSOPTION_* #defines in jsapi.h.
-     */
-
-    /**
-     * Strict mode is on.
-     */
-    const long OPT_STRICT      = 0x01;
-    /**
-     * Warnings reported as errors.
-     */
-    const long OPT_WERR        = 0x02;
-    /**
-     * Makes eval() use the last object on its 'obj' param's scope chain as the
-     * ECMA 'variables object'.
-     */
-    const long OPT_VAROBJFIX   = 0x04;
-    /**
-     * Private data for this object is an nsISupports object. Attempting to
-     * alter this bit will result in an NS_ERROR_ILLEGAL_VALUE.
-     */
-    const long OPT_ISUPPORTS   = 0x08;
-    /**
-     * OPT_* values above, OR'd together.
-     */
-    attribute unsigned long          options;
-
-    /**
-     * Unique tag among all valid jsdIContext objects, useful as a hash key.
-     */
-    readonly attribute unsigned long tag;
-
-    /**
-     * Private data for this context, if it is an nsISupports, |null| otherwise.
-     */
-    readonly attribute nsISupports   privateData;
-    
-    /**
-     * Retrieve the underlying context wrapped by this jsdIContext.
-     */
-    readonly attribute nsISupports   wrappedContext;
-
-    /**
-     * Top of the scope chain for this context.
-     */
-    readonly attribute jsdIValue     globalObject;
-
-    /**
-     * |true| if this context should be allowed to run scripts, |false|
-     * otherwise. This attribute is only valid for contexts which implement
-     * nsIScriptContext. Setting or getting this attribute on any other
-     * context will throw a NS_ERROR_NO_INTERFACE exception.
-     */
-    attribute boolean                scriptsEnabled;
-};
-
-/**
- * Stack frame objects. These are only valid inside the jsdIExecutionHook which
- * gave it to you. After you return from that handler the bottom frame, and any
- * frame you found attached through it, are invalidated via the jsdIEphemeral
- * interface. Once a jsdIStackFrame has been invalidated all method and
- * property accesses will throw a NS_ERROR_NOT_AVAILABLE exception.
- */
-[scriptable, uuid(7c95422c-7579-4a6f-8ef7-e5b391552ee5)]
-interface jsdIStackFrame : jsdIEphemeral
-{
-    /** Internal use only. */
-    [noscript] readonly attribute JSDContext        JSDContext;
-    /** Internal use only. */
-    [noscript] readonly attribute JSDThreadState    JSDThreadState;
-    /** Internal use only. */
-    [noscript] readonly attribute JSDStackFrameInfo JSDStackFrameInfo;
-   
-    /**
-     * True if stack frame represents a frame created as a result of a debugger
-     * evaluation.
-     */
-    readonly attribute boolean isDebugger;
-    /**
-     * True if stack frame is constructing a new object.
-     */
-    readonly attribute boolean isConstructing;
-
-    /**
-     * Link to the caller's stack frame.
-     */
-    readonly attribute jsdIStackFrame callingFrame;
-    /**
-     * Executon context.
-     */
-    readonly attribute jsdIContext    executionContext;
-    /**
-     * Function name executing in this stack frame.
-     */
-    readonly attribute AUTF8String    functionName;
-    /**
-     * Script running in this stack frame, null for native frames.
-     */
-    readonly attribute jsdIScript     script;
-    /**
-     * Current program counter in this stack frame.
-     */
-    readonly attribute unsigned long  pc;
-    /**
-     * Current line number (using the script's pc to line map.)
-     */
-    readonly attribute unsigned long  line;
-    /**
-     * Function object running in this stack frame.
-     */
-    readonly attribute jsdIValue      callee;
-    /**
-     * Top object in the scope chain.
-     */
-    readonly attribute jsdIValue      scope;
-    /**
-     * |this| object for this stack frame.
-     */
-    readonly attribute jsdIValue      thisValue;
-    /**
-     * Evaluate arbitrary JavaScript in this stack frame.
-     * @param bytes    Script to be evaluated.
-     * @param fileName Filename to compile this script under. This is the
-     *                 filename you'll see in error messages, etc.
-     * @param line     Starting line number for this script. One based.
-     * @retval         Result of evaluating the script.
-     */
-    boolean eval(in AString bytes, in AUTF8String fileName,
-                 in unsigned long line, out jsdIValue result);
-    
-};
-
-/**
- * Script object. In JavaScript engine terms, there's a single script for each
- * function, and one for the top level script.
- */
-[scriptable, uuid(8ce9b2a2-cc33-48a8-9f47-8696186ed9a5)]
-interface jsdIScript : jsdIEphemeral
-{
-    /** Internal use only. */
-    [noscript] readonly attribute JSDContext JSDContext;
-    /** Internal use only. */
-    [noscript] readonly attribute JSDScript  JSDScript;
-    
-    /**
-     * Last version set on this context.
-     * Scripts typically select this with the "language" attribute.
-     * See the VERSION_* consts on jsdIDebuggerService.
-     */
-    readonly attribute long          version;
-
-    /**
-     * Tag value guaranteed unique among jsdIScript objects. Useful as a
-     * hash key in script.
-     */
-    readonly attribute unsigned long tag;
-
-    /**
-     * FLAG_* values need to be kept in sync with JSD_SCRIPT_* #defines in
-     * jsdebug.h.
-     */
-
-    /**
-     * Determines whether or not to collect profile information for this
-     * script. The context flag FLAG_PROFILE_WHEN_SET decides the logic.
-     */
-    const unsigned long FLAG_PROFILE = 0x01;
-    /**
-     * Determines whether or not to ignore breakpoints, etc. in this script.
-     * The context flag JSD_DEBUG_WHEN_SET decides the logic.
-     */
-    const unsigned long FLAG_DEBUG   = 0x02;
-    /**
-     * Determines whether to invoke the onScriptDestroy callback for this
-     * script. The default is for this to be true if the onScriptCreated
-     * callback was invoked for this script.
-     */
-    const unsigned long FLAG_CALL_DESTROY_HOOK = 0x04;
-    
-    /**
-     * FLAG_* attributes from above, OR'd together.
-     */
-    attribute unsigned long flags;
-
-    /**
-     * Filename given for this script when it was compiled.
-     * This data is copied from the underlying structure when the jsdIScript
-     * instance is created and is therefore available even after the script is
-     * invalidated.
-     */
-    readonly attribute AUTF8String   fileName;
-    /**
-     * Function name for this script. "anonymous" for unnamed functions (or
-     * a function actually named anonymous), empty for top level scripts.
-     * This data is copied from the underlying structure when the jsdIScript
-     * instance is created and is therefore available even after the script is
-     * invalidated.
-     */
-    readonly attribute AUTF8String   functionName;
-    /**
-     * The names of the arguments for this function; empty if this is
-     * not a function.
-     */
-    void getParameterNames([optional] out unsigned long count,
-                           [array, size_is(count), retval] out wstring paramNames);
-    /**
-     * Fetch the function object as a jsdIValue.
-     */
-    readonly attribute jsdIValue     functionObject;
-    /**
-     * Source code for this script, without function declaration.
-     */
-    readonly attribute AString functionSource;
-    /**
-     * Line number in source file containing the first line of this script.
-     * This data is copied from the underlying structure when the jsdIScript
-     * instance is created and is therefore available even after the script is
-     * invalidated.
-     */
-    readonly attribute unsigned long baseLineNumber;
-    /**
-     * Total number of lines in this script.
-     * This data is copied from the underlying structure when the jsdIScript
-     * instance is created and is therefore available even after the script is
-     * invalidated.
-     */
-    readonly attribute unsigned long lineExtent;
-
-    /**
-     * Number of times this script has been called.
-     */
-    readonly attribute unsigned long callCount;
-    /**
-     * Number of times this script called itself, directly or indirectly.
-     */
-    readonly attribute unsigned long maxRecurseDepth;
-    /**
-     * Shortest execution time recorded, in milliseconds.
-     */
-    readonly attribute double minExecutionTime;
-    /**
-     * Longest execution time recorded, in milliseconds.
-     */
-    readonly attribute double maxExecutionTime;
-    /**
-     * Total time spent in this function, in milliseconds.
-     */
-    readonly attribute double totalExecutionTime;
-    /**
-     * Shortest execution time recorded, in milliseconds, excluding time spent
-     * in other called code.
-     */
-    readonly attribute double minOwnExecutionTime;
-    /**
-     * Longest execution time recorded, in milliseconds, excluding time spent
-     * in other called code.
-     */
-    readonly attribute double maxOwnExecutionTime;
-    /**
-     * Total time spent in this function, in milliseconds, excluding time spent
-     * in other called code.
-     */
-    readonly attribute double totalOwnExecutionTime;
-    
-    /**
-     * Clear profile data for this script.
-     */
-    void clearProfileData();
-    
-    const unsigned long PCMAP_SOURCETEXT  = 1; /* map to actual source text    */
-    const unsigned long PCMAP_PRETTYPRINT = 2; /* map to pretty printed source */
-
-    /**
-     * Get the closest line number to a given PC.
-     * The |pcmap| argument specifies which pc to source line map to use.
-     */
-    unsigned long pcToLine(in unsigned long pc, in unsigned long pcmap);
-    /**
-     * Get the first PC associated with a line.
-     * The |pcmap| argument specifies which pc to source line map to use.
-     */
-    unsigned long lineToPc(in unsigned long line, in unsigned long pcmap);
-    /**
-     * Determine is a particular line is executable, like checking that
-     * lineToPc == pcToLine, except in one call.
-     * The |pcmap| argument specifies which pc to source line map to use.
-     */
-    boolean isLineExecutable(in unsigned long line, in unsigned long pcmap);
-
-    /**
-     * Return a list of all executable lines in a script.
-     * |pcmap| specifies which pc to source line map to use.
-     * |startLine| and |maxLines| may be used to retrieve a chunk at a time.
-     */
-    void getExecutableLines(in unsigned long pcmap,
-                            in unsigned long startLine, in unsigned long maxLines,
-                            [optional] out unsigned long count,
-                            [array, size_is(count), retval] out unsigned long executableLines);
- 
-    /**
-     * Set a breakpoint at a PC in this script.
-     */
-    void setBreakpoint(in unsigned long pc);
-    /**
-     * Clear a breakpoint at a PC in this script.
-     */
-    void clearBreakpoint(in unsigned long pc);
-    /**
-     * Clear all breakpoints set in this script.
-     */
-    void clearAllBreakpoints();
-    /**
-     * Call interrupt hook at least once per source line
-     */
-    void enableSingleStepInterrupts(in boolean mode);
-};
-
-/**
- * Value objects. Represents typeless JavaScript values (jsval in SpiderMonkey
- * terminology.)  These are valid until the debugger is turned off. Holding a
- * jsdIValue adds a root for the underlying JavaScript value, so don't keep it
- * if you don't need to.
- */
-[scriptable, uuid(1cd3535b-4ddb-4202-9053-e0ec88f5c82b)]
-interface jsdIValue : jsdIEphemeral
-{
-    /** Internal use only. */
-    [noscript] readonly attribute JSDContext JSDContext;
-    /** Internal use only. */
-    [noscript] readonly attribute JSDValue   JSDValue;
-
-    /**
-     * |false| unless the value is a function declared in script.
-     */
-    readonly attribute boolean isNative;
-    /**
-     * |true| if the value represents a number, either double or integer.
-     * |false| for all other values, including numbers assigned as strings
-     * (eg. x = "1";)
-     */
-    readonly attribute boolean isNumber;
-    /**
-     * |true| if the value represents a JavaScript primitive number or AUTF8String
-     */
-    readonly attribute boolean isPrimitive;
-    
-    /** Value is either |true| or |false|. */
-    const unsigned long TYPE_BOOLEAN  = 0;
-    /** Value is a primitive number that is too large to fit in an integer. */
-    const unsigned long TYPE_DOUBLE   = 1;
-    /** Value is a primitive number that fits into an integer. */
-    const unsigned long TYPE_INT      = 2;
-    /** Value is a function. */
-    const unsigned long TYPE_FUNCTION = 3;
-    /** Value is |null|. */
-    const unsigned long TYPE_NULL     = 4;
-    /** Value is an object. */
-    const unsigned long TYPE_OBJECT   = 5;
-    /** Value is a primitive AUTF8String. */
-    const unsigned long TYPE_STRING   = 6;
-    /** Value is void. */
-    const unsigned long TYPE_VOID     = 7;
-    
-    /**
-     * One of the TYPE_* values above.
-     */
-    readonly attribute unsigned long jsType;
-    /**
-     * Prototype value if this value represents an object, null if the value is
-     * not an object or the object has no prototype.
-     */
-    readonly attribute jsdIValue     jsPrototype;
-    /**
-     * Parent value if this value represents an object, null if the value is not
-     * an object or the object has no parent.
-     */    
-    readonly attribute jsdIValue     jsParent;
-    /**
-     * Class name if this value represents an object. Empty AUTF8String if the value
-     * is not an object.
-     */
-    readonly attribute AUTF8String   jsClassName;
-    /**
-     * Constructor name if this value represents an object. Empty AUTF8String if the
-     * value is not an object.
-     */
-    readonly attribute jsdIValue     jsConstructor;
-    /**
-     * Function name if this value represents a function. Empty AUTF8String if the
-     * value is not a function.
-     */
-    readonly attribute AUTF8String   jsFunctionName;
-    
-    /**
-     * Value if interpreted as a boolean. Converts if necessary.
-     */
-    readonly attribute boolean       booleanValue;
-    /**
-     * Value if interpreted as a double. Converts if necessary.
-     */
-    readonly attribute double        doubleValue;
-    /**
-     * Value if interpreted as an integer. Converts if necessary.
-     */
-    readonly attribute long          intValue;
-    /**
-     * Value if interpreted as an object.
-     */
-    readonly attribute jsdIObject    objectValue;
-    /**
-     * Value if interpreted as a AUTF8String. Converts if necessary.
-     */
-    readonly attribute AUTF8String   stringValue;
-
-    /**
-     * Number of properties. 0 if the value is not an object, or the value is
-     * an object but has no properties.
-     */
-    readonly attribute long propertyCount;
-    
-    /**
-     * Retrieves all properties if this value represents an object. If this
-     * value is not an object a 0 element array is returned.
-     * @param propArray Array of jsdIProperty values for this value.
-     * @param length    Size of array.
-     */
-    void getProperties([array, size_is(length)] out jsdIProperty propArray,
-                       out unsigned long length);
-    /**
-     * Retrieves a single property from the value. Only valid if the value
-     * represents an object.
-     * @param name Name of the property to retrieve.
-     * @retval     jsdIProperty for the requested property name or null if no
-     *             property exists for the requested name.
-     */
-    jsdIProperty getProperty(in AUTF8String name);
-
-    /**
-     * jsdIValues are wrappers around JavaScript engine structures. Much of the
-     * data is copied instead of shared. The refresh method is used to resync
-     * the jsdIValue with the underlying structure.
-     */
-    void refresh();
-
-    /**
-     * When called from JavaScript, this method returns the JavaScript value
-     * wrapped by this jsdIValue. The calling script is free to use the result
-     * as it would any other JavaScript value.
-     * When called from another language this method returns an xpconnect
-     * defined error code.
-     */
-    [implicit_jscontext] jsval getWrappedValue();
-
-    /**
-     * If this is a function value, return its associated jsdIScript.
-     * Otherwise, return null.
-     */
-    readonly attribute jsdIScript script;
-};
-
-/**
- * Properties specific to values which are also objects.
- * XXX We don't add roots for these yet, so make sure you hold on to the
- * jsdIValue from whence your jsdIObject instance came for at least as long as
- * you hold the jsdIObject.
- * XXX Maybe the jsClassName, jsConstructorName, and property related attribute/
- * functions from jsdIValue should move to this interface. We could inherit from
- * jsdIValue or use interface flattening or something.
- */
-[scriptable, uuid(87d86308-7a27-4255-b23c-ce2394f02473)]
-interface jsdIObject : nsISupports
-{
-    /** Internal use only. */
-    [noscript] readonly attribute JSDContext JSDContext;
-    /** Internal use only. */
-    [noscript] readonly attribute JSDObject  JSDObject;
-
-    /**
-     * The URL (filename) that contains the script which caused this object
-     * to be created.
-     */
-    readonly attribute AUTF8String   creatorURL;
-    /**
-     * Line number in the creatorURL where this object was created.
-     */
-    readonly attribute unsigned long creatorLine;
-    /**
-     * The URL (filename) that contains the script which defined the constructor
-     * used to create this object.
-     */
-    readonly attribute AUTF8String   constructorURL;
-    /**
-     * Line number in the creatorURL where this object was created.
-     */
-    readonly attribute unsigned long constructorLine;
-    /**
-     * jsdIValue for this object.
-     */
-    readonly attribute jsdIValue     value;
-};
-
-/**
- * Representation of a property of an object. When an instance is invalid, all
- * method and property access will result in a NS_UNAVAILABLE error.
- */
-[scriptable, uuid(acf1329e-aaf6-4d6a-a1eb-f75858566f09)]
-interface jsdIProperty : jsdIEphemeral
-{
-    /** Internal use only. */
-    [noscript] readonly attribute JSDContext  JSDContext;
-    /** Internal use only. */
-    [noscript] readonly attribute JSDProperty JSDProperty;
-
-    /**
-     * FLAG_* values must be kept in sync with JSDPD_* #defines in jsdebug.h.
-     */
-
-    /** visible to for/in loop */
-    const unsigned long FLAG_ENUMERATE = 0x01;
-    /** assignment is error */    
-    const unsigned long FLAG_READONLY  = 0x02;
-    /** property cannot be deleted */
-    const unsigned long FLAG_PERMANENT = 0x04;
-    /** property has an alias id */
-    const unsigned long FLAG_ALIAS     = 0x08;
-    /** argument to function */
-    const unsigned long FLAG_ARGUMENT  = 0x10;
-    /** local variable in function */
-    const unsigned long FLAG_VARIABLE  = 0x20;
-    /** exception occurred looking up property, value is exception */
-    const unsigned long FLAG_EXCEPTION = 0x40;
-    /** native getter returned false without throwing an exception */
-    const unsigned long FLAG_ERROR     = 0x80;
-    /** found via explicit lookup (property defined elsewhere.) */
-    const unsigned long FLAG_HINTED    = 0x800;
-
-    /** FLAG_* values OR'd together, representing the flags for this property. */
-    readonly attribute unsigned long flags;
-    /** jsdIValue representing the alias for this property. */
-    readonly attribute jsdIValue     alias;
-    /** name for this property. */
-    readonly attribute jsdIValue     name;
-    /** value of this property. */
-    readonly attribute jsdIValue     value;
-};
deleted file mode 100644
--- a/js/jsd/idl/moz.build
+++ /dev/null
@@ -1,12 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-XPIDL_SOURCES += [
-    'jsdIDebuggerService.idl',
-]
-
-XPIDL_MODULE = 'jsdservice'
-
deleted file mode 100644
--- a/js/jsd/jsd.h
+++ /dev/null
@@ -1,1054 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- * Header for JavaScript Debugging support - Internal ONLY declarations
- */
-
-#ifndef jsd_h___
-#define jsd_h___
-
-/*
-* NOTE: This is a *private* header file and should only be included by
-* the sources in js/jsd. Defining EXPORT_JSD_API in an outside module
-* using jsd would be bad.
-*/
-#define EXPORT_JSD_API 1 /* if used, must be set before include of jsdebug.h */
-
-/*
-* These can be controled by the makefile, but this allows a place to set
-* the values always used in the mozilla client, but perhaps done differently
-* in other embeddings.
-*/
-#ifdef MOZILLA_CLIENT
-#define JSD_THREADSAFE 1
-/* define JSD_HAS_DANGEROUS_THREAD 1 */
-#define JSD_USE_NSPR_LOCKS 1
-#endif /* MOZILLA_CLIENT */
-
-#include "jsapi.h"
-#include "jshash.h"
-#include "jsclist.h"
-#include "jsdebug.h"
-#include "js/OldDebugAPI.h"
-#include "jsd_lock.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define JSD_MAJOR_VERSION 1
-#define JSD_MINOR_VERSION 1
-
-/***************************************************************************/
-/* handy macros */
-#undef  CHECK_BIT_FLAG
-#define CHECK_BIT_FLAG(f,b) ((f)&(b))
-#undef  SET_BIT_FLAG
-#define SET_BIT_FLAG(f,b)   ((f)|=(b))
-#undef  CLEAR_BIT_FLAG
-#define CLEAR_BIT_FLAG(f,b) ((f)&=(~(b)))
-
-#define JSD_IS_DEBUG_ENABLED(jsdc,jsdscript)                                   \
-        (!(((jsdc->flags & JSD_DEBUG_WHEN_SET) ? 1 : 0)  ^                     \
-           ((jsdscript->flags & JSD_SCRIPT_DEBUG_BIT) ?  1 : 0)))
-#define JSD_IS_PROFILE_ENABLED(jsdc,jsdscript)                                 \
-        ((jsdc->flags & JSD_COLLECT_PROFILE_DATA) &&                           \
-         (!(((jsdc->flags & JSD_PROFILE_WHEN_SET) ? 1 : 0) ^                   \
-            ((jsdscript->flags & JSD_SCRIPT_PROFILE_BIT) ? 1 : 0))))
-
-
-/***************************************************************************/
-/* These are not exposed in jsdebug.h - typedef here for consistency */
-
-typedef struct JSDExecHook          JSDExecHook;
-typedef struct JSDAtom              JSDAtom;
-typedef struct JSDProfileData       JSDProfileData;
-/***************************************************************************/
-/* Our structures */
-
-/*
-* XXX What I'm calling a JSDContext is really more of a JSDTaskState. 
-*/
-
-struct JSDContext
-{
-    JSCList                 links;      /* we are part of a JSCList */
-    bool                    inited;
-    void*                   data;
-    uint32_t                flags;
-    JSD_ScriptHookProc      scriptHook;
-    void*                   scriptHookData;
-    JSD_ExecutionHookProc   interruptHook;
-    void*                   interruptHookData;
-    JSRuntime*              jsrt;
-    JSD_ErrorReporter       errorReporter;
-    void*                   errorReporterData;
-    JSCList                 threadsStates;
-    JSD_ExecutionHookProc   debugBreakHook;
-    void*                   debugBreakHookData;
-    JSD_ExecutionHookProc   debuggerHook;
-    void*                   debuggerHookData;
-    JSD_ExecutionHookProc   throwHook;
-    void*                   throwHookData;
-    JSD_CallHookProc        functionHook;
-    void*                   functionHookData;
-    JSD_CallHookProc        toplevelHook;
-    void*                   toplevelHookData;
-    JS::Heap<JSObject*>     glob;
-    JSD_UserCallbacks       userCallbacks;
-    void*                   user;
-    JSCList                 scripts;
-    JSHashTable*            scriptsTable;
-    JSCList                 sources;
-    JSCList                 removedSources;
-    unsigned                   sourceAlterCount;
-    JSHashTable*            atoms;
-    JSCList                 objectsList;
-    JSHashTable*            objectsTable;
-    JSDProfileData*         callingFunctionPData;
-    int64_t                 lastReturnTime;
-#ifdef JSD_THREADSAFE
-    JSDStaticLock*          scriptsLock;
-    JSDStaticLock*          sourceTextLock;
-    JSDStaticLock*          objectsLock;
-    JSDStaticLock*          atomsLock;
-    JSDStaticLock*          threadStatesLock;
-#endif /* JSD_THREADSAFE */
-#ifdef JSD_HAS_DANGEROUS_THREAD
-    void*                   dangerousThread;
-#endif /* JSD_HAS_DANGEROUS_THREAD */
-
-};
-
-struct JSDScript
-{
-    JSCList     links;      /* we are part of a JSCList */
-    JSDContext* jsdc;       /* JSDContext for this jsdscript */
-    JSScript*   script;     /* script we are wrapping */
-    unsigned       lineBase;   /* we cache this */
-    unsigned       lineExtent; /* we cache this */
-    JSCList     hooks;      /* JSCList of JSDExecHooks for this script */
-    char*       url;
-    uint32_t    flags;
-    void*       data;
-
-    JSDProfileData  *profileData;
-};
-
-struct JSDProfileData
-{
-    JSDProfileData* caller;
-    int64_t  lastCallStart;
-    int64_t  runningTime;
-    unsigned    callCount;
-    unsigned    recurseDepth;
-    unsigned    maxRecurseDepth;
-    double minExecutionTime;
-    double maxExecutionTime;
-    double totalExecutionTime;
-    double minOwnExecutionTime;
-    double maxOwnExecutionTime;
-    double totalOwnExecutionTime;
-};
-
-struct JSDSourceText
-{
-    JSCList          links;      /* we are part of a JSCList */
-    char*            url;
-    char*            text;
-    unsigned         textLength;
-    unsigned         textSpace;
-    bool             dirty;
-    JSDSourceStatus  status;
-    unsigned         alterCount;
-    bool             doingEval;
-};
-
-struct JSDExecHook
-{
-    JSCList               links;        /* we are part of a JSCList */
-    JSDScript*            jsdscript;
-    uintptr_t             pc;
-    JSD_ExecutionHookProc hook;
-    void*                 callerdata;
-};
-
-#define TS_HAS_DISABLED_FRAME 0x01
-
-struct JSDThreadState
-{
-    JSCList             links;        /* we are part of a JSCList */
-    JSContext*          context;
-    void*               thread;
-    JSCList             stack;
-    unsigned               stackDepth;
-    unsigned               flags;
-};
-
-struct JSDStackFrameInfo
-{
-    JSCList             links;        /* we are part of a JSCList */
-    JSDThreadState*     jsdthreadstate;
-    JSDScript*          jsdscript;
-    uintptr_t           pc;
-    bool                isConstructing;
-    JSAbstractFramePtr  frame;
-};
-
-#define GOT_PROTO   ((short) (1 << 0))
-#define GOT_PROPS   ((short) (1 << 1))
-#define GOT_PARENT  ((short) (1 << 2))
-#define GOT_CTOR    ((short) (1 << 3))
-
-struct JSDValue
-{
-    JS::Heap<JS::Value> val;
-    int                 nref;
-    JSCList             props;
-    JS::Heap<JSString*> string;
-    JS::Heap<JSString*> funName;
-    const char*         className;
-    JSDValue*           proto;
-    JSDValue*           parent;
-    JSDValue*           ctor;
-    unsigned            flags;
-};
-
-struct JSDProperty
-{
-    JSCList     links;      /* we are part of a JSCList */
-    int        nref;
-    JSDValue*   val;
-    JSDValue*   name;
-    JSDValue*   alias;
-    unsigned       flags;
-};
-
-struct JSDAtom
-{
-    char* str;      /* must be first element in struct for compare */
-    int  refcount;
-};
-
-struct JSDObject
-{
-    JSCList     links;      /* we are part of a JSCList */
-    JSObject*   obj;
-    JSDAtom*    newURL;
-    unsigned       newLineno;
-    JSDAtom*    ctorURL;
-    unsigned       ctorLineno;
-    JSDAtom*    ctorName;
-};
-
-/***************************************************************************/
-/* Code validation support */
-
-#ifdef DEBUG
-extern void JSD_ASSERT_VALID_CONTEXT(JSDContext* jsdc);
-extern void JSD_ASSERT_VALID_SCRIPT(JSDScript* jsdscript);
-extern void JSD_ASSERT_VALID_SOURCE_TEXT(JSDSourceText* jsdsrc);
-extern void JSD_ASSERT_VALID_THREAD_STATE(JSDThreadState* jsdthreadstate);
-extern void JSD_ASSERT_VALID_STACK_FRAME(JSDStackFrameInfo* jsdframe);
-extern void JSD_ASSERT_VALID_EXEC_HOOK(JSDExecHook* jsdhook);
-extern void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval);
-extern void JSD_ASSERT_VALID_PROPERTY(JSDProperty* jsdprop);
-extern void JSD_ASSERT_VALID_OBJECT(JSDObject* jsdobj);
-#else
-#define JSD_ASSERT_VALID_CONTEXT(x)     ((void)0)
-#define JSD_ASSERT_VALID_SCRIPT(x)      ((void)0)
-#define JSD_ASSERT_VALID_SOURCE_TEXT(x) ((void)0)
-#define JSD_ASSERT_VALID_THREAD_STATE(x)((void)0)
-#define JSD_ASSERT_VALID_STACK_FRAME(x) ((void)0)
-#define JSD_ASSERT_VALID_EXEC_HOOK(x)   ((void)0)
-#define JSD_ASSERT_VALID_VALUE(x)       ((void)0)
-#define JSD_ASSERT_VALID_PROPERTY(x)    ((void)0)
-#define JSD_ASSERT_VALID_OBJECT(x)      ((void)0)
-#endif
-
-/***************************************************************************/
-/* higher level functions */
-
-extern JSDContext*
-jsd_DebuggerOnForUser(JSRuntime*         jsrt,
-                      JSD_UserCallbacks* callbacks,
-                      void*              user,
-                      JSObject*          scopeobj);
-
-extern JSDContext*
-jsd_DebuggerOn(void);
-
-extern void
-jsd_DebuggerOff(JSDContext* jsdc);
-
-extern void
-jsd_DebuggerPause(JSDContext* jsdc, bool forceAllHooksOff);
-
-extern void
-jsd_DebuggerUnpause(JSDContext* jsdc);
-
-extern void
-jsd_SetUserCallbacks(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user);
-
-extern JSDContext*
-jsd_JSDContextForJSContext(JSContext* context);
-
-extern void*
-jsd_SetContextPrivate(JSDContext* jsdc, void *data);
-
-extern void*
-jsd_GetContextPrivate(JSDContext* jsdc);
-
-extern void
-jsd_ClearAllProfileData(JSDContext* jsdc);
-
-extern bool
-jsd_SetErrorReporter(JSDContext*       jsdc,
-                     JSD_ErrorReporter reporter,
-                     void*             callerdata);
-
-extern bool
-jsd_GetErrorReporter(JSDContext*        jsdc,
-                     JSD_ErrorReporter* reporter,
-                     void**             callerdata);
-
-/***************************************************************************/
-/* Script functions */
-
-extern bool
-jsd_InitScriptManager(JSDContext *jsdc);
-
-extern void
-jsd_DestroyScriptManager(JSDContext* jsdc);
-
-extern JSDScript*
-jsd_FindJSDScript(JSDContext*  jsdc,
-                  JSScript     *script);
-
-extern JSDScript*
-jsd_FindOrCreateJSDScript(JSDContext    *jsdc,
-                          JSContext     *cx,
-                          JSScript      *script,
-                          JSAbstractFramePtr frame);
-
-extern JSDProfileData*
-jsd_GetScriptProfileData(JSDContext* jsdc, JSDScript *script);
-
-extern uint32_t
-jsd_GetScriptFlags(JSDContext *jsdc, JSDScript *script);
-
-extern void
-jsd_SetScriptFlags(JSDContext *jsdc, JSDScript *script, uint32_t flags);
-
-extern unsigned
-jsd_GetScriptCallCount(JSDContext* jsdc, JSDScript *script);
-
-extern  unsigned
-jsd_GetScriptMaxRecurseDepth(JSDContext* jsdc, JSDScript *script);
-
-extern double
-jsd_GetScriptMinExecutionTime(JSDContext* jsdc, JSDScript *script);
-
-extern double
-jsd_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script);
-
-extern double
-jsd_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script);
-
-extern double
-jsd_GetScriptMinOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
-
-extern double
-jsd_GetScriptMaxOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
-
-extern double
-jsd_GetScriptTotalOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
-
-extern void
-jsd_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script);
-
-extern JSScript *
-jsd_GetJSScript (JSDContext *jsdc, JSDScript *script);
-
-extern JSFunction *
-jsd_GetJSFunction (JSDContext *jsdc, JSDScript *script);
-
-extern JSDScript*
-jsd_IterateScripts(JSDContext* jsdc, JSDScript **iterp);
-
-extern void *
-jsd_SetScriptPrivate (JSDScript *jsdscript, void *data);
-
-extern void *
-jsd_GetScriptPrivate (JSDScript *jsdscript);
-
-extern bool
-jsd_IsActiveScript(JSDContext* jsdc, JSDScript *jsdscript);
-
-extern const char*
-jsd_GetScriptFilename(JSDContext* jsdc, JSDScript *jsdscript);
-
-extern JSString*
-jsd_GetScriptFunctionId(JSDContext* jsdc, JSDScript *jsdscript);
-
-extern unsigned
-jsd_GetScriptBaseLineNumber(JSDContext* jsdc, JSDScript *jsdscript);
-
-extern unsigned
-jsd_GetScriptLineExtent(JSDContext* jsdc, JSDScript *jsdscript);
-
-extern bool
-jsd_SetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc hook, void* callerdata);
-
-extern bool
-jsd_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata);
-
-extern uintptr_t
-jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, unsigned line);
-
-extern unsigned
-jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, uintptr_t pc);
-
-extern bool
-jsd_GetLinePCs(JSDContext* jsdc, JSDScript* jsdscript,
-               unsigned startLine, unsigned maxLines,
-               unsigned* count, unsigned** lines, uintptr_t** pcs);
-
-extern void
-jsd_NewScriptHookProc(
-                JSContext   *cx,
-                const char  *filename,      /* URL this script loads from */
-                unsigned       lineno,         /* line where this script starts */
-                JSScript    *script,
-                JSFunction  *fun,
-                void*       callerdata);
-
-extern void
-jsd_DestroyScriptHookProc(
-                JSFreeOp    *fop,
-                JSScript    *script,
-                void*       callerdata);
-
-/* Script execution hook functions */
-
-extern bool
-jsd_SetExecutionHook(JSDContext*           jsdc,
-                     JSDScript*            jsdscript,
-                     uintptr_t             pc,
-                     JSD_ExecutionHookProc hook,
-                     void*                 callerdata);
-
-extern bool
-jsd_ClearExecutionHook(JSDContext*           jsdc,
-                       JSDScript*            jsdscript,
-                       uintptr_t             pc);
-
-extern bool
-jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript);
-
-extern bool
-jsd_ClearAllExecutionHooks(JSDContext* jsdc);
-
-extern void
-jsd_ScriptCreated(JSDContext* jsdc,
-                  JSContext   *cx,
-                  const char  *filename,    /* URL this script loads from */
-                  unsigned       lineno,       /* line where this script starts */
-                  JSScript    *script,
-                  JSFunction  *fun);
-
-extern void
-jsd_ScriptDestroyed(JSDContext* jsdc,
-                    JSFreeOp    *fop,
-                    JSScript    *script);
-
-/***************************************************************************/
-/* Source Text functions */
-
-extern JSDSourceText*
-jsd_IterateSources(JSDContext* jsdc, JSDSourceText **iterp);
-
-extern JSDSourceText*
-jsd_FindSourceForURL(JSDContext* jsdc, const char* url);
-
-extern const char*
-jsd_GetSourceURL(JSDContext* jsdc, JSDSourceText* jsdsrc);
-
-extern bool
-jsd_GetSourceText(JSDContext* jsdc, JSDSourceText* jsdsrc,
-                  const char** ppBuf, int* pLen);
-
-extern void
-jsd_ClearSourceText(JSDContext* jsdc, JSDSourceText* jsdsrc);
-
-extern JSDSourceStatus
-jsd_GetSourceStatus(JSDContext* jsdc, JSDSourceText* jsdsrc);
-
-extern bool
-jsd_IsSourceDirty(JSDContext* jsdc, JSDSourceText* jsdsrc);
-
-extern void
-jsd_SetSourceDirty(JSDContext* jsdc, JSDSourceText* jsdsrc, bool dirty);
-
-extern unsigned
-jsd_GetSourceAlterCount(JSDContext* jsdc, JSDSourceText* jsdsrc);
-
-extern unsigned
-jsd_IncrementSourceAlterCount(JSDContext* jsdc, JSDSourceText* jsdsrc);
-
-extern JSDSourceText*
-jsd_NewSourceText(JSDContext* jsdc, const char* url);
-
-extern JSDSourceText*
-jsd_AppendSourceText(JSDContext* jsdc,
-                     JSDSourceText* jsdsrc,
-                     const char* text,       /* *not* zero terminated */
-                     size_t length,
-                     JSDSourceStatus status);
-
-extern JSDSourceText*
-jsd_AppendUCSourceText(JSDContext* jsdc,
-                       JSDSourceText* jsdsrc,
-                       const jschar* text,       /* *not* zero terminated */
-                       size_t length,
-                       JSDSourceStatus status);
-
-/* convienence function for adding complete source of url in one call */
-extern bool
-jsd_AddFullSourceText(JSDContext* jsdc,
-                      const char* text,       /* *not* zero terminated */
-                      size_t      length,
-                      const char* url);
-
-extern void
-jsd_DestroyAllSources(JSDContext* jsdc);
-
-extern char*
-jsd_BuildNormalizedURL(const char* url_string);
-
-extern void
-jsd_StartingEvalUsingFilename(JSDContext* jsdc, const char* url);
-
-extern void
-jsd_FinishedEvalUsingFilename(JSDContext* jsdc, const char* url);
-
-/***************************************************************************/
-/* Interrupt Hook functions */
-
-extern bool
-jsd_SetInterruptHook(JSDContext*           jsdc,
-                     JSD_ExecutionHookProc hook,
-                     void*                 callerdata);
-
-extern bool
-jsd_ClearInterruptHook(JSDContext* jsdc);
-
-extern bool
-jsd_EnableSingleStepInterrupts(JSDContext* jsdc,
-                               JSDScript*  jsdscript,
-                               bool        enable);
-
-extern bool
-jsd_SetDebugBreakHook(JSDContext*           jsdc,
-                      JSD_ExecutionHookProc hook,
-                      void*                 callerdata);
-
-extern bool
-jsd_ClearDebugBreakHook(JSDContext* jsdc);
-
-extern bool
-jsd_SetDebuggerHook(JSDContext*           jsdc,
-                    JSD_ExecutionHookProc hook,
-                    void*                 callerdata);
-
-extern bool
-jsd_ClearDebuggerHook(JSDContext* jsdc);
-
-extern JSTrapStatus
-jsd_CallExecutionHook(JSDContext*           jsdc,
-                      JSContext*            cx,
-                      unsigned                 type,
-                      JSD_ExecutionHookProc hook,
-                      void*                 hookData,
-                      jsval*                rval);
-
-extern bool
-jsd_CallCallHook (JSDContext*      jsdc,
-                  JSContext*       cx,
-                  unsigned            type,
-                  JSD_CallHookProc hook,
-                  void*            hookData);
-
-extern bool
-jsd_SetThrowHook(JSDContext*           jsdc,
-                 JSD_ExecutionHookProc hook,
-                 void*                 callerdata);
-extern bool
-jsd_ClearThrowHook(JSDContext* jsdc);
-
-extern JSTrapStatus
-jsd_DebuggerHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
-                    jsval *rval, void *closure);
-
-extern JSTrapStatus
-jsd_ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
-                 jsval *rval, void *closure);
-
-extern bool
-jsd_SetFunctionHook(JSDContext*      jsdc,
-                    JSD_CallHookProc hook,
-                    void*            callerdata);
-
-extern bool
-jsd_ClearFunctionHook(JSDContext* jsdc);
-
-extern bool
-jsd_SetTopLevelHook(JSDContext*      jsdc,
-                    JSD_CallHookProc hook,
-                    void*            callerdata);
-
-extern bool
-jsd_ClearTopLevelHook(JSDContext* jsdc);
-
-/***************************************************************************/
-/* Stack Frame functions */
-
-extern unsigned
-jsd_GetCountOfStackFrames(JSDContext* jsdc, JSDThreadState* jsdthreadstate);
-
-extern JSDStackFrameInfo*
-jsd_GetStackFrame(JSDContext* jsdc, JSDThreadState* jsdthreadstate);
-
-extern JSContext*
-jsd_GetJSContext(JSDContext* jsdc, JSDThreadState* jsdthreadstate);
-
-extern JSDStackFrameInfo*
-jsd_GetCallingStackFrame(JSDContext* jsdc,
-                         JSDThreadState* jsdthreadstate,
-                         JSDStackFrameInfo* jsdframe);
-
-extern JSDScript*
-jsd_GetScriptForStackFrame(JSDContext* jsdc,
-                           JSDThreadState* jsdthreadstate,
-                           JSDStackFrameInfo* jsdframe);
-
-extern uintptr_t
-jsd_GetPCForStackFrame(JSDContext* jsdc,
-                       JSDThreadState* jsdthreadstate,
-                       JSDStackFrameInfo* jsdframe);
-
-extern JSDValue*
-jsd_GetCallObjectForStackFrame(JSDContext* jsdc,
-                               JSDThreadState* jsdthreadstate,
-                               JSDStackFrameInfo* jsdframe);
-
-extern JSDValue*
-jsd_GetScopeChainForStackFrame(JSDContext* jsdc,
-                               JSDThreadState* jsdthreadstate,
-                               JSDStackFrameInfo* jsdframe);
-
-extern bool
-jsd_IsStackFrameDebugger(JSDContext* jsdc, 
-                         JSDThreadState* jsdthreadstate,
-                         JSDStackFrameInfo* jsdframe);
-
-extern bool
-jsd_IsStackFrameConstructing(JSDContext* jsdc, 
-                             JSDThreadState* jsdthreadstate,
-                             JSDStackFrameInfo* jsdframe);
-
-extern JSDValue*
-jsd_GetThisForStackFrame(JSDContext* jsdc,
-                         JSDThreadState* jsdthreadstate,
-                         JSDStackFrameInfo* jsdframe);
-
-extern JSString*
-jsd_GetIdForStackFrame(JSDContext* jsdc, 
-                       JSDThreadState* jsdthreadstate,
-                       JSDStackFrameInfo* jsdframe);
-
-extern JSDThreadState*
-jsd_NewThreadState(JSDContext* jsdc, JSContext *cx);
-
-extern void
-jsd_DestroyThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate);
-
-extern bool
-jsd_EvaluateUCScriptInStackFrame(JSDContext* jsdc,
-                                 JSDThreadState* jsdthreadstate,
-                                 JSDStackFrameInfo* jsdframe,
-                                 const jschar *bytes, unsigned length,
-                                 const char *filename, unsigned lineno,
-                                 bool eatExceptions, JS::MutableHandleValue rval);
-
-extern bool
-jsd_EvaluateScriptInStackFrame(JSDContext* jsdc,
-                               JSDThreadState* jsdthreadstate,
-                               JSDStackFrameInfo* jsdframe,
-                               const char *bytes, unsigned length,
-                               const char *filename, unsigned lineno,
-                               bool eatExceptions, JS::MutableHandleValue rval);
-
-extern JSString*
-jsd_ValToStringInStackFrame(JSDContext* jsdc,
-                            JSDThreadState* jsdthreadstate,
-                            JSDStackFrameInfo* jsdframe,
-                            jsval val);
-
-extern bool
-jsd_IsValidThreadState(JSDContext*        jsdc,
-                       JSDThreadState*    jsdthreadstate);
-
-extern bool
-jsd_IsValidFrameInThreadState(JSDContext*        jsdc,
-                              JSDThreadState*    jsdthreadstate,
-                              JSDStackFrameInfo* jsdframe);
-
-extern JSDValue*
-jsd_GetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate);
-
-extern bool
-jsd_SetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate, 
-                 JSDValue* jsdval);
-
-/***************************************************************************/
-/* Locking support */
-
-/* protos are in js_lock.h for:
- *      jsd_CreateLock
- *      jsd_Lock
- *      jsd_Unlock
- *      jsd_IsLocked
- *      jsd_CurrentThread
- */
-
-#ifdef JSD_THREADSAFE
-
-/* the system-wide lock */
-extern JSDStaticLock* _jsd_global_lock;
-#define JSD_LOCK()                               \
-    JS_BEGIN_MACRO                               \
-        if(!_jsd_global_lock)                    \
-            _jsd_global_lock = jsd_CreateLock(); \
-        MOZ_ASSERT(_jsd_global_lock);            \
-        jsd_Lock(_jsd_global_lock);              \
-    JS_END_MACRO
-
-#define JSD_UNLOCK()                             \
-    JS_BEGIN_MACRO                               \
-        MOZ_ASSERT(_jsd_global_lock);            \
-        jsd_Unlock(_jsd_global_lock);            \
-    JS_END_MACRO
-
-/* locks for the subsystems of a given context */
-#define JSD_INIT_LOCKS(jsdc)                                       \
-    ( (nullptr != (jsdc->scriptsLock      = jsd_CreateLock())) &&  \
-      (nullptr != (jsdc->sourceTextLock   = jsd_CreateLock())) &&  \
-      (nullptr != (jsdc->atomsLock        = jsd_CreateLock())) &&  \
-      (nullptr != (jsdc->objectsLock      = jsd_CreateLock())) &&  \
-      (nullptr != (jsdc->threadStatesLock = jsd_CreateLock())) )
-
-#define JSD_LOCK_SCRIPTS(jsdc)        jsd_Lock(jsdc->scriptsLock)
-#define JSD_UNLOCK_SCRIPTS(jsdc)      jsd_Unlock(jsdc->scriptsLock)
-
-#define JSD_LOCK_SOURCE_TEXT(jsdc)    jsd_Lock(jsdc->sourceTextLock)
-#define JSD_UNLOCK_SOURCE_TEXT(jsdc)  jsd_Unlock(jsdc->sourceTextLock)
-
-#define JSD_LOCK_ATOMS(jsdc)          jsd_Lock(jsdc->atomsLock)
-#define JSD_UNLOCK_ATOMS(jsdc)        jsd_Unlock(jsdc->atomsLock)
-
-#define JSD_LOCK_OBJECTS(jsdc)        jsd_Lock(jsdc->objectsLock)
-#define JSD_UNLOCK_OBJECTS(jsdc)      jsd_Unlock(jsdc->objectsLock)
-
-#define JSD_LOCK_THREADSTATES(jsdc)   jsd_Lock(jsdc->threadStatesLock)
-#define JSD_UNLOCK_THREADSTATES(jsdc) jsd_Unlock(jsdc->threadStatesLock)
-
-#else  /* !JSD_THREADSAFE */
-
-#define JSD_LOCK()                    ((void)0)
-#define JSD_UNLOCK()                  ((void)0)
-
-#define JSD_INIT_LOCKS(jsdc)          1
-
-#define JSD_LOCK_SCRIPTS(jsdc)        ((void)0)
-#define JSD_UNLOCK_SCRIPTS(jsdc)      ((void)0)
-
-#define JSD_LOCK_SOURCE_TEXT(jsdc)    ((void)0)
-#define JSD_UNLOCK_SOURCE_TEXT(jsdc)  ((void)0)
-
-#define JSD_LOCK_ATOMS(jsdc)          ((void)0)
-#define JSD_UNLOCK_ATOMS(jsdc)        ((void)0)
-
-#define JSD_LOCK_OBJECTS(jsdc)        ((void)0)
-#define JSD_UNLOCK_OBJECTS(jsdc)      ((void)0)
-
-#define JSD_LOCK_THREADSTATES(jsdc)   ((void)0)
-#define JSD_UNLOCK_THREADSTATES(jsdc) ((void)0)
-
-#endif /* JSD_THREADSAFE */
-
-/* NOTE: These are intended for ASSERTs. Thus we supply checks for both
- * LOCKED and UNLOCKED (rather that just LOCKED and !LOCKED) so that in
- * the DEBUG non-Threadsafe case we can have an ASSERT that always succeeds
- * without having to special case things in the code.
- */
-#if defined(JSD_THREADSAFE) && defined(DEBUG)
-#define JSD_SCRIPTS_LOCKED(jsdc)        (jsd_IsLocked(jsdc->scriptsLock))
-#define JSD_SOURCE_TEXT_LOCKED(jsdc)    (jsd_IsLocked(jsdc->sourceTextLock))
-#define JSD_ATOMS_LOCKED(jsdc)          (jsd_IsLocked(jsdc->atomsLock))
-#define JSD_OBJECTS_LOCKED(jsdc)        (jsd_IsLocked(jsdc->objectsLock))
-#define JSD_THREADSTATES_LOCKED(jsdc)   (jsd_IsLocked(jsdc->threadStatesLock))
-#define JSD_SCRIPTS_UNLOCKED(jsdc)      (!jsd_IsLocked(jsdc->scriptsLock))
-#define JSD_SOURCE_TEXT_UNLOCKED(jsdc)  (!jsd_IsLocked(jsdc->sourceTextLock))
-#define JSD_ATOMS_UNLOCKED(jsdc)        (!jsd_IsLocked(jsdc->atomsLock))
-#define JSD_OBJECTS_UNLOCKED(jsdc)      (!jsd_IsLocked(jsdc->objectsLock))
-#define JSD_THREADSTATES_UNLOCKED(jsdc) (!jsd_IsLocked(jsdc->threadStatesLock))
-#else
-#define JSD_SCRIPTS_LOCKED(jsdc)        1
-#define JSD_SOURCE_TEXT_LOCKED(jsdc)    1
-#define JSD_ATOMS_LOCKED(jsdc)          1
-#define JSD_OBJECTS_LOCKED(jsdc)        1
-#define JSD_THREADSTATES_LOCKED(jsdc)   1
-#define JSD_SCRIPTS_UNLOCKED(jsdc)      1
-#define JSD_SOURCE_TEXT_UNLOCKED(jsdc)  1
-#define JSD_ATOMS_UNLOCKED(jsdc)        1
-#define JSD_OBJECTS_UNLOCKED(jsdc)      1
-#define JSD_THREADSTATES_UNLOCKED(jsdc) 1
-#endif /* defined(JSD_THREADSAFE) && defined(DEBUG) */
-
-/***************************************************************************/
-/* Threading support */
-
-#ifdef JSD_THREADSAFE
-
-#define JSD_CURRENT_THREAD()        jsd_CurrentThread()
-
-#else  /* !JSD_THREADSAFE */
-
-#define JSD_CURRENT_THREAD()        ((void*)0)
-
-#endif /* JSD_THREADSAFE */
-
-/***************************************************************************/
-/* Dangerous thread support */
-
-#ifdef JSD_HAS_DANGEROUS_THREAD
-
-#define JSD_IS_DANGEROUS_THREAD(jsdc) \
-    (JSD_CURRENT_THREAD() == jsdc->dangerousThread)
-
-#else  /* !JSD_HAS_DANGEROUS_THREAD */
-
-#define JSD_IS_DANGEROUS_THREAD(jsdc)   0
-
-#endif /* JSD_HAS_DANGEROUS_THREAD */
-
-/***************************************************************************/
-/* Value and Property Functions */
-
-extern JSDValue*
-jsd_NewValue(JSDContext* jsdc, jsval val);
-
-extern void
-jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval);
-
-extern jsval
-jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval);
-
-extern void
-jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval);
-
-/**************************************************/
-
-extern bool
-jsd_IsValueObject(JSDContext* jsdc, JSDValue* jsdval);
-
-extern bool
-jsd_IsValueNumber(JSDContext* jsdc, JSDValue* jsdval);
-
-extern bool
-jsd_IsValueInt(JSDContext* jsdc, JSDValue* jsdval);
-
-extern bool
-jsd_IsValueDouble(JSDContext* jsdc, JSDValue* jsdval);
-
-extern bool
-jsd_IsValueString(JSDContext* jsdc, JSDValue* jsdval);
-
-extern bool
-jsd_IsValueBoolean(JSDContext* jsdc, JSDValue* jsdval);
-
-extern bool
-jsd_IsValueNull(JSDContext* jsdc, JSDValue* jsdval);
-
-extern bool
-jsd_IsValueVoid(JSDContext* jsdc, JSDValue* jsdval);
-
-extern bool
-jsd_IsValuePrimitive(JSDContext* jsdc, JSDValue* jsdval);
-
-extern bool
-jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval);
-
-extern bool
-jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval);
-
-/**************************************************/
-
-extern bool
-jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval);
-
-extern int32_t
-jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval);
-
-extern double
-jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval);
-
-extern JSString*
-jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval);
-
-extern JSString*
-jsd_GetValueFunctionId(JSDContext* jsdc, JSDValue* jsdval);
-
-extern JSFunction*
-jsd_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval);
-
-/**************************************************/
-
-extern unsigned
-jsd_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval);
-
-extern JSDProperty*
-jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp);
-
-extern JSDProperty*
-jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name);
-
-extern JSDValue*
-jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval);
-
-extern JSDValue*
-jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval);
-
-extern JSDValue*
-jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval);
-
-extern const char*
-jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval);
-
-extern JSDScript*
-jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval);
-
-/**************************************************/
-
-extern void
-jsd_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop);
-
-extern JSDValue*
-jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop);
-
-extern JSDValue*
-jsd_GetPropertyValue(JSDContext* jsdc, JSDProperty* jsdprop);
-
-extern JSDValue*
-jsd_GetPropertyAlias(JSDContext* jsdc, JSDProperty* jsdprop);
-
-extern unsigned
-jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop);
-
-/**************************************************/
-/* Stepping Functions */
-
-extern void *
-jsd_FunctionCallHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
-                     bool before, bool *ok, void *closure);
-
-extern void *
-jsd_TopLevelCallHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
-                     bool before, bool *ok, void *closure);
-
-/**************************************************/
-/* Object Functions */
-
-extern bool
-jsd_InitObjectManager(JSDContext* jsdc);
-
-extern void
-jsd_DestroyObjectManager(JSDContext* jsdc);
-
-extern void
-jsd_DestroyObjects(JSDContext* jsdc);
-
-extern void
-jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
-                 JSAbstractFramePtr frame);
-
-extern JSDObject*
-jsd_IterateObjects(JSDContext* jsdc, JSDObject** iterp);
-
-extern JSObject*
-jsd_GetWrappedObject(JSDContext* jsdc, JSDObject* jsdobj);
-
-extern const char*
-jsd_GetObjectNewURL(JSDContext* jsdc, JSDObject* jsdobj);
-
-extern unsigned
-jsd_GetObjectNewLineNumber(JSDContext* jsdc, JSDObject* jsdobj);
-
-extern const char*
-jsd_GetObjectConstructorURL(JSDContext* jsdc, JSDObject* jsdobj);
-
-extern unsigned
-jsd_GetObjectConstructorLineNumber(JSDContext* jsdc, JSDObject* jsdobj);
-
-extern const char*
-jsd_GetObjectConstructorName(JSDContext* jsdc, JSDObject* jsdobj);
-
-extern JSDObject*
-jsd_GetJSDObjectForJSObject(JSDContext* jsdc, JSObject* jsobj);
-
-extern JSDObject*
-jsd_GetObjectForValue(JSDContext* jsdc, JSDValue* jsdval);
-
-/*
-* returns new refcounted JSDValue
-*/
-extern JSDValue*
-jsd_GetValueForObject(JSDContext* jsdc, JSDObject* jsdobj);
-
-/**************************************************/
-/* Atom Functions */
-
-extern bool
-jsd_CreateAtomTable(JSDContext* jsdc);
-
-extern void
-jsd_DestroyAtomTable(JSDContext* jsdc);
-
-extern JSDAtom*
-jsd_AddAtom(JSDContext* jsdc, const char* str);
-
-extern JSDAtom*
-jsd_CloneAtom(JSDContext* jsdc, JSDAtom* atom);
-
-extern void
-jsd_DropAtom(JSDContext* jsdc, JSDAtom* atom);
-
-#define JSD_ATOM_TO_STRING(a) ((const char*)((a)->str))
-
-struct AutoSaveExceptionState {
-    AutoSaveExceptionState(JSContext *cx) : mCx(cx) {
-        mState = JS_SaveExceptionState(cx);
-    }
-    ~AutoSaveExceptionState() {
-        JS_RestoreExceptionState(mCx, mState);
-    }
-    JSContext *mCx;
-    JSExceptionState *mState;
-};
-
-#endif /* jsd_h___ */
deleted file mode 100644
--- a/js/jsd/jsd1640.def
+++ /dev/null
@@ -1,77 +0,0 @@
-; -*- Mode: Fundamental; tab-width: 4; indent-tabs-mode: nil -*-
-;
-; This Source Code Form is subject to the terms of the Mozilla Public
-; License, v. 2.0. If a copy of the MPL was not distributed with this
-; file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-
-LIBRARY JSD1640.DLL
-EXETYPE WINDOWS
-PROTMODE
-
-DESCRIPTION 'Netscape 16-bit JavaScript Debugger Library'
-
-CODE    LOADONCALL MOVEABLE DISCARDABLE
-DATA	PRELOAD MOVEABLE SINGLE
-
-HEAPSIZE    8192
-
-EXPORTS
-	WEP															@1 RESIDENTNAME	NONAME
-	_JSD_AppendSourceText
-	_JSD_ClearAllExecutionHooks
-	_JSD_ClearAllExecutionHooksForScript
-	_JSD_ClearDebugBreakHook
-	_JSD_ClearExecutionHook
-	_JSD_ClearInterruptHook
-	_JSD_ClearSourceText
-	_JSD_DebuggerOff
-	_JSD_DebuggerOn
-	_JSD_EvaluateScriptInStackFrame
-	_JSD_FindSourceForURL
-	_JSD_GetCallingStackFrame
-	_JSD_GetClosestLine
-	_JSD_GetClosestPC
-	_JSD_GetCountOfStackFrames
-	_JSD_GetMajorVersion
-	_JSD_GetMinorVersion
-	_JSD_GetPCForStackFrame
-	_JSD_GetScriptBaseLineNumber
-	_JSD_GetScriptFilename
-	_JSD_GetScriptForStackFrame
-	_JSD_GetScriptFunctionId
-	_JSD_GetScriptHook
-	_JSD_GetScriptLineExtent
-	_JSD_GetSourceAlterCount
-	_JSD_GetSourceStatus
-	_JSD_GetSourceText
-	_JSD_GetSourceURL
-	_JSD_GetStackFrame
-	_JSD_IncrementSourceAlterCount
-	_JSD_IsSourceDirty
-	_JSD_IterateScripts
-	_JSD_IterateSources
-	_JSD_LockScriptSubsystem
-	_JSD_LockSourceTextSubsystem
-	_JSD_NewSourceText
-	_JSD_SetDebugBreakHook
-	_JSD_SetErrorReporter
-	_JSD_SetExecutionHook
-	_JSD_SetInterruptHook
-	_JSD_SetScriptHook
-	_JSD_SetSourceDirty
-	_JSD_SetUserCallbacks
-	_JSD_UnlockScriptSubsystem
-	_JSD_UnlockSourceTextSubsystem
-	_Java_netscape_jsdebug_DebugController__0005fsetController_stub
-	_Java_netscape_jsdebug_DebugController_executeScriptInStackFrame_stub
-	_Java_netscape_jsdebug_DebugController_sendInterrupt_stub
-	_Java_netscape_jsdebug_DebugController_setInstructionHook0_stub
-	_Java_netscape_jsdebug_JSPC_getSourceLocation_stub
-	_Java_netscape_jsdebug_JSSourceTextProvider_loadSourceTextItem_stub
-	_Java_netscape_jsdebug_JSSourceTextProvider_refreshSourceTextVector_stub
-	_Java_netscape_jsdebug_JSStackFrameInfo_getCaller0_stub
-	_Java_netscape_jsdebug_JSStackFrameInfo_getPC_stub
-	_Java_netscape_jsdebug_JSThreadState_countStackFrames_stub
-	_Java_netscape_jsdebug_JSThreadState_getCurrentFrame_stub
-	_Java_netscape_jsdebug_Script_getClosestPC_stub
deleted file mode 100644
--- a/js/jsd/jsd1640.rc
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-// Version stamp for this .DLL
-
-#include <windows.h>
-
-#include <ver.h>
-
-
-
-VS_VERSION_INFO     VERSIONINFO
-
-  FILEVERSION       4 // major, minor, release (alpha 1), build #
-
-  PRODUCTVERSION    4
-
-  FILEFLAGSMASK     0
-
-  FILEFLAGS         0 // final version
-
-  FILEOS            VOS_DOS_WINDOWS16
-
-  FILETYPE          VFT_DLL
-
-  FILESUBTYPE       0   // not used
-
-BEGIN
-
-    BLOCK "StringFileInfo"
-
-    BEGIN
-
-        BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual
-
-        BEGIN
-
-            VALUE "CompanyName",     "Netscape Communications Corporation\0"
-
-            VALUE "FileDescription", "Netscape 16-bit JavaScript Debugger Module\0"
-
-            VALUE "FileVersion",     "4.0\0"
-
-            VALUE "InternalName",    "JSD1640\0"
-
-            VALUE "LegalCopyright",  "Copyright Netscape Communications. 1994-96\0"
-
-            VALUE "LegalTrademarks", "Netscape, Mozilla\0"
-
-            VALUE "OriginalFilename","JSD1640.DLL\0"
-
-            VALUE "ProductName",     "NETSCAPE\0"
-
-            VALUE "ProductVersion",  "4.0\0"
-
-        END
-
-    END
-
-END
-
deleted file mode 100644
--- a/js/jsd/jsd3240.rc
+++ /dev/null
@@ -1,86 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "winver.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 4,0,0,0
- PRODUCTVERSION 4,0,0,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x10004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904e4"
-        BEGIN
-            VALUE "CompanyName", "Netscape Communications Corporation\0"
-            VALUE "FileDescription", "Netscape 32-bit JavaScript Debugger Module\0"
-            VALUE "FileVersion", "4.0\0"
-            VALUE "InternalName", "JSD3240\0"
-            VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0"
-            VALUE "LegalTrademarks", "Netscape, Mozilla\0"
-            VALUE "OriginalFilename", "jsd3240.dll\0"
-            VALUE "ProductName", "NETSCAPE\0"
-            VALUE "ProductVersion", "4.0\0"
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1252
-    END
-END
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "#include ""winver.h""\r\n"
-    "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-/////////////////////////////////////////////////////////////////////////////
\ No newline at end of file
deleted file mode 100644
--- a/js/jsd/jsd_atom.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- * JavaScript Debugging support - Atom support
- */
-
-#include "jsd.h"
-
-/* #define TEST_ATOMS 1 */
-
-#ifdef TEST_ATOMS
-static void 
-_testAtoms(JSDContext*jsdc)
-{
-    JSDAtom* atom0 = jsd_AddAtom(jsdc, "foo");
-    JSDAtom* atom1 = jsd_AddAtom(jsdc, "foo");
-    JSDAtom* atom2 = jsd_AddAtom(jsdc, "bar");
-    JSDAtom* atom3 = jsd_CloneAtom(jsdc, atom1);
-    JSDAtom* atom4 = jsd_CloneAtom(jsdc, atom2);
-
-    const char* c0 = JSD_ATOM_TO_STRING(atom0);
-    const char* c1 = JSD_ATOM_TO_STRING(atom1);
-    const char* c2 = JSD_ATOM_TO_STRING(atom2);
-    const char* c3 = JSD_ATOM_TO_STRING(atom3);
-    const char* c4 = JSD_ATOM_TO_STRING(atom4);
-
-    jsd_DropAtom(jsdc, atom0);
-    jsd_DropAtom(jsdc, atom1);
-    jsd_DropAtom(jsdc, atom2);
-    jsd_DropAtom(jsdc, atom3);
-    jsd_DropAtom(jsdc, atom4);
-}        
-#endif    
-
-static int
-_atom_smasher(JSHashEntry *he, int i, void *arg)
-{
-    MOZ_ASSERT(he);
-    MOZ_ASSERT(he->value);
-    MOZ_ASSERT(((JSDAtom*)(he->value))->str);
-
-    free(((JSDAtom*)(he->value))->str);
-    free(he->value);
-    he->value = nullptr;
-    he->key   = nullptr;
-    return HT_ENUMERATE_NEXT;
-}
-
-static int
-_compareAtomKeys(const void *v1, const void *v2)
-{
-    return 0 == strcmp((const char*)v1, (const char*)v2);
-}        
-
-static int
-_compareAtoms(const void *v1, const void *v2)
-{
-    return 0 == strcmp(((JSDAtom*)v1)->str, ((JSDAtom*)v2)->str);
-}        
-
-
-bool
-jsd_CreateAtomTable(JSDContext* jsdc)
-{
-    jsdc->atoms = JS_NewHashTable(256, JS_HashString,
-                                  _compareAtomKeys, _compareAtoms,
-                                  nullptr, nullptr);
-#ifdef TEST_ATOMS
-    _testAtoms(jsdc);
-#endif    
-    return !!jsdc->atoms;
-}
-
-void
-jsd_DestroyAtomTable(JSDContext* jsdc)
-{
-    if( jsdc->atoms )
-    {
-        JS_HashTableEnumerateEntries(jsdc->atoms, _atom_smasher, nullptr);
-        JS_HashTableDestroy(jsdc->atoms);
-        jsdc->atoms = nullptr;
-    }
-}
-
-JSDAtom*
-jsd_AddAtom(JSDContext* jsdc, const char* str)
-{
-    JSDAtom* atom;
-
-    if(!str)
-    {
-        MOZ_ASSERT(0);
-        return nullptr;
-    }
-
-    JSD_LOCK_ATOMS(jsdc);
-    
-    atom = (JSDAtom*) JS_HashTableLookup(jsdc->atoms, str);
-
-    if( atom )
-        atom->refcount++;
-    else
-    {
-        atom = (JSDAtom*) malloc(sizeof(JSDAtom));
-        if( atom )
-        {
-            atom->str = strdup(str);
-            atom->refcount = 1;
-            if(!JS_HashTableAdd(jsdc->atoms, atom->str, atom))
-            {
-                free(atom->str);
-                free(atom);
-                atom = nullptr;
-            }
-        }
-    }
-
-    JSD_UNLOCK_ATOMS(jsdc);
-    return atom;
-}        
-
-JSDAtom*
-jsd_CloneAtom(JSDContext* jsdc, JSDAtom* atom)
-{
-    JSD_LOCK_ATOMS(jsdc);
-    atom->refcount++;
-    JSD_UNLOCK_ATOMS(jsdc);
-    return atom;
-}        
-
-void
-jsd_DropAtom(JSDContext* jsdc, JSDAtom* atom)
-{
-    JSD_LOCK_ATOMS(jsdc);
-    if(! --atom->refcount)
-    {
-        JS_HashTableRemove(jsdc->atoms, atom->str);
-        free(atom->str);
-        free(atom);
-    }
-    JSD_UNLOCK_ATOMS(jsdc);
-}        
-
deleted file mode 100644
--- a/js/jsd/jsd_high.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- * JavaScript Debugging support - 'High Level' functions
- */
-
-#include "jsd.h"
-#include "nsCxPusher.h"
-
-using mozilla::AutoSafeJSContext;
-
-/***************************************************************************/
-
-/* XXX not 'static' because of old Mac CodeWarrior bug */ 
-JSCList _jsd_context_list = JS_INIT_STATIC_CLIST(&_jsd_context_list);
-
-/* these are used to connect JSD_SetUserCallbacks() with JSD_DebuggerOn() */
-static JSD_UserCallbacks _callbacks;
-static void*             _user = nullptr; 
-static JSRuntime*        _jsrt = nullptr;
-
-#ifdef JSD_HAS_DANGEROUS_THREAD
-static void* _dangerousThread = nullptr;
-#endif
-
-#ifdef JSD_THREADSAFE
-JSDStaticLock* _jsd_global_lock = nullptr;
-#endif
-
-#ifdef DEBUG
-void JSD_ASSERT_VALID_CONTEXT(JSDContext* jsdc)
-{
-    MOZ_ASSERT(jsdc->inited);
-    MOZ_ASSERT(jsdc->jsrt);
-    MOZ_ASSERT(jsdc->glob);
-}
-#endif
-
-/***************************************************************************/
-/* xpconnect related utility functions implemented in jsd_xpc.cpp */
-
-extern void
-global_finalize(JSFreeOp* fop, JSObject* obj);
-
-extern JSObject*
-CreateJSDGlobal(JSContext *cx, const JSClass *clasp);
-
-/***************************************************************************/
-
-
-static const JSClass global_class = {
-    "JSDGlobal", JSCLASS_GLOBAL_FLAGS |
-    JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS,
-    JS_PropertyStub,  JS_DeletePropertyStub,  JS_PropertyStub,  JS_StrictPropertyStub,
-    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   global_finalize,
-    nullptr, nullptr, nullptr,
-    JS_GlobalObjectTraceHook
-};
-
-static bool
-_validateUserCallbacks(JSD_UserCallbacks* callbacks)
-{
-    return !callbacks ||
-           (callbacks->size && callbacks->size <= sizeof(JSD_UserCallbacks));
-}    
-
-static JSDContext*
-_newJSDContext(JSRuntime*         jsrt, 
-               JSD_UserCallbacks* callbacks, 
-               void*              user,
-               JSObject*          scopeobj)
-{
-    JSDContext* jsdc = nullptr;
-    bool ok = true;
-    AutoSafeJSContext cx;
-
-    if( ! jsrt )
-        return nullptr;
-
-    if( ! _validateUserCallbacks(callbacks) )
-        return nullptr;
-
-    jsdc = (JSDContext*) calloc(1, sizeof(JSDContext));
-    if( ! jsdc )
-        goto label_newJSDContext_failure;
-
-    if( ! JSD_INIT_LOCKS(jsdc) )
-        goto label_newJSDContext_failure;
-
-    JS_INIT_CLIST(&jsdc->links);
-
-    jsdc->jsrt = jsrt;
-
-    if( callbacks )
-        memcpy(&jsdc->userCallbacks, callbacks, callbacks->size);
-    
-    jsdc->user = user;
-
-#ifdef JSD_HAS_DANGEROUS_THREAD
-    jsdc->dangerousThread = _dangerousThread;
-#endif
-
-    JS_INIT_CLIST(&jsdc->threadsStates);
-    JS_INIT_CLIST(&jsdc->sources);
-    JS_INIT_CLIST(&jsdc->removedSources);
-
-    jsdc->sourceAlterCount = 1;
-
-    if( ! jsd_CreateAtomTable(jsdc) )
-        goto label_newJSDContext_failure;
-
-    if( ! jsd_InitObjectManager(jsdc) )
-        goto label_newJSDContext_failure;
-
-    if( ! jsd_InitScriptManager(jsdc) )
-        goto label_newJSDContext_failure;
-
-    {
-        JS::RootedObject global(cx, CreateJSDGlobal(cx, &global_class));
-        if( ! global )
-            goto label_newJSDContext_failure;
-
-        jsdc->glob = global;
-
-        JSAutoCompartment ac(cx, jsdc->glob);
-        ok = JS::AddNamedObjectRoot(cx, &jsdc->glob, "JSD context global") &&
-             JS_InitStandardClasses(cx, global);
-    }
-    if( ! ok )
-        goto label_newJSDContext_failure;
-
-    jsdc->data = nullptr;
-    jsdc->inited = true;
-
-    JSD_LOCK();
-    JS_INSERT_LINK(&jsdc->links, &_jsd_context_list);
-    JSD_UNLOCK();
-
-    return jsdc;
-
-label_newJSDContext_failure:
-    if( jsdc ) {
-        if ( jsdc->glob )
-            JS::RemoveObjectRootRT(JS_GetRuntime(cx), &jsdc->glob);
-        jsd_DestroyObjectManager(jsdc);
-        jsd_DestroyAtomTable(jsdc);
-        free(jsdc);
-    }
-    return nullptr;
-}
-
-static void
-_destroyJSDContext(JSDContext* jsdc)
-{
-    JSD_ASSERT_VALID_CONTEXT(jsdc);
-
-    JSD_LOCK();
-    JS_REMOVE_LINK(&jsdc->links);
-    JSD_UNLOCK();
-
-    if ( jsdc->glob ) {
-        JS::RemoveObjectRootRT(jsdc->jsrt, &jsdc->glob);
-    }
-    jsd_DestroyObjectManager(jsdc);
-    jsd_DestroyAtomTable(jsdc);
-
-    jsdc->inited = false;
-
-    /*
-    * We should free jsdc here, but we let it leak in case there are any 
-    * asynchronous hooks calling into the system using it as a handle
-    *
-    * XXX we also leak the locks
-    */
-}
-
-/***************************************************************************/
-
-JSDContext*
-jsd_DebuggerOnForUser(JSRuntime*         jsrt, 
-                      JSD_UserCallbacks* callbacks, 
-                      void*              user,
-                      JSObject*          scopeobj)
-{
-    JSDContext* jsdc;
-
-    jsdc = _newJSDContext(jsrt, callbacks, user, scopeobj);
-    if( ! jsdc )
-        return nullptr;
-
-    /*
-     * Set hooks here.  The new/destroy script hooks are on even when
-     * the debugger is paused.  The destroy hook so we'll clean up
-     * internal data structures when scripts are destroyed, and the
-     * newscript hook for backwards compatibility for now.  We'd like
-     * to stop doing that.
-     */
-    JS_SetNewScriptHookProc(jsdc->jsrt, jsd_NewScriptHookProc, jsdc);
-    JS_SetDestroyScriptHookProc(jsdc->jsrt, jsd_DestroyScriptHookProc, jsdc);
-    jsd_DebuggerUnpause(jsdc);
-
-    if( jsdc->userCallbacks.setContext )
-        jsdc->userCallbacks.setContext(jsdc, jsdc->user);
-    return jsdc;
-}
-
-JSDContext*
-jsd_DebuggerOn(void)
-{
-    MOZ_ASSERT(_jsrt);
-    MOZ_ASSERT(_validateUserCallbacks(&_callbacks));
-    return jsd_DebuggerOnForUser(_jsrt, &_callbacks, _user, nullptr);
-}
-
-void
-jsd_DebuggerOff(JSDContext* jsdc)
-{
-    jsd_DebuggerPause(jsdc, true);
-    /* clear hooks here */
-    JS_SetNewScriptHookProc(jsdc->jsrt, nullptr, nullptr);
-    JS_SetDestroyScriptHookProc(jsdc->jsrt, nullptr, nullptr);
-
-    /* clean up */
-    JSD_LockScriptSubsystem(jsdc);
-    jsd_DestroyScriptManager(jsdc);
-    JSD_UnlockScriptSubsystem(jsdc);
-    jsd_DestroyAllSources(jsdc);
-    
-    _destroyJSDContext(jsdc);
-
-    if( jsdc->userCallbacks.setContext )
-        jsdc->userCallbacks.setContext(nullptr, jsdc->user);
-}
-
-void
-jsd_DebuggerPause(JSDContext* jsdc, bool forceAllHooksOff)
-{
-    JS_SetDebuggerHandler(jsdc->jsrt, nullptr, nullptr);
-    if (forceAllHooksOff || !(jsdc->flags & JSD_COLLECT_PROFILE_DATA)) {
-        JS_SetExecuteHook(jsdc->jsrt, nullptr, nullptr);
-        JS_SetCallHook(jsdc->jsrt, nullptr, nullptr);
-    }
-    JS_SetThrowHook(jsdc->jsrt, nullptr, nullptr);
-    JS_SetDebugErrorHook(jsdc->jsrt, nullptr, nullptr);
-}
-
-static bool
-jsd_DebugErrorHook(JSContext *cx, const char *message,
-                   JSErrorReport *report, void *closure);
-
-void
-jsd_DebuggerUnpause(JSDContext* jsdc)
-{
-    JS_SetDebuggerHandler(jsdc->jsrt, jsd_DebuggerHandler, jsdc);
-    JS_SetExecuteHook(jsdc->jsrt, jsd_TopLevelCallHook, jsdc);
-    JS_SetCallHook(jsdc->jsrt, jsd_FunctionCallHook, jsdc);
-    JS_SetThrowHook(jsdc->jsrt, jsd_ThrowHandler, jsdc);
-    JS_SetDebugErrorHook(jsdc->jsrt, jsd_DebugErrorHook, jsdc);
-}
-
-void
-jsd_SetUserCallbacks(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user)
-{
-    _jsrt = jsrt;
-    _user = user;
-
-#ifdef JSD_HAS_DANGEROUS_THREAD
-    _dangerousThread = JSD_CURRENT_THREAD();
-#endif
-
-    if( callbacks )
-        memcpy(&_callbacks, callbacks, sizeof(JSD_UserCallbacks));
-    else
-        memset(&_callbacks, 0 , sizeof(JSD_UserCallbacks));
-}
-
-void*
-jsd_SetContextPrivate(JSDContext* jsdc, void *data)
-{
-    jsdc->data = data;
-    return data;
-}
-
-void*
-jsd_GetContextPrivate(JSDContext* jsdc)
-{
-    return jsdc->data;
-}
-
-void
-jsd_ClearAllProfileData(JSDContext* jsdc)
-{
-    JSDScript *current;
-    
-    JSD_LOCK_SCRIPTS(jsdc);
-    current = (JSDScript *)jsdc->scripts.next;
-    while (current != (JSDScript *)&jsdc->scripts)
-    {
-        jsd_ClearScriptProfileData(jsdc, current);
-        current = (JSDScript *)current->links.next;
-    }
-
-    JSD_UNLOCK_SCRIPTS(jsdc);
-}
-
-JSDContext*
-jsd_JSDContextForJSContext(JSContext* context)
-{
-    JSDContext* iter;
-    JSDContext* jsdc = nullptr;
-    JSRuntime*  runtime = JS_GetRuntime(context);
-
-    JSD_LOCK();
-    for( iter = (JSDContext*)_jsd_context_list.next;
-         iter != (JSDContext*)&_jsd_context_list;
-         iter = (JSDContext*)iter->links.next )
-    {
-        if( runtime == iter->jsrt )
-        {
-            jsdc = iter;
-            break;
-        }
-    }
-    JSD_UNLOCK();
-    return jsdc;
-}    
-
-static bool
-jsd_DebugErrorHook(JSContext *cx, const char *message,
-                   JSErrorReport *report, void *closure)
-{
-    JSDContext* jsdc = (JSDContext*) closure;
-    JSD_ErrorReporter errorReporter;
-    void*             errorReporterData;
-    
-    if( ! jsdc )
-    {
-        MOZ_ASSERT(0);
-        return true;
-    }
-    if( JSD_IS_DANGEROUS_THREAD(jsdc) )
-        return true;
-
-    /* local in case hook gets cleared on another thread */
-    JSD_LOCK();
-    errorReporter     = jsdc->errorReporter;
-    errorReporterData = jsdc->errorReporterData;
-    JSD_UNLOCK();
-
-    if(!errorReporter)
-        return true;
-
-    switch(errorReporter(jsdc, cx, message, report, errorReporterData))
-    {
-        case JSD_ERROR_REPORTER_PASS_ALONG:
-            return true;
-        case JSD_ERROR_REPORTER_RETURN:
-            return false;
-        case JSD_ERROR_REPORTER_DEBUG:
-        {
-            JS::RootedValue rval(cx);
-            JSD_ExecutionHookProc   hook;
-            void*                   hookData;
-
-            /* local in case hook gets cleared on another thread */
-            JSD_LOCK();
-            hook = jsdc->debugBreakHook;
-            hookData = jsdc->debugBreakHookData;
-            JSD_UNLOCK();
-
-            jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_DEBUG_REQUESTED,
-                                  hook, hookData, rval.address());
-            /* XXX Should make this dependent on ExecutionHook retval */
-            return true;
-        }
-        case JSD_ERROR_REPORTER_CLEAR_RETURN:
-            if(report && JSREPORT_IS_EXCEPTION(report->flags))
-                JS_ClearPendingException(cx);
-            return false;
-        default:
-            MOZ_ASSERT(0);
-            break;
-    }
-    return true;
-}
-
-bool
-jsd_SetErrorReporter(JSDContext*       jsdc, 
-                     JSD_ErrorReporter reporter, 
-                     void*             callerdata)
-{
-    JSD_LOCK();
-    jsdc->errorReporter = reporter;
-    jsdc->errorReporterData = callerdata;
-    JSD_UNLOCK();
-    return true;
-}
-
-bool
-jsd_GetErrorReporter(JSDContext*        jsdc, 
-                     JSD_ErrorReporter* reporter, 
-                     void**             callerdata)
-{
-    JSD_LOCK();
-    if( reporter )
-        *reporter = jsdc->errorReporter;
-    if( callerdata )
-        *callerdata = jsdc->errorReporterData;
-    JSD_UNLOCK();
-    return true;
-}
deleted file mode 100644
--- a/js/jsd/jsd_hook.cpp
+++ /dev/null
@@ -1,330 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- * JavaScript Debugging support - Hook support
- */
-
-#include "jsd.h"
-
-JSTrapStatus
-jsd_InterruptHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
-                     void *closure)
-{
-    JSDScript*      jsdscript;
-    JSDContext*     jsdc = (JSDContext*) closure;
-    JSD_ExecutionHookProc hook;
-    void*                 hookData;
-
-    if( ! jsdc || ! jsdc->inited )
-        return JSTRAP_CONTINUE;
-
-    if( JSD_IS_DANGEROUS_THREAD(jsdc) )
-        return JSTRAP_CONTINUE;
-
-    /* local in case jsdc->interruptHook gets cleared on another thread */
-    JSD_LOCK();
-    hook     = jsdc->interruptHook;
-    hookData = jsdc->interruptHookData;
-    JSD_UNLOCK();
-
-    if (!hook)
-        return JSTRAP_CONTINUE;
-    
-    JSD_LOCK_SCRIPTS(jsdc);
-    jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
-    JSD_UNLOCK_SCRIPTS(jsdc);
-    if( ! jsdscript )
-        return JSTRAP_CONTINUE;
-
-    return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_INTERRUPTED,
-                                 hook, hookData, rval);
-}
-
-JSTrapStatus
-jsd_DebuggerHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
-                    jsval *rval, void *closure)
-{
-    JSDScript*      jsdscript;
-    JSDContext*     jsdc = (JSDContext*) closure;
-    JSD_ExecutionHookProc hook;
-    void*                 hookData;
-
-    if( ! jsdc || ! jsdc->inited )
-        return JSTRAP_CONTINUE;
-
-    if( JSD_IS_DANGEROUS_THREAD(jsdc) )
-        return JSTRAP_CONTINUE;
-
-    /* local in case jsdc->debuggerHook gets cleared on another thread */
-    JSD_LOCK();
-    hook     = jsdc->debuggerHook;
-    hookData = jsdc->debuggerHookData;
-    JSD_UNLOCK();
-    if(!hook)
-        return JSTRAP_CONTINUE;
-
-    JSD_LOCK_SCRIPTS(jsdc);
-    jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
-    JSD_UNLOCK_SCRIPTS(jsdc);
-    if( ! jsdscript )
-        return JSTRAP_CONTINUE;
-
-    return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_DEBUGGER_KEYWORD,
-                                 hook, hookData, rval);
-}
-
-
-JSTrapStatus
-jsd_ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
-                 jsval *rvalArg, void *closure)
-{
-    JSDScript*      jsdscript;
-    JSDContext*     jsdc = (JSDContext*) closure;
-    JSD_ExecutionHookProc hook;
-    void*                 hookData;
-
-    if( ! jsdc || ! jsdc->inited )
-        return JSTRAP_CONTINUE;
-
-    if( JSD_IS_DANGEROUS_THREAD(jsdc) )
-        return JSTRAP_CONTINUE;
-
-    /* local in case jsdc->throwHook gets cleared on another thread */
-    JSD_LOCK();
-    hook     = jsdc->throwHook;
-    hookData = jsdc->throwHookData;
-    JSD_UNLOCK();
-    if (!hook)
-        return JSTRAP_CONTINUE;
-
-    JSD_LOCK_SCRIPTS(jsdc);
-    jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
-    JSD_UNLOCK_SCRIPTS(jsdc);
-    if( ! jsdscript )
-        return JSTRAP_CONTINUE;
-
-    JS::RootedValue rval(cx);
-    JS_GetPendingException(cx, &rval);
-
-    JSTrapStatus result = jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_THROW,
-                                                hook, hookData, rval.address());
-    *rvalArg = rval;
-    return result;
-}
-
-JSTrapStatus
-jsd_CallExecutionHook(JSDContext* jsdc,
-                      JSContext *cx,
-                      unsigned type,
-                      JSD_ExecutionHookProc hook,
-                      void* hookData,
-                      jsval* rval)
-{
-    unsigned hookanswer = JSD_HOOK_THROW == type ? 
-                            JSD_HOOK_RETURN_CONTINUE_THROW :
-                            JSD_HOOK_RETURN_CONTINUE;
-    JSDThreadState* jsdthreadstate;
-
-    if(hook && nullptr != (jsdthreadstate = jsd_NewThreadState(jsdc, cx)))
-    {
-        if ((type != JSD_HOOK_THROW && type != JSD_HOOK_INTERRUPTED) ||
-            jsdc->flags & JSD_MASK_TOP_FRAME_ONLY ||
-            !(jsdthreadstate->flags & TS_HAS_DISABLED_FRAME))
-        {
-            /*
-             * if it's not a throw and it's not an interrupt,
-             * or we're only masking the top frame,
-             * or there are no disabled frames in this stack,
-             * then call out.
-             */
-             hookanswer = hook(jsdc, jsdthreadstate, type, hookData, rval);
-             jsd_DestroyThreadState(jsdc, jsdthreadstate);
-        }
-    }
-
-    switch(hookanswer)
-    {
-        case JSD_HOOK_RETURN_ABORT:
-        case JSD_HOOK_RETURN_HOOK_ERROR:
-            return JSTRAP_ERROR;
-        case JSD_HOOK_RETURN_RET_WITH_VAL:
-            return JSTRAP_RETURN;
-        case JSD_HOOK_RETURN_THROW_WITH_VAL:
-            return JSTRAP_THROW;
-        case JSD_HOOK_RETURN_CONTINUE:
-            break;
-        case JSD_HOOK_RETURN_CONTINUE_THROW:
-            /* only makes sense for jsd_ThrowHandler (which init'd rval) */
-            MOZ_ASSERT(JSD_HOOK_THROW == type);
-            return JSTRAP_THROW;
-        default:
-            MOZ_ASSERT(0);
-            break;
-    }
-    return JSTRAP_CONTINUE;
-}
-
-bool
-jsd_CallCallHook (JSDContext* jsdc,
-                  JSContext *cx,
-                  unsigned type,
-                  JSD_CallHookProc hook,
-                  void* hookData)
-{
-    bool hookanswer;
-    JSDThreadState*  jsdthreadstate;
-    
-    hookanswer = false;
-    if(hook && nullptr != (jsdthreadstate = jsd_NewThreadState(jsdc, cx)))
-    {
-        hookanswer = hook(jsdc, jsdthreadstate, type, hookData);
-        jsd_DestroyThreadState(jsdc, jsdthreadstate);
-    }
-
-    return hookanswer;
-}
-
-bool
-jsd_SetInterruptHook(JSDContext*           jsdc,
-                     JSD_ExecutionHookProc hook,
-                     void*                 callerdata)
-{
-    JSD_LOCK();
-    jsdc->interruptHookData  = callerdata;
-    jsdc->interruptHook      = hook;
-    JS_SetInterrupt(jsdc->jsrt, jsd_InterruptHandler, (void*) jsdc);
-    JSD_UNLOCK();
-
-    return true;
-}
-
-bool
-jsd_ClearInterruptHook(JSDContext* jsdc)
-{
-    JSD_LOCK();
-    JS_ClearInterrupt(jsdc->jsrt, nullptr, nullptr);
-    jsdc->interruptHook      = nullptr;
-    JSD_UNLOCK();
-
-    return true;
-}
-
-bool
-jsd_SetDebugBreakHook(JSDContext*           jsdc,
-                      JSD_ExecutionHookProc hook,
-                      void*                 callerdata)
-{
-    JSD_LOCK();
-    jsdc->debugBreakHookData  = callerdata;
-    jsdc->debugBreakHook      = hook;
-    JSD_UNLOCK();
-
-    return true;
-}
-
-bool
-jsd_ClearDebugBreakHook(JSDContext* jsdc)
-{
-    JSD_LOCK();
-    jsdc->debugBreakHook      = nullptr;
-    JSD_UNLOCK();
-
-    return true;
-}
-
-bool
-jsd_SetDebuggerHook(JSDContext*           jsdc,
-                      JSD_ExecutionHookProc hook,
-                      void*                 callerdata)
-{
-    JSD_LOCK();
-    jsdc->debuggerHookData  = callerdata;
-    jsdc->debuggerHook      = hook;
-    JSD_UNLOCK();
-
-    return true;
-}
-
-bool
-jsd_ClearDebuggerHook(JSDContext* jsdc)
-{
-    JSD_LOCK();
-    jsdc->debuggerHook      = nullptr;
-    JSD_UNLOCK();
-
-    return true;
-}
-
-bool
-jsd_SetThrowHook(JSDContext*           jsdc,
-                 JSD_ExecutionHookProc hook,
-                 void*                 callerdata)
-{
-    JSD_LOCK();
-    jsdc->throwHookData  = callerdata;
-    jsdc->throwHook      = hook;
-    JSD_UNLOCK();
-
-    return true;
-}
-
-bool
-jsd_ClearThrowHook(JSDContext* jsdc)
-{
-    JSD_LOCK();
-    jsdc->throwHook      = nullptr;
-    JSD_UNLOCK();
-
-    return true;
-}
-
-bool
-jsd_SetFunctionHook(JSDContext*      jsdc,
-                    JSD_CallHookProc hook,
-                    void*            callerdata)
-{
-    JSD_LOCK();
-    jsdc->functionHookData  = callerdata;
-    jsdc->functionHook      = hook;
-    JSD_UNLOCK();
-
-    return true;
-}
-
-bool
-jsd_ClearFunctionHook(JSDContext* jsdc)
-{
-    JSD_LOCK();
-    jsdc->functionHook      = nullptr;
-    JSD_UNLOCK();
-
-    return true;
-}
-
-bool
-jsd_SetTopLevelHook(JSDContext*      jsdc,
-                    JSD_CallHookProc hook,
-                    void*            callerdata)
-{
-    JSD_LOCK();
-    jsdc->toplevelHookData  = callerdata;
-    jsdc->toplevelHook      = hook;
-    JSD_UNLOCK();
-
-    return true;
-}
-
-bool
-jsd_ClearTopLevelHook(JSDContext* jsdc)
-{
-    JSD_LOCK();
-    jsdc->toplevelHook      = nullptr;
-    JSD_UNLOCK();
-
-    return true;
-}
-
deleted file mode 100644
--- a/js/jsd/jsd_lock.cpp
+++ /dev/null
@@ -1,228 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- * JavaScript Debugging support - Locking and threading support
- */
-
-/*                                                                           
-* ifdef JSD_USE_NSPR_LOCKS then you must build and run against NSPR2.       
-* Otherwise, there are stubs that can be filled in with your own locking     
-* code. Also, note that these stubs include a jsd_CurrentThread()            
-* implementation that only works on Win32 - this is needed for the inprocess 
-* Java-based debugger.                                                       
-*/                                                                           
-
-#include "jsd.h"
-
-#include "js/Utility.h"
-
-#ifdef JSD_THREADSAFE
-
-#ifdef JSD_USE_NSPR_LOCKS
-
-#include "prlock.h"
-#include "prthread.h"
-
-#ifdef JSD_ATTACH_THREAD_HACK
-#include "pprthred.h"   /* need this as long as JS_AttachThread is needed */
-#endif
-
-struct JSDStaticLock
-{
-    void*     owner;
-    PRLock*   lock;
-    int       count;
-#ifdef DEBUG
-    uint16_t  sig;
-#endif
-};
-
-/* 
- * This exists to wrap non-NSPR theads (e.g. Java threads) in NSPR wrappers.
- * XXX We ignore the memory leak issue.
- * It is claimed that future versions of NSPR will automatically wrap on 
- * the call to PR_GetCurrentThread.
- *
- * XXX We ignore the memory leak issue - i.e. we never call PR_DetachThread.
- *
- */
-#undef _CURRENT_THREAD
-#ifdef JSD_ATTACH_THREAD_HACK
-#define _CURRENT_THREAD(out)                                                  \
-JS_BEGIN_MACRO                                                                \
-    out = (void*) PR_GetCurrentThread();                                      \
-    if(!out)                                                                  \
-        out = (void*) JS_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL,     \
-                                      nullptr);                               \
-    MOZ_ASSERT(out);                                                          \
-JS_END_MACRO
-#else
-#define _CURRENT_THREAD(out)             \
-JS_BEGIN_MACRO                           \
-    out = (void*) PR_GetCurrentThread(); \
-    MOZ_ASSERT(out);                     \
-JS_END_MACRO
-#endif
-
-#ifdef DEBUG
-#define JSD_LOCK_SIG 0x10CC10CC
-void ASSERT_VALID_LOCK(JSDStaticLock* lock)
-{
-    MOZ_ASSERT(lock);
-    MOZ_ASSERT(lock->lock);
-    MOZ_ASSERT(lock->count >= 0);
-    MOZ_ASSERT(lock->sig == (uint16_t) JSD_LOCK_SIG);
-}    
-#else
-#define ASSERT_VALID_LOCK(x) ((void)0)
-#endif
-
-JSDStaticLock*
-jsd_CreateLock()
-{
-    JSDStaticLock* lock;
-
-    if( ! (lock = js_pod_calloc<JSDStaticLock>()) ||
-        ! (lock->lock = PR_NewLock()) )
-    {
-        if(lock)
-        {
-            free(lock);
-            lock = nullptr;
-        }
-    }
-#ifdef DEBUG
-    if(lock) lock->sig = (uint16_t) JSD_LOCK_SIG;
-#endif
-    return lock;
-}    
-
-void
-jsd_Lock(JSDStaticLock* lock)
-{
-    void* me;
-    ASSERT_VALID_LOCK(lock);
-    _CURRENT_THREAD(me);
-
-    if(lock->owner == me)
-    {
-        lock->count++;
-        MOZ_ASSERT(lock->count > 1);
-    }
-    else
-    {
-        PR_Lock(lock->lock);            /* this can block... */
-        MOZ_ASSERT(lock->owner == 0);