Merge m-c to inbound.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 27 Feb 2014 17:33:47 -0500
changeset 171446 87e5cf5b2ccbb02818f5c98770e2a0bff5e7cd6a
parent 171362 6e3b9da3d83f812d595f80447c4efa1c32ea419d (current diff)
parent 171445 c3ce3b51c881501b62527439ddd70016c7ed133c (diff)
child 171448 8daa52f6b3f3f0850e297db7ccb412eb82f45099
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone30.0a1
Merge m-c to inbound.
browser/devtools/commandline/test/browser_cmd_pref.js
browser/devtools/commandline/test/browser_gcli_cli.js
browser/devtools/commandline/test/browser_gcli_completion.js
browser/devtools/commandline/test/browser_gcli_remote.js
browser/devtools/commandline/test/browser_gcli_scratchpad.js
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -857,25 +857,22 @@ pref("media.webspeech.synth.enabled", tr
 
 // Downloads API
 pref("dom.mozDownloads.enabled", true);
 pref("dom.downloads.max_retention_days", 7);
 
 // Inactivity time in milliseconds after which we shut down the OS.File worker.
 pref("osfile.reset_worker_delay", 5000);
 
-// The URL of the Firefox Accounts auth server backend
-pref("identity.fxaccounts.auth.uri", "https://api-accounts.dev.lcip.org/v1");
-
 // APZC preferences.
 //
 // Gaia relies heavily on scroll events for now, so lets fire them
 // more often than the default value (100).
 pref("apz.asyncscroll.throttle", 40);
-pref("apz.pan_repaint_interval", 40);
+pref("apz.pan_repaint_interval", 16);
 
 // Maximum fling velocity in px/ms.  Slower devices may need to reduce this
 // to avoid checkerboarding.  Note, float value must be set as a string.
 pref("apz.max_velocity_pixels_per_ms", "6.0");
 
 // This preference allows FirefoxOS apps (and content, I think) to force
 // the use of software (instead of hardware accelerated) 2D canvases by
 // creating a context like this:
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,23 +14,23 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a9fdec737cdfd41206a332970fea833ec4ca13a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="adaeeb2970c9327e977711c4e18741cfea4baaa6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="022eadd5917615ff00c47eaaafa792b45e9c8a28"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="456499c44d1ef39b602ea02e9ed460b6aab85b44"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="52ca41d9fa6ef88e65d9da52e375716c68d48646"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3a9fdec737cdfd41206a332970fea833ec4ca13a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="adaeeb2970c9327e977711c4e18741cfea4baaa6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="52ca41d9fa6ef88e65d9da52e375716c68d48646"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,23 +14,23 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a9fdec737cdfd41206a332970fea833ec4ca13a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="adaeeb2970c9327e977711c4e18741cfea4baaa6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="022eadd5917615ff00c47eaaafa792b45e9c8a28"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="456499c44d1ef39b602ea02e9ed460b6aab85b44"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="52ca41d9fa6ef88e65d9da52e375716c68d48646"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "remote": "", 
         "branch": "", 
         "revision": ""
     }, 
-    "revision": "cba6294f97cb705143dc4581410518901aa4aa59", 
+    "revision": "761b205f4e8b27f766af4eb35b0457b618d97c52", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,22 +12,22 @@
   <!--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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a9fdec737cdfd41206a332970fea833ec4ca13a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="adaeeb2970c9327e977711c4e18741cfea4baaa6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="52ca41d9fa6ef88e65d9da52e375716c68d48646"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
   <project name="platform/development" path="development" revision="2460485184bc8535440bb63876d4e63ec1b4770c"/>
   <project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
   <project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- 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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a9fdec737cdfd41206a332970fea833ec4ca13a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="adaeeb2970c9327e977711c4e18741cfea4baaa6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -14,22 +14,22 @@
   <!--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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a9fdec737cdfd41206a332970fea833ec4ca13a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="adaeeb2970c9327e977711c4e18741cfea4baaa6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="52ca41d9fa6ef88e65d9da52e375716c68d48646"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
   <project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/>
   <project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/>
   <project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -12,22 +12,22 @@
   <!--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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a9fdec737cdfd41206a332970fea833ec4ca13a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="adaeeb2970c9327e977711c4e18741cfea4baaa6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="52ca41d9fa6ef88e65d9da52e375716c68d48646"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <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"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="575fdbf046e966a5915b1f1e800e5d6ad0ea14c0"/>
   <project name="platform/development" path="development" revision="b1025ec93beeb480caaf3049d171283c3846461d"/>
   <project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
   <project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3a9fdec737cdfd41206a332970fea833ec4ca13a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="adaeeb2970c9327e977711c4e18741cfea4baaa6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="52ca41d9fa6ef88e65d9da52e375716c68d48646"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,22 +12,22 @@
   <!--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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a9fdec737cdfd41206a332970fea833ec4ca13a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="adaeeb2970c9327e977711c4e18741cfea4baaa6"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="52ca41d9fa6ef88e65d9da52e375716c68d48646"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <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="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
   <project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/>
   <project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/>
   <project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1092,17 +1092,16 @@ pref("services.sync.prefs.sync.xpinstall
 #endif
 
 // Disable the error console
 pref("devtools.errorconsole.enabled", false);
 
 // Developer toolbar and GCLI preferences
 pref("devtools.toolbar.enabled", true);
 pref("devtools.toolbar.visible", false);
-pref("devtools.gcli.allowSet", false);
 pref("devtools.commands.dir", "");
 
 // Enable the app manager
 pref("devtools.appmanager.enabled", true);
 pref("devtools.appmanager.lastTab", "help");
 pref("devtools.appmanager.manifestEditor.enabled", true);
 
 // Toolbox preferences
@@ -1381,19 +1380,16 @@ pref("identity.fxaccounts.remote.force_a
 // The remote content URL shown for signin in. Must use HTTPS.
 pref("identity.fxaccounts.remote.signin.uri", "https://accounts.firefox.com/signin?service=sync&context=fx_desktop_v1");
 
 // The URL we take the user to when they opt to "manage" their Firefox Account.
 // Note that this will always need to be in the same TLD as the
 // "identity.fxaccounts.remote.uri" pref.
 pref("identity.fxaccounts.settings.uri", "https://accounts.firefox.com/settings");
 
-// The URL of the Firefox Accounts auth server backend
-pref("identity.fxaccounts.auth.uri", "https://api.accounts.firefox.com/v1");
-
 // On GTK, we now default to showing the menubar only when alt is pressed:
 #ifdef MOZ_WIDGET_GTK
 pref("ui.key.menuAccessKeyFocuses", true);
 #endif
 
 
 // Delete HTTP cache v2 data of users that didn't opt-in manually
 pref("browser.cache.auto_delete_cache_version", 1);
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -35,16 +35,25 @@
                           label="New Non-e10s Window"
                           hidden="true"
                           command="Tools:NonRemoteWindow"/>
                 <menuitem id="menu_openFile"
                           label="&openFileCmd.label;"
                           command="Browser:OpenFile"
                           key="openFileKb"
                           accesskey="&openFileCmd.accesskey;"/>
+#ifdef HAVE_SHELL_SERVICE
+#ifdef XP_WIN
+#ifdef MOZ_METRO
+                <menuitem id="menu_switchToMetro"
+                          label="&switchToMetroCmd2.label;"
+                          oncommand="SwitchToMetro()"/>
+#endif
+#endif
+#endif
                 <menuitem id="menu_close"
                           class="show-only-for-keyboard"
                           label="&closeCmd.label;"
                           key="key_close"
                           accesskey="&closeCmd.accesskey;"
                           command="cmd_close"/>
                 <menuitem id="menu_closeWindow"
                           class="show-only-for-keyboard"
--- a/browser/base/content/browser-webrtcUI.js
+++ b/browser/base/content/browser-webrtcUI.js
@@ -54,10 +54,12 @@ let WebrtcIndicator = {
 
     let browserWindow = streamData.browser.ownerDocument.defaultView;
     if (streamData.tab) {
       browserWindow.gBrowser.selectedTab = streamData.tab;
     } else {
       streamData.browser.focus();
     }
     browserWindow.focus();
+    PopupNotifications.getNotification("webRTC-sharingDevices",
+                                       streamData.browser).reshow();
   }
 }
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -216,16 +216,16 @@
       </svg:mask>
     </svg:defs>
   </svg:svg>
 </panel>
 
 <panel id="widget-overflow"
        role="group"
        type="arrow"
-       level="top"
+       noautofocus="true"
        context="toolbar-context-menu"
        hidden="true">
   <vbox id="widget-overflow-scroller">
     <vbox id="widget-overflow-list" class="widget-overflow-list"
           overflowfortoolbar="nav-bar"/>
   </vbox>
 </panel>
--- a/browser/components/customizableui/content/panelUI.js
+++ b/browser/components/customizableui/content/panelUI.js
@@ -128,16 +128,22 @@ const PanelUI = {
     }
 
     this.ensureReady().then(() => {
       let editControlPlacement = CustomizableUI.getPlacementOfWidget("edit-controls");
       if (editControlPlacement && editControlPlacement.area == CustomizableUI.AREA_PANEL) {
         updateEditUIVisibility();
       }
 
+      let personalBookmarksPlacement = CustomizableUI.getPlacementOfWidget("personal-bookmarks");
+      if (personalBookmarksPlacement &&
+          personalBookmarksPlacement.area == CustomizableUI.AREA_PANEL) {
+        PlacesToolbarHelper.customizeChange();
+      }
+
       let anchor;
       if (!aEvent ||
           aEvent.type == "command") {
         anchor = this.menuButton;
       } else {
         anchor = aEvent.target;
       }
       let iconAnchor =
--- a/browser/components/customizableui/test/browser.ini
+++ b/browser/components/customizableui/test/browser.ini
@@ -60,13 +60,14 @@ skip-if = os == "linux"
 [browser_942581_unregisterArea_keeps_placements.js]
 [browser_943683_migration_test.js]
 [browser_944887_destroyWidget_should_destroy_in_palette.js]
 [browser_945739_showInPrivateBrowsing_customize_mode.js]
 [browser_947987_removable_default.js]
 [browser_948985_non_removable_defaultArea.js]
 [browser_952963_areaType_getter_no_area.js]
 [browser_956602_remove_special_widget.js]
+[browser_968447_bookmarks_toolbar_items_in_panel.js]
 [browser_969427_recreate_destroyed_widget_after_reset.js]
 [browser_969661_character_encoding_navbar_disabled.js]
 [browser_970511_undo_restore_default.js]
 [browser_972267_customizationchange_events.js]
 [browser_panel_toggle.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/test/browser_968447_bookmarks_toolbar_items_in_panel.js
@@ -0,0 +1,32 @@
+/* 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/. */
+
+"use strict";
+
+// Bug 968447 - The Bookmarks Toolbar Items doesn't appear as a
+// normal menu panel button in new windows.
+add_task(function() {
+  const buttonId = "bookmarks-toolbar-placeholder";
+  yield startCustomizing();
+  CustomizableUI.addWidgetToArea("personal-bookmarks", CustomizableUI.AREA_PANEL);
+  yield endCustomizing();
+  yield PanelUI.show();
+  let bookmarksToolbarPlaceholder = document.getElementById(buttonId);
+  ok(bookmarksToolbarPlaceholder.classList.contains("toolbarbutton-1"),
+     "Button should have toolbarbutton-1 class");
+  is(bookmarksToolbarPlaceholder.getAttribute("wrap"), "true",
+     "Button should have the 'wrap' attribute");
+  yield PanelUI.hide();
+
+  let newWin = yield openAndLoadWindow();
+  yield newWin.PanelUI.show();
+  let newWinBookmarksToolbarPlaceholder = newWin.document.getElementById(buttonId);
+  ok(newWinBookmarksToolbarPlaceholder.classList.contains("toolbarbutton-1"),
+     "Button in new window should have toolbarbutton-1 class");
+  is(newWinBookmarksToolbarPlaceholder.getAttribute("wrap"), "true",
+     "Button in new window should have 'wrap' attribute");
+  yield newWin.PanelUI.hide();
+  newWin.close();
+  CustomizableUI.reset();
+});
--- a/browser/devtools/commandline/BuiltinCommands.jsm
+++ b/browser/devtools/commandline/BuiltinCommands.jsm
@@ -11,20 +11,20 @@ const BRAND_SHORT_NAME = Cc["@mozilla.or
 
 this.EXPORTED_SYMBOLS = [ "CmdAddonFlags", "CmdCommands", "DEFAULT_DEBUG_PORT", "connect" ];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
 Cu.import("resource://gre/modules/osfile.jsm");
 
-Cu.import("resource://gre/modules/devtools/gcli.jsm");
 Cu.import("resource://gre/modules/devtools/event-emitter.js");
 
 let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
+let gcli = devtools.require("gcli/index");
 let Telemetry = devtools.require("devtools/shared/telemetry");
 let telemetry = new Telemetry();
 
 XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
                                   "resource:///modules/devtools/gDevTools.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AppCacheUtils",
                                   "resource:///modules/devtools/AppCacheUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
@@ -838,33 +838,29 @@ XPCOMUtils.defineLazyModuleGetter(this, 
   });
 
   /**
    * 'console close' command
    */
   gcli.addCommand({
     name: "console close",
     description: gcli.lookup("consolecloseDesc"),
-    exec: function Command_consoleClose(args, context) {
-      let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
-      let target = devtools.TargetFactory.forTab(gBrowser.selectedTab);
-      return gDevTools.closeToolbox(target);
+    exec: function(args, context) {
+      return gDevTools.closeToolbox(context.environment.target);
     }
   });
 
   /**
    * 'console open' command
    */
   gcli.addCommand({
     name: "console open",
     description: gcli.lookup("consoleopenDesc"),
-    exec: function Command_consoleOpen(args, context) {
-      let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
-      let target = devtools.TargetFactory.forTab(gBrowser.selectedTab);
-      return gDevTools.showToolbox(target, "webconsole");
+    exec: function(args, context) {
+      return gDevTools.showToolbox(context.environment.target, "webconsole");
     }
   });
 }(this));
 
 /* CmdCookie --------------------------------------------------------------- */
 
 (function(module) {
   XPCOMUtils.defineLazyModuleGetter(this, "console",
--- a/browser/devtools/commandline/test/browser.ini
+++ b/browser/devtools/commandline/test/browser.ini
@@ -34,17 +34,19 @@ support-files =
 support-files =
   browser_cmd_jsb_script.jsi
 [browser_cmd_media.js]
 support-files =
   browser_cmd_media.html
 [browser_cmd_pagemod_export.js]
 support-files =
   browser_cmd_pagemod_export.html
-[browser_cmd_pref.js]
+[browser_cmd_pref1.js]
+[browser_cmd_pref2.js]
+[browser_cmd_pref3.js]
 [browser_cmd_restart.js]
 [browser_cmd_screenshot.js]
 support-files =
   browser_cmd_screenshot.html
 [browser_cmd_settings.js]
 [browser_gcli_async.js]
 [browser_gcli_canon.js]
 [browser_gcli_cli.js]
@@ -58,19 +60,20 @@ skip-if = true # Disabled until TZ bug i
 [browser_gcli_history.js]
 [browser_gcli_incomplete.js]
 [browser_gcli_inputter.js]
 [browser_gcli_intro.js]
 [browser_gcli_js.js]
 [browser_gcli_keyboard1.js]
 [browser_gcli_keyboard2.js]
 [browser_gcli_keyboard3.js]
+[browser_gcli_keyboard4.js]
+[browser_gcli_keyboard5.js]
 [browser_gcli_menu.js]
 [browser_gcli_node.js]
-[browser_gcli_remote.js]
 [browser_gcli_resource.js]
-[browser_gcli_scratchpad.js]
+[browser_gcli_short.js]
 [browser_gcli_spell.js]
 [browser_gcli_split.js]
 [browser_gcli_tokenize.js]
 [browser_gcli_tooltip.js]
 [browser_gcli_types.js]
 [browser_gcli_util.js]
--- a/browser/devtools/commandline/test/browser_cmd_addon.js
+++ b/browser/devtools/commandline/test/browser_cmd_addon.js
@@ -5,17 +5,17 @@
 
 let CmdAddonFlags = (Cu.import("resource:///modules/devtools/BuiltinCommands.jsm", {})).CmdAddonFlags;
 
 let tests = {};
 
 function test() {
   helpers.addTabWithToolbar("about:blank", function(options) {
     return helpers.runTests(options, tests);
-  }).then(finish);
+  }).then(finish, helpers.handleError);
 }
 
 tests.gatTest = function(options) {
   let deferred = promise.defer();
 
   let onGatReady = function() {
     Services.obs.removeObserver(onGatReady, "gcli_addon_commands_ready");
     info("gcli_addon_commands_ready notification received, running tests");
@@ -128,19 +128,17 @@ tests.gatTest = function(options) {
           }
         },
         exec: {
           output: 'Test Plug-in 1.0.0.0 enabled.'
         }
       }
     ]);
 
-    auditDone.then(function() {
-      deferred.resolve();
-    });
+    auditDone.then(deferred.resolve, deferred.reject);
   };
 
   Services.obs.addObserver(onGatReady, "gcli_addon_commands_ready", false);
 
   if (CmdAddonFlags.addonsLoaded) {
     info("The call to AddonManager.getAllAddons in BuiltinCommands.jsm is done.");
     info("Send the gcli_addon_commands_ready notification ourselves.");
 
--- a/browser/devtools/commandline/test/browser_cmd_appcache_invalid.js
+++ b/browser/devtools/commandline/test/browser_cmd_appcache_invalid.js
@@ -2,101 +2,99 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the appcache validate works as they should with an invalid
 // manifest.
 
 const TEST_URI = "http://sub1.test1.example.com/browser/browser/devtools/commandline/" +
                  "test/browser_cmd_appcache_invalid_index.html";
 
-let tests = {};
+function test() {
+  return Task.spawn(spawnTest).then(finish, helpers.handleError);
+}
 
-function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    let deferred = promise.defer();
+function spawnTest() {
+  let options = yield helpers.openTab(TEST_URI);
+  info("window open");
+
+  // Wait for site to be cached.
+  yield helpers.listenOnce(gBrowser.contentWindow.applicationCache, 'error');
+  info("applicationCache error happened");
 
-    // Wait for site to be cached.
-    gBrowser.contentWindow.applicationCache.addEventListener('error', function BCAI_error() {
-      gBrowser.contentWindow.applicationCache.removeEventListener('error', BCAI_error);
+  yield helpers.openToolbar(options);
+  info("toolbar open");
 
-      info("Site now cached, running tests.");
+  // Pages containing an appcache the notification bar gives options to allow
+  // or deny permission for the app to save data offline. Let's click Allow.
+  let notificationID = "offline-app-requested-sub1.test1.example.com";
+  let notification = PopupNotifications.getNotification(notificationID, gBrowser.selectedBrowser);
+
+  if (notification) {
+    info("Authorizing offline storage.");
+    notification.mainAction.callback();
+  } else {
+    info("No notification box is available.");
+  }
 
-      deferred.resolve(helpers.audit(options, [
-        {
-          setup: 'appcache validate',
-          check: {
-            input:  'appcache validate',
-            markup: 'VVVVVVVVVVVVVVVVV',
-            status: 'VALID',
-            args: {}
-          },
-          exec: {
-            completed: false,
-            output: [
-              /Manifest has a character encoding of ISO-8859-1\. Manifests must have the utf-8 character encoding\./,
-              /The first line of the manifest must be "CACHE MANIFEST" at line 1\./,
-              /"CACHE MANIFEST" is only valid on the first line but was found at line 3\./,
-              /images\/sound-icon\.png points to a resource that is not available at line 9\./,
-              /images\/background\.png points to a resource that is not available at line 10\./,
-              /NETWORK section line 13 \(\/checking\.cgi\) prevents caching of line 13 \(\/checking\.cgi\) in the NETWORK section\./,
-              /\/checking\.cgi points to a resource that is not available at line 13\./,
-              /Asterisk \(\*\) incorrectly used in the NETWORK section at line 14\. If a line in the NETWORK section contains only a single asterisk character, then any URI not listed in the manifest will be treated as if the URI was listed in the NETWORK section\. Otherwise such URIs will be treated as unavailable\. Other uses of the \* character are prohibited/,
-              /\.\.\/rel\.html points to a resource that is not available at line 17\./,
-              /\.\.\/\.\.\/rel\.html points to a resource that is not available at line 18\./,
-              /\.\.\/\.\.\/\.\.\/rel\.html points to a resource that is not available at line 19\./,
-              /\.\.\/\.\.\/\.\.\/\.\.\/rel\.html points to a resource that is not available at line 20\./,
-              /\.\.\/\.\.\/\.\.\/\.\.\/\.\.\/rel\.html points to a resource that is not available at line 21\./,
-              /\/\.\.\/ is not a valid URI prefix at line 22\./,
-              /\/test\.css points to a resource that is not available at line 23\./,
-              /\/test\.js points to a resource that is not available at line 24\./,
-              /test\.png points to a resource that is not available at line 25\./,
-              /\/main\/features\.js points to a resource that is not available at line 27\./,
-              /\/main\/settings\/index\.css points to a resource that is not available at line 28\./,
-              /http:\/\/example\.com\/scene\.jpg points to a resource that is not available at line 29\./,
-              /\/section1\/blockedbyfallback\.html points to a resource that is not available at line 30\./,
-              /http:\/\/example\.com\/images\/world\.jpg points to a resource that is not available at line 31\./,
-              /\/section2\/blockedbyfallback\.html points to a resource that is not available at line 32\./,
-              /\/main\/home points to a resource that is not available at line 34\./,
-              /main\/app\.js points to a resource that is not available at line 35\./,
-              /\/settings\/home points to a resource that is not available at line 37\./,
-              /\/settings\/app\.js points to a resource that is not available at line 38\./,
-              /The file http:\/\/sub1\.test1\.example\.com\/browser\/browser\/devtools\/commandline\/test\/browser_cmd_appcache_invalid_page3\.html was modified after http:\/\/sub1\.test1\.example\.com\/browser\/browser\/devtools\/commandline\/test\/browser_cmd_appcache_invalid_appcache\.appcache\. Unless the text in the manifest file is changed the cached version will be used instead at line 39\./,
-              /browser_cmd_appcache_invalid_page3\.html has cache-control set to no-store\. This will prevent the application cache from storing the file at line 39\./,
-              /http:\/\/example\.com\/logo\.png points to a resource that is not available at line 40\./,
-              /http:\/\/example\.com\/check\.png points to a resource that is not available at line 41\./,
-              /Spaces in URIs need to be replaced with % at line 42\./,
-              /http:\/\/example\.com\/cr oss\.png points to a resource that is not available at line 42\./,
-              /Asterisk \(\*\) incorrectly used in the CACHE section at line 43\. If a line in the NETWORK section contains only a single asterisk character, then any URI not listed in the manifest will be treated as if the URI was listed in the NETWORK section\. Otherwise such URIs will be treated as unavailable\. Other uses of the \* character are prohibited/,
-              /The SETTINGS section may only contain a single value, "prefer-online" or "fast" at line 47\./,
-              /FALLBACK section line 50 \(\/section1\/ \/offline1\.html\) prevents caching of line 30 \(\/section1\/blockedbyfallback\.html\) in the CACHE section\./,
-              /\/offline1\.html points to a resource that is not available at line 50\./,
-              /FALLBACK section line 51 \(\/section2\/ offline2\.html\) prevents caching of line 32 \(\/section2\/blockedbyfallback\.html\) in the CACHE section\./,
-              /offline2\.html points to a resource that is not available at line 51\./,
-              /Only two URIs separated by spaces are allowed in the FALLBACK section at line 52\./,
-              /Asterisk \(\*\) incorrectly used in the FALLBACK section at line 53\. URIs in the FALLBACK section simply need to match a prefix of the request URI\./,
-              /offline3\.html points to a resource that is not available at line 53\./,
-              /Invalid section name \(BLAH\) at line 55\./,
-              /Only two URIs separated by spaces are allowed in the FALLBACK section at line 55\./
-            ]
-          },
-        },
-      ]));
-    });
+  info("Site now cached, running tests.");
+  yield helpers.audit(options, [
+    {
+      setup: 'appcache validate',
+      check: {
+        input:  'appcache validate',
+        markup: 'VVVVVVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {}
+      },
+      exec: {
+        output: [
+          /Manifest has a character encoding of ISO-8859-1\. Manifests must have the utf-8 character encoding\./,
+          /The first line of the manifest must be "CACHE MANIFEST" at line 1\./,
+          /"CACHE MANIFEST" is only valid on the first line but was found at line 3\./,
+          /images\/sound-icon\.png points to a resource that is not available at line 9\./,
+          /images\/background\.png points to a resource that is not available at line 10\./,
+          /NETWORK section line 13 \(\/checking\.cgi\) prevents caching of line 13 \(\/checking\.cgi\) in the NETWORK section\./,
+          /\/checking\.cgi points to a resource that is not available at line 13\./,
+          /Asterisk \(\*\) incorrectly used in the NETWORK section at line 14\. If a line in the NETWORK section contains only a single asterisk character, then any URI not listed in the manifest will be treated as if the URI was listed in the NETWORK section\. Otherwise such URIs will be treated as unavailable\. Other uses of the \* character are prohibited/,
+          /\.\.\/rel\.html points to a resource that is not available at line 17\./,
+          /\.\.\/\.\.\/rel\.html points to a resource that is not available at line 18\./,
+          /\.\.\/\.\.\/\.\.\/rel\.html points to a resource that is not available at line 19\./,
+          /\.\.\/\.\.\/\.\.\/\.\.\/rel\.html points to a resource that is not available at line 20\./,
+          /\.\.\/\.\.\/\.\.\/\.\.\/\.\.\/rel\.html points to a resource that is not available at line 21\./,
+          /\/\.\.\/ is not a valid URI prefix at line 22\./,
+          /\/test\.css points to a resource that is not available at line 23\./,
+          /\/test\.js points to a resource that is not available at line 24\./,
+          /test\.png points to a resource that is not available at line 25\./,
+          /\/main\/features\.js points to a resource that is not available at line 27\./,
+          /\/main\/settings\/index\.css points to a resource that is not available at line 28\./,
+          /http:\/\/example\.com\/scene\.jpg points to a resource that is not available at line 29\./,
+          /\/section1\/blockedbyfallback\.html points to a resource that is not available at line 30\./,
+          /http:\/\/example\.com\/images\/world\.jpg points to a resource that is not available at line 31\./,
+          /\/section2\/blockedbyfallback\.html points to a resource that is not available at line 32\./,
+          /\/main\/home points to a resource that is not available at line 34\./,
+          /main\/app\.js points to a resource that is not available at line 35\./,
+          /\/settings\/home points to a resource that is not available at line 37\./,
+          /\/settings\/app\.js points to a resource that is not available at line 38\./,
+          /The file http:\/\/sub1\.test1\.example\.com\/browser\/browser\/devtools\/commandline\/test\/browser_cmd_appcache_invalid_page3\.html was modified after http:\/\/sub1\.test1\.example\.com\/browser\/browser\/devtools\/commandline\/test\/browser_cmd_appcache_invalid_appcache\.appcache\. Unless the text in the manifest file is changed the cached version will be used instead at line 39\./,
+          /browser_cmd_appcache_invalid_page3\.html has cache-control set to no-store\. This will prevent the application cache from storing the file at line 39\./,
+          /http:\/\/example\.com\/logo\.png points to a resource that is not available at line 40\./,
+          /http:\/\/example\.com\/check\.png points to a resource that is not available at line 41\./,
+          /Spaces in URIs need to be replaced with % at line 42\./,
+          /http:\/\/example\.com\/cr oss\.png points to a resource that is not available at line 42\./,
+          /Asterisk \(\*\) incorrectly used in the CACHE section at line 43\. If a line in the NETWORK section contains only a single asterisk character, then any URI not listed in the manifest will be treated as if the URI was listed in the NETWORK section\. Otherwise such URIs will be treated as unavailable\. Other uses of the \* character are prohibited/,
+          /The SETTINGS section may only contain a single value, "prefer-online" or "fast" at line 47\./,
+          /FALLBACK section line 50 \(\/section1\/ \/offline1\.html\) prevents caching of line 30 \(\/section1\/blockedbyfallback\.html\) in the CACHE section\./,
+          /\/offline1\.html points to a resource that is not available at line 50\./,
+          /FALLBACK section line 51 \(\/section2\/ offline2\.html\) prevents caching of line 32 \(\/section2\/blockedbyfallback\.html\) in the CACHE section\./,
+          /offline2\.html points to a resource that is not available at line 51\./,
+          /Only two URIs separated by spaces are allowed in the FALLBACK section at line 52\./,
+          /Asterisk \(\*\) incorrectly used in the FALLBACK section at line 53\. URIs in the FALLBACK section simply need to match a prefix of the request URI\./,
+          /offline3\.html points to a resource that is not available at line 53\./,
+          /Invalid section name \(BLAH\) at line 55\./,
+          /Only two URIs separated by spaces are allowed in the FALLBACK section at line 55\./
+        ]
+      },
+    },
+  ]);
 
-    acceptOfflineCachePrompt();
-
-    return deferred.promise;
-  }).then(finish);
-
-  function acceptOfflineCachePrompt() {
-    // Pages containing an appcache the notification bar gives options to allow
-    // or deny permission for the app to save data offline. Let's click Allow.
-    let notificationID = "offline-app-requested-sub1.test1.example.com";
-    let notification = PopupNotifications.getNotification(notificationID, gBrowser.selectedBrowser);
-
-    if (notification) {
-      info("Authorizing offline storage.");
-      notification.mainAction.callback();
-    } else {
-      info("No notification box is available.");
-    }
-  }
+  yield helpers.closeToolbar(options);
+  yield helpers.closeTab(options);
 }
--- a/browser/devtools/commandline/test/browser_cmd_appcache_valid.js
+++ b/browser/devtools/commandline/test/browser_cmd_appcache_valid.js
@@ -1,179 +1,173 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the appcache commands works as they should
 
 const TEST_URI = "http://sub1.test2.example.com/browser/browser/devtools/" +
                  "commandline/test/browser_cmd_appcache_valid_index.html";
-let tests = {};
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    let deferred = promise.defer();
+  return Task.spawn(spawnTest).then(finish, helpers.handleError);
+}
 
-    info("adding cache listener.");
+function spawnTest() {
+  let options = yield helpers.openTab(TEST_URI);
+  yield helpers.openToolbar(options);
+
+  info("adding cache listener.");
+
+  // Wait for site to be cached.
+  yield helpers.listenOnce(gBrowser.contentWindow.applicationCache, 'cached');
 
-    // Wait for site to be cached.
-    gBrowser.contentWindow.applicationCache.addEventListener('cached', function BCAV_cached() {
-      gBrowser.contentWindow.applicationCache.removeEventListener('cached', BCAV_cached);
+  // Pages containing an appcache the notification bar gives options to allow
+  // or deny permission for the app to save data offline. Let's click Allow.
+  let notificationID = "offline-app-requested-sub1.test2.example.com";
+  let notification = PopupNotifications.getNotification(notificationID, gBrowser.selectedBrowser);
 
-      info("Site now cached, running tests.");
+  if (notification) {
+    info("Authorizing offline storage.");
+    notification.mainAction.callback();
+  } else {
+    info("No notification box is available.");
+  }
 
-      deferred.resolve(helpers.audit(options, [
-        {
-          setup: 'appcache',
-          check: {
-            input:  'appcache',
-            markup: 'IIIIIIII',
-            status: 'ERROR',
-            args: {}
-          },
-        },
+  info("Site now cached, running tests.");
+  yield helpers.audit(options, [
+    {
+      setup: 'appcache',
+      check: {
+        input:  'appcache',
+        markup: 'IIIIIIII',
+        status: 'ERROR',
+        args: {}
+      },
+    },
 
-        {
-          setup: function() {
-            Services.prefs.setBoolPref("browser.cache.disk.enable", false);
-            helpers.setInput(options, 'appcache list', 13);
-          },
-          check: {
-            input:  'appcache list',
-            markup: 'VVVVVVVVVVVVV',
-            status: 'VALID',
-            args: {},
-          },
-          exec: {
-            output: [ /cache is disabled/ ]
-          },
-          post: function(output) {
-            Services.prefs.setBoolPref("browser.cache.disk.enable", true);
-          }
-        },
+    {
+      setup: function() {
+        Services.prefs.setBoolPref("browser.cache.disk.enable", false);
+        return helpers.setInput(options, 'appcache list', 13);
+      },
+      check: {
+        input:  'appcache list',
+        markup: 'VVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {},
+      },
+      exec: {
+        output: [ /cache is disabled/ ]
+      },
+      post: function(output) {
+        Services.prefs.setBoolPref("browser.cache.disk.enable", true);
+      }
+    },
 
-        {
-          setup: 'appcache list',
-          check: {
-            input:  'appcache list',
-            markup: 'VVVVVVVVVVVVV',
-            status: 'VALID',
-            args: {},
-          },
-          exec: {
-            output: [ /index/, /page1/, /page2/, /page3/ ]
-          },
-        },
+    {
+      setup: 'appcache list',
+      check: {
+        input:  'appcache list',
+        markup: 'VVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {},
+      },
+      exec: {
+        output: [ /index/, /page1/, /page2/, /page3/ ]
+      },
+    },
 
-        {
-          setup: 'appcache list page',
-          check: {
-            input:  'appcache list page',
-            markup: 'VVVVVVVVVVVVVVVVVV',
-            status: 'VALID',
-            args: {
-              search: { value: 'page' },
-            }
-          },
-          exec: {
-            output: [ /page1/, /page2/, /page3/ ]
-          },
-          post: function(output, text) {
-            ok(!text.contains("index"), "index is not contained in output");
-          }
-        },
+    {
+      setup: 'appcache list page',
+      check: {
+        input:  'appcache list page',
+        markup: 'VVVVVVVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {
+          search: { value: 'page' },
+        }
+      },
+      exec: {
+        output: [ /page1/, /page2/, /page3/ ]
+      },
+      post: function(output, text) {
+        ok(!text.contains("index"), "index is not contained in output");
+      }
+    },
 
-        {
-          setup: 'appcache validate',
-          check: {
-            input:  'appcache validate',
-            markup: 'VVVVVVVVVVVVVVVVV',
-            status: 'VALID',
-            args: {}
-          },
-          exec: {
-            completed: false,
-            output: [ /successfully/ ]
+    {
+      setup: 'appcache validate',
+      check: {
+        input:  'appcache validate',
+        markup: 'VVVVVVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {}
+      },
+      exec: {
+        output: [ /successfully/ ]
+      },
+    },
+
+    {
+      setup: 'appcache validate ' + TEST_URI,
+      check: {
+        input:  'appcache validate ' + TEST_URI,
+              // appcache validate http://sub1.test2.example.com/browser/browser/devtools/commandline/test/browser_cmd_appcache_valid_index.html
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {
+          uri: {
+            value: TEST_URI
           },
-        },
+        }
+      },
+      exec: {
+        output: [ /successfully/ ]
+      },
+    },
 
-        {
-          setup: 'appcache validate ' + TEST_URI,
-          check: {
-            input:  'appcache validate ' + TEST_URI,
-                  // appcache validate http://sub1.test2.example.com/browser/browser/devtools/commandline/test/browser_cmd_appcache_valid_index.html
-            markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
-            status: 'VALID',
-            args: {
-              uri: {
-                value: TEST_URI
-              },
-            }
-          },
-          exec: {
-            completed: false,
-            output: [ /successfully/ ]
-          },
-        },
-
-        {
-          setup: 'appcache clear',
-          check: {
-            input:  'appcache clear',
-            markup: 'VVVVVVVVVVVVVV',
-            status: 'VALID',
-            args: {},
-          },
-          exec: {
-            output: [ /successfully/ ]
-          },
-        },
+    {
+      setup: 'appcache clear',
+      check: {
+        input:  'appcache clear',
+        markup: 'VVVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {},
+      },
+      exec: {
+        output: [ /successfully/ ]
+      },
+    },
 
-        {
-          setup: 'appcache list',
-          check: {
-            input:  'appcache list',
-            markup: 'VVVVVVVVVVVVV',
-            status: 'VALID',
-            args: {},
-          },
-          exec: {
-            output: [ /no results/ ]
-          },
-          post: function(output, text) {
-            ok(!text.contains("index"), "index is not contained in output");
-            ok(!text.contains("page1"), "page1 is not contained in output");
-            ok(!text.contains("page2"), "page1 is not contained in output");
-            ok(!text.contains("page3"), "page1 is not contained in output");
-          }
-        },
+    {
+      setup: 'appcache list',
+      check: {
+        input:  'appcache list',
+        markup: 'VVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {},
+      },
+      exec: {
+        output: [ /no results/ ]
+      },
+      post: function(output, text) {
+        ok(!text.contains("index"), "index is not contained in output");
+        ok(!text.contains("page1"), "page1 is not contained in output");
+        ok(!text.contains("page2"), "page1 is not contained in output");
+        ok(!text.contains("page3"), "page1 is not contained in output");
+      }
+    },
 
-        {
-          setup: 'appcache viewentry --key ' + TEST_URI,
-          check: {
-            input:  'appcache viewentry --key ' + TEST_URI,
-                  // appcache viewentry --key http://sub1.test2.example.com/browser/browser/devtools/commandline/test/browser_cmd_appcache_valid_index.html
-            markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
-            status: 'VALID',
-            args: {}
-          },
-        },
-      ]));
-    });
-
-    acceptOfflineCachePrompt();
+    {
+      setup: 'appcache viewentry --key ' + TEST_URI,
+      check: {
+        input:  'appcache viewentry --key ' + TEST_URI,
+              // appcache viewentry --key http://sub1.test2.example.com/browser/browser/devtools/commandline/test/browser_cmd_appcache_valid_index.html
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {}
+      },
+    },
+  ]);
 
-    return deferred.promise;
-  }).then(finish);
-
-  function acceptOfflineCachePrompt() {
-    // Pages containing an appcache the notification bar gives options to allow
-    // or deny permission for the app to save data offline. Let's click Allow.
-    let notificationID = "offline-app-requested-sub1.test2.example.com";
-    let notification = PopupNotifications.getNotification(notificationID, gBrowser.selectedBrowser);
-
-    if (notification) {
-      info("Authorizing offline storage.");
-      notification.mainAction.callback();
-    } else {
-      info("No notification box is available.");
-    }
-  }
+  yield helpers.closeToolbar(options);
+  yield helpers.closeTab(options);
 }
--- a/browser/devtools/commandline/test/browser_cmd_calllog.js
+++ b/browser/devtools/commandline/test/browser_cmd_calllog.js
@@ -3,19 +3,25 @@
 
 // Tests that the calllog commands works as they should
 
 const TEST_URI = "data:text/html;charset=utf-8,gcli-calllog";
 
 let tests = {};
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, tests);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+
+    yield helpers.runTests(options, tests);
+
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 tests.testCallLogStatus = function(options) {
   return helpers.audit(options, [
     {
       setup: "calllog",
       check: {
         input:  'calllog',
@@ -92,18 +98,19 @@ tests.testCallLogExec = function(options
       }
     },
     {
       name: "calllog start",
       setup: function() {
         // This test wants to be in a different event
         var deferred = promise.defer();
         executeSoon(function() {
-          helpers.setInput(options, "calllog start");
-          deferred.resolve();
+          helpers.setInput(options, "calllog start").then(() => {
+            deferred.resolve();
+          });
         });
         return deferred.promise;
       },
       exec: {
         output: /Call logging started/,
       },
     },
   ]);
--- a/browser/devtools/commandline/test/browser_cmd_calllog_chrome.js
+++ b/browser/devtools/commandline/test/browser_cmd_calllog_chrome.js
@@ -3,19 +3,25 @@
 
 // Tests that the calllog commands works as they should
 
 const TEST_URI = "data:text/html;charset=utf-8,cmd-calllog-chrome";
 
 let tests = {};
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, tests);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+
+    yield helpers.runTests(options, tests);
+
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 tests.testCallLogStatus = function(options) {
   return helpers.audit(options, [
     {
       setup: "calllog",
       check: {
         status: "ERROR",
@@ -78,17 +84,16 @@ tests.testCallLogExec = function(options
           let labels = hud.jsterm.outputNode.querySelectorAll(".webconsole-msg-output");
           is(labels.length, 0, "no output in console");
         }
       },
       {
         setup: "console close",
         exec: {
           output: '',
-          completed: false,
         },
       },
     ]).then(function() {
       deferred.resolve();
     });
   }
   Services.obs.addObserver(onWebConsoleOpen, "web-console-created", false);
 
--- a/browser/devtools/commandline/test/browser_cmd_commands.js
+++ b/browser/devtools/commandline/test/browser_cmd_commands.js
@@ -1,73 +1,61 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test various GCLI commands
 
 const TEST_URI = "data:text/html;charset=utf-8,gcli-commands";
 
-let tests = {};
-
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, tests);
-  }).then(finish);
+  return Task.spawn(spawnTest).then(finish, helpers.handleError);
 }
 
-tests.testConsole = function(options) {
-  let deferred = promise.defer();
-  let hud = null;
-
-  let onWebConsoleOpen = function(subject) {
-    Services.obs.removeObserver(onWebConsoleOpen, "web-console-created");
-
-    subject.QueryInterface(Ci.nsISupportsString);
-    hud = HUDService.getHudReferenceById(subject.data);
-    ok(hud, "console open");
-
-    hud.jsterm.execute("pprint(window)", onExecute);
-  }
-  Services.obs.addObserver(onWebConsoleOpen, "web-console-created", false);
-
-  function onExecute (msg) {
-    ok(msg, "output for pprint(window)");
-
-    hud.jsterm.once("messages-cleared", onClear);
+function spawnTest() {
+  let options = yield helpers.openTab(TEST_URI);
+  yield helpers.openToolbar(options);
 
-    helpers.audit(options, [
-      {
-        setup: "console clear",
-        exec: {
-          output: ""
-        },
-      }
-    ]);
-  }
-
-  function onClear() {
-    let labels = hud.outputNode.querySelectorAll(".message");
-    is(labels.length, 0, "no output in console");
-
-    helpers.audit(options, [
-      {
-        setup: "console close",
-        exec: {
-          output: ""
-        },
-        post: function() {
-          ok(!HUDService.getHudReferenceById(hud.hudId), "console closed");
-        }
-      }
-    ]).then(function() {
-      deferred.resolve();
-    });
-  }
+  let subjectPromise = helpers.observeOnce("web-console-created");
 
   helpers.audit(options, [
     {
       setup: "console open",
       exec: { }
     }
   ]);
 
-  return deferred.promise;
-};
+  let subject = yield subjectPromise;
+
+  subject.QueryInterface(Ci.nsISupportsString);
+  let hud = HUDService.getHudReferenceById(subject.data);
+  ok(hud, "console open");
+
+  let jstermExecute = helpers.promiseify(hud.jsterm.execute, hud.jsterm);
+  let msg = yield jstermExecute("pprint(window)");
+
+  ok(msg, "output for pprint(window)");
+
+  let oncePromise = hud.jsterm.once("messages-cleared");
+
+  helpers.audit(options, [
+    {
+      setup: "console clear",
+      exec: { output: "" }
+    }
+  ]);
+
+  yield oncePromise;
+
+  let labels = hud.outputNode.querySelectorAll(".message");
+  is(labels.length, 0, "no output in console");
+
+  yield helpers.audit(options, [
+    {
+      setup: "console close",
+      exec: { output: "" }
+    }
+  ]);
+
+  ok(!HUDService.getHudReferenceById(hud.hudId), "console closed");
+
+  yield helpers.closeToolbar(options);
+  yield helpers.closeTab(options);
+}
--- a/browser/devtools/commandline/test/browser_cmd_cookie.js
+++ b/browser/devtools/commandline/test/browser_cmd_cookie.js
@@ -161,10 +161,10 @@ function test() {
           ok(!text.contains("zip"), "");
           ok(!text.contains("zop"), "");
           ok(!text.contains("zup"), "");
           ok(!text.contains("banana"), "");
           ok(!text.contains("Edit"), "");
         }
       },
     ]);
-  }).then(finish);
+  }).then(finish, helpers.handleError);
 }
--- a/browser/devtools/commandline/test/browser_cmd_jsb.js
+++ b/browser/devtools/commandline/test/browser_cmd_jsb.js
@@ -1,28 +1,27 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the jsb command works as it should
 
 const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
                  "test/browser_cmd_jsb_script.jsi";
 
-let scratchpadWin = null;
-let scratchpad = null;
-let tests = {};
-
 function test() {
-  helpers.addTabWithToolbar("about:blank", function(options) {
-    return helpers.runTests(options, tests);
-  }).then(finish);
+  return Task.spawn(testTask).then(finish, helpers.handleError);
 }
 
-tests.jsbTest = function(options) {
+function testTask() {
+  let options = yield helpers.openTab("about:blank");
+  yield helpers.openToolbar(options);
+
   let deferred = promise.defer();
+  let scratchpadWin = null;
+  let scratchpad = null;
 
   let observer = {
     onReady: function() {
       scratchpad.removeObserver(observer);
 
       let result = scratchpad.getText();
       result = result.replace(/[\r\n]]*/g, "\n");
       let correct = "function somefunc() {\n" +
@@ -72,15 +71,17 @@ tests.jsbTest = function(options) {
         markup: 'VVV',
         status: 'ERROR'
       }
     },
     {
       setup: 'jsb ' + TEST_URI,
       // Should result in a new window, which should fire onReady (eventually)
       exec: {
-        completed: false
       }
     }
   ]);
 
-  return deferred.promise;
-};
+  yield deferred.promise;
+
+  yield helpers.closeToolbar(options);
+  yield helpers.closeTab(options);
+}
--- a/browser/devtools/commandline/test/browser_cmd_media.js
+++ b/browser/devtools/commandline/test/browser_cmd_media.js
@@ -69,12 +69,18 @@ let tests = {
           is(style.backgroundColor, "rgb(255, 255, 255)", "media reset");
         }
       }
     ]);
   }
 };
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, tests);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+
+    yield helpers.runTests(options, tests);
+
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
--- a/browser/devtools/commandline/test/browser_cmd_pagemod_export.js
+++ b/browser/devtools/commandline/test/browser_cmd_pagemod_export.js
@@ -2,375 +2,371 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the inspect command works as it should
 
 const TEST_URI = "http://example.com/browser/browser/devtools/commandline/"+
                  "test/browser_cmd_pagemod_export.html";
 
 function test() {
-  let initialHtml = "";
-
-  var tests = {};
-
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    initialHtml = content.document.documentElement.innerHTML;
+  return Task.spawn(spawnTest).then(finish, helpers.handleError);
+}
 
-    return helpers.runTests(options, tests);
-  }).then(finish);
+function spawnTest() {
+  // Setup
+  let options = yield helpers.openTab(TEST_URI);
+  yield helpers.openToolbar(options);
 
-  function getContent(options) {
-    return options.document.documentElement.innerHTML;
-  }
-
-  function resetContent(options) {
+  const documentElement = options.document.documentElement;
+  const initialHtml = documentElement.innerHTML;
+  function resetContent() {
     options.document.documentElement.innerHTML = initialHtml;
   }
 
-  tests.testExportHtml = function(options) {
-    let oldOpen = options.window.open;
-    let openURL = "";
-    options.window.open = function(url) {
-      // The URL is a data: URL that contains the document source
-      openURL = decodeURIComponent(url);
-    };
-
-    return helpers.audit(options, [
-      {
-        setup: 'export html',
-        check: {
-          input:  'export html',
-          hints:             '',
-          markup: 'VVVVVVVVVVV',
-          status: 'VALID'
-        },
-        exec: {
-          output: ''
-        },
-        post: function() {
-          isnot(openURL.indexOf('<html lang="en">'), -1, "export html works: <html>");
-          isnot(openURL.indexOf("<title>GCLI"), -1, "export html works: <title>");
-          isnot(openURL.indexOf('<p id="someid">#'), -1, "export html works: <p>");
-
-           options.window.open = oldOpen;
-        }
-      }
-    ]);
-  };
-
-  tests.testPageModReplace = function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pagemod replace',
-        check: {
-          input:  'pagemod replace',
-          hints:                 ' <search> <replace> [ignoreCase] [selector] [root] [attrOnly] [contentOnly] [attributes]',
-          markup: 'VVVVVVVVVVVVVVV',
-          status: 'ERROR'
-        }
-      },
-      {
-        setup: 'pagemod replace some foo',
-        check: {
-          input:  'pagemod replace some foo',
-          hints:                          ' [ignoreCase] [selector] [root] [attrOnly] [contentOnly] [attributes]',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
-          status: 'VALID'
-        }
-      },
-      {
-        setup: 'pagemod replace some foo true',
-        check: {
-          input:  'pagemod replace some foo true',
-          hints:                               ' [selector] [root] [attrOnly] [contentOnly] [attributes]',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
-          status: 'VALID'
-        }
-      },
-      {
-        setup: 'pagemod replace some foo true --attrOnly',
-        check: {
-          input:  'pagemod replace some foo true --attrOnly',
-          hints:                                          ' [selector] [root] [contentOnly] [attributes]',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
-          status: 'VALID'
-        }
-      },
-      {
-        setup: 'pagemod replace sOme foOBar',
-        exec: {
-          output: /^[^:]+: 13\. [^:]+: 0\. [^:]+: 0\.\s*$/
-        },
-        post: function() {
-          is(getContent(options), initialHtml, "no change in the page");
-        }
-      },
-      {
-        setup: 'pagemod replace sOme foOBar true',
-        exec: {
-          output: /^[^:]+: 13\. [^:]+: 2\. [^:]+: 2\.\s*$/
-        },
-        post: function() {
-          let html = getContent(options);
-
-          isnot(html.indexOf('<p class="foOBarclass">.foOBarclass'), -1,
-                ".someclass changed to .foOBarclass");
-          isnot(html.indexOf('<p id="foOBarid">#foOBarid'), -1,
-                "#someid changed to #foOBarid");
-
-          resetContent(options);
-        }
-      },
-      {
-        setup: 'pagemod replace some foobar --contentOnly',
-        exec: {
-          output: /^[^:]+: 13\. [^:]+: 2\. [^:]+: 0\.\s*$/
-        },
-        post: function() {
-          let html = getContent(options);
-
-          isnot(html.indexOf('<p class="someclass">.foobarclass'), -1,
-                ".someclass changed to .foobarclass (content only)");
-          isnot(html.indexOf('<p id="someid">#foobarid'), -1,
-                "#someid changed to #foobarid (content only)");
-
-          resetContent(options);
-        }
-      },
-      {
-        setup: 'pagemod replace some foobar --attrOnly',
-        exec: {
-          output: /^[^:]+: 13\. [^:]+: 0\. [^:]+: 2\.\s*$/
-        },
-        post: function() {
-          let html = getContent(options);
-
-          isnot(html.indexOf('<p class="foobarclass">.someclass'), -1,
-                ".someclass changed to .foobarclass (attr only)");
-          isnot(html.indexOf('<p id="foobarid">#someid'), -1,
-                "#someid changed to #foobarid (attr only)");
-
-          resetContent(options);
-        }
-      },
-      {
-        setup: 'pagemod replace some foobar --root head',
-        exec: {
-          output: /^[^:]+: 2\. [^:]+: 0\. [^:]+: 0\.\s*$/
-        },
-        post: function() {
-          is(getContent(options), initialHtml, "nothing changed");
-        }
-      },
-      {
-        setup: 'pagemod replace some foobar --selector .someclass,div,span',
-        exec: {
-          output: /^[^:]+: 4\. [^:]+: 1\. [^:]+: 1\.\s*$/
-        },
-        post: function() {
-          let html = getContent(options);
-
-          isnot(html.indexOf('<p class="foobarclass">.foobarclass'), -1,
-                ".someclass changed to .foobarclass");
-          isnot(html.indexOf('<p id="someid">#someid'), -1,
-                "#someid did not change");
-
-          resetContent(options);
-        }
-      },
-    ]);
+  // Test exporting HTML
+  let oldOpen = options.window.open;
+  let openURL = "";
+  options.window.open = function(url) {
+    // The URL is a data: URL that contains the document source
+    openURL = decodeURIComponent(url);
   };
 
-  tests.testPageModRemoveElement = function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pagemod remove',
-        check: {
-          input:  'pagemod remove',
-          hints:                ' attribute',
-          markup: 'IIIIIIIVIIIIII',
-          status: 'ERROR'
-        },
+  yield helpers.audit(options, [
+    {
+      setup: 'export html',
+      check: {
+        input:  'export html',
+        hints:             '',
+        markup: 'VVVVVVVVVVV',
+        status: 'VALID'
       },
-      {
-        setup: 'pagemod remove element',
-        check: {
-          input:  'pagemod remove element',
-          hints:                        ' <search> [root] [stripOnly] [ifEmptyOnly]',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVV',
-          status: 'ERROR'
-        },
+      exec: {
+        output: ''
       },
-      {
-        setup: 'pagemod remove element foo',
-        check: {
-          input:  'pagemod remove element foo',
-          hints:                            ' [root] [stripOnly] [ifEmptyOnly]',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVV',
-          status: 'VALID'
-        },
+      post: function() {
+        isnot(openURL.indexOf('<html lang="en">'), -1, "export html works: <html>");
+        isnot(openURL.indexOf("<title>GCLI"), -1, "export html works: <title>");
+        isnot(openURL.indexOf('<p id="someid">#'), -1, "export html works: <p>");
+
+         options.window.open = oldOpen;
+      }
+    }
+  ]);
+
+  // Test 'pagemod replace'
+  yield helpers.audit(options, [
+    {
+      setup: 'pagemod replace',
+      check: {
+        input:  'pagemod replace',
+        hints:                 ' <search> <replace> [ignoreCase] [selector] [root] [attrOnly] [contentOnly] [attributes]',
+        markup: 'VVVVVVVVVVVVVVV',
+        status: 'ERROR'
+      }
+    },
+    {
+      setup: 'pagemod replace some foo',
+      check: {
+        input:  'pagemod replace some foo',
+        hints:                          ' [ignoreCase] [selector] [root] [attrOnly] [contentOnly] [attributes]',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
+        status: 'VALID'
+      }
+    },
+    {
+      setup: 'pagemod replace some foo true',
+      check: {
+        input:  'pagemod replace some foo true',
+        hints:                               ' [selector] [root] [attrOnly] [contentOnly] [attributes]',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
+        status: 'VALID'
+      }
+    },
+    {
+      setup: 'pagemod replace some foo true --attrOnly',
+      check: {
+        input:  'pagemod replace some foo true --attrOnly',
+        hints:                                          ' [selector] [root] [contentOnly] [attributes]',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
+        status: 'VALID'
+      }
+    },
+    {
+      setup: 'pagemod replace sOme foOBar',
+      exec: {
+        output: /^[^:]+: 13\. [^:]+: 0\. [^:]+: 0\.\s*$/
       },
-      {
-        setup: 'pagemod remove element p',
-        exec: {
-          output: /^[^:]+: 3\. [^:]+: 3\.\s*$/
-        },
-        post: function() {
-          let html = getContent(options);
+      post: function() {
+        is(documentElement.innerHTML, initialHtml, "no change in the page");
+      }
+    },
+    {
+      setup: 'pagemod replace sOme foOBar true',
+      exec: {
+        output: /^[^:]+: 13\. [^:]+: 2\. [^:]+: 2\.\s*$/
+      },
+      post: function() {
+        let html = documentElement.innerHTML;
+
+        isnot(html.indexOf('<p class="foOBarclass">.foOBarclass'), -1,
+              ".someclass changed to .foOBarclass");
+        isnot(html.indexOf('<p id="foOBarid">#foOBarid'), -1,
+              "#someid changed to #foOBarid");
+
+        resetContent();
+      }
+    },
+    {
+      setup: 'pagemod replace some foobar --contentOnly',
+      exec: {
+        output: /^[^:]+: 13\. [^:]+: 2\. [^:]+: 0\.\s*$/
+      },
+      post: function() {
+        let html = documentElement.innerHTML;
 
-          is(html.indexOf('<p class="someclass">'), -1, "p.someclass removed");
-          is(html.indexOf('<p id="someid">'), -1, "p#someid removed");
-          is(html.indexOf("<p><strong>"), -1, "<p> wrapping <strong> removed");
-          isnot(html.indexOf("<span>"), -1, "<span> not removed");
+        isnot(html.indexOf('<p class="someclass">.foobarclass'), -1,
+              ".someclass changed to .foobarclass (content only)");
+        isnot(html.indexOf('<p id="someid">#foobarid'), -1,
+              "#someid changed to #foobarid (content only)");
 
-          resetContent(options);
-        }
+        resetContent();
+      }
+    },
+    {
+      setup: 'pagemod replace some foobar --attrOnly',
+      exec: {
+        output: /^[^:]+: 13\. [^:]+: 0\. [^:]+: 2\.\s*$/
+      },
+      post: function() {
+        let html = documentElement.innerHTML;
+
+        isnot(html.indexOf('<p class="foobarclass">.someclass'), -1,
+              ".someclass changed to .foobarclass (attr only)");
+        isnot(html.indexOf('<p id="foobarid">#someid'), -1,
+              "#someid changed to #foobarid (attr only)");
+
+        resetContent();
+      }
+    },
+    {
+      setup: 'pagemod replace some foobar --root head',
+      exec: {
+        output: /^[^:]+: 2\. [^:]+: 0\. [^:]+: 0\.\s*$/
       },
-      {
-        setup: 'pagemod remove element p head',
-        exec: {
-          output: /^[^:]+: 0\. [^:]+: 0\.\s*$/
-        },
-        post: function() {
-          is(getContent(options), initialHtml, "nothing changed in the page");
-        }
+      post: function() {
+        is(documentElement.innerHTML, initialHtml, "nothing changed");
+      }
+    },
+    {
+      setup: 'pagemod replace some foobar --selector .someclass,div,span',
+      exec: {
+        output: /^[^:]+: 4\. [^:]+: 1\. [^:]+: 1\.\s*$/
       },
-      {
-        setup: 'pagemod remove element p --ifEmptyOnly',
-        exec: {
-          output: /^[^:]+: 3\. [^:]+: 0\.\s*$/
-        },
-        post: function() {
-          is(getContent(options), initialHtml, "nothing changed in the page");
-        }
+      post: function() {
+        let html = documentElement.innerHTML;
+
+        isnot(html.indexOf('<p class="foobarclass">.foobarclass'), -1,
+              ".someclass changed to .foobarclass");
+        isnot(html.indexOf('<p id="someid">#someid'), -1,
+              "#someid did not change");
+
+        resetContent();
+      }
+    },
+  ]);
+
+  // Test 'pagemod remove element'
+  yield helpers.audit(options, [
+    {
+      setup: 'pagemod remove',
+      check: {
+        input:  'pagemod remove',
+        hints:                ' attribute',
+        markup: 'IIIIIIIVIIIIII',
+        status: 'ERROR'
+      },
+    },
+    {
+      setup: 'pagemod remove element',
+      check: {
+        input:  'pagemod remove element',
+        hints:                        ' <search> [root] [stripOnly] [ifEmptyOnly]',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVV',
+        status: 'ERROR'
+      },
+    },
+    {
+      setup: 'pagemod remove element foo',
+      check: {
+        input:  'pagemod remove element foo',
+        hints:                            ' [root] [stripOnly] [ifEmptyOnly]',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVV',
+        status: 'VALID'
+      },
+    },
+    {
+      setup: 'pagemod remove element p',
+      exec: {
+        output: /^[^:]+: 3\. [^:]+: 3\.\s*$/
       },
-      {
-        setup: 'pagemod remove element meta,title --ifEmptyOnly',
-        exec: {
-          output: /^[^:]+: 2\. [^:]+: 1\.\s*$/
-        },
-        post: function() {
-          let html = getContent(options);
+      post: function() {
+        let html = documentElement.innerHTML;
+
+        is(html.indexOf('<p class="someclass">'), -1, "p.someclass removed");
+        is(html.indexOf('<p id="someid">'), -1, "p#someid removed");
+        is(html.indexOf("<p><strong>"), -1, "<p> wrapping <strong> removed");
+        isnot(html.indexOf("<span>"), -1, "<span> not removed");
 
-          is(html.indexOf("<meta charset="), -1, "<meta> removed");
-          isnot(html.indexOf("<title>"), -1, "<title> not removed");
-
-          resetContent(options);
-        }
+        resetContent();
+      }
+    },
+    {
+      setup: 'pagemod remove element p head',
+      exec: {
+        output: /^[^:]+: 0\. [^:]+: 0\.\s*$/
+      },
+      post: function() {
+        is(documentElement.innerHTML, initialHtml, "nothing changed in the page");
+      }
+    },
+    {
+      setup: 'pagemod remove element p --ifEmptyOnly',
+      exec: {
+        output: /^[^:]+: 3\. [^:]+: 0\.\s*$/
+      },
+      post: function() {
+        is(documentElement.innerHTML, initialHtml, "nothing changed in the page");
+      }
+    },
+    {
+      setup: 'pagemod remove element meta,title --ifEmptyOnly',
+      exec: {
+        output: /^[^:]+: 2\. [^:]+: 1\.\s*$/
       },
-      {
-        setup: 'pagemod remove element p --stripOnly',
-        exec: {
-          output: /^[^:]+: 3\. [^:]+: 3\.\s*$/
-        },
-        post: function() {
-          let html = getContent(options);
+      post: function() {
+        let html = documentElement.innerHTML;
+
+        is(html.indexOf("<meta charset="), -1, "<meta> removed");
+        isnot(html.indexOf("<title>"), -1, "<title> not removed");
+
+        resetContent();
+      }
+    },
+    {
+      setup: 'pagemod remove element p --stripOnly',
+      exec: {
+        output: /^[^:]+: 3\. [^:]+: 3\.\s*$/
+      },
+      post: function() {
+        let html = documentElement.innerHTML;
 
-          is(html.indexOf('<p class="someclass">'), -1, "p.someclass removed");
-          is(html.indexOf('<p id="someid">'), -1, "p#someid removed");
-          is(html.indexOf("<p><strong>"), -1, "<p> wrapping <strong> removed");
-          isnot(html.indexOf(".someclass"), -1, ".someclass still exists");
-          isnot(html.indexOf("#someid"), -1, "#someid still exists");
-          isnot(html.indexOf("<strong>p"), -1, "<strong> still exists");
+        is(html.indexOf('<p class="someclass">'), -1, "p.someclass removed");
+        is(html.indexOf('<p id="someid">'), -1, "p#someid removed");
+        is(html.indexOf("<p><strong>"), -1, "<p> wrapping <strong> removed");
+        isnot(html.indexOf(".someclass"), -1, ".someclass still exists");
+        isnot(html.indexOf("#someid"), -1, "#someid still exists");
+        isnot(html.indexOf("<strong>p"), -1, "<strong> still exists");
+
+        resetContent();
+      }
+    },
+  ]);
 
-          resetContent(options);
+  // Test 'pagemod remove attribute'
+  yield helpers.audit(options, [
+    {
+      setup: 'pagemod remove attribute',
+      check: {
+        input:  'pagemod remove attribute',
+        hints:                          ' <searchAttributes> <searchElements> [root] [ignoreCase]',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
+        status: 'ERROR',
+        args: {
+          searchAttributes: { value: undefined, status: 'INCOMPLETE' },
+          searchElements: { value: undefined, status: 'INCOMPLETE' },
+          root: { value: undefined },
+          ignoreCase: { value: false },
         }
       },
-    ]);
-  };
-
-  tests.testPageModRemoveAttribute = function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pagemod remove attribute',
-        check: {
-          input:  'pagemod remove attribute',
-          hints:                          ' <searchAttributes> <searchElements> [root] [ignoreCase]',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
-          status: 'ERROR',
-          args: {
-            searchAttributes: { value: undefined, status: 'INCOMPLETE' },
-            searchElements: { value: undefined, status: 'INCOMPLETE' },
-            root: { value: undefined },
-            ignoreCase: { value: false },
-          }
-        },
-      },
-      {
-        setup: 'pagemod remove attribute foo bar',
-        check: {
-          input:  'pagemod remove attribute foo bar',
-          hints:                                  ' [root] [ignoreCase]',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
-          status: 'VALID',
-          args: {
-            searchAttributes: { value: 'foo' },
-            searchElements: { value: 'bar' },
-            root: { value: undefined },
-            ignoreCase: { value: false },
-          }
-        },
-        post: function() {
-          let deferred = promise.defer();
-          executeSoon(function() {
-            deferred.resolve();
-          });
-          return deferred.promise;
+    },
+    {
+      setup: 'pagemod remove attribute foo bar',
+      check: {
+        input:  'pagemod remove attribute foo bar',
+        hints:                                  ' [root] [ignoreCase]',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {
+          searchAttributes: { value: 'foo' },
+          searchElements: { value: 'bar' },
+          root: { value: undefined },
+          ignoreCase: { value: false },
         }
       },
-      {
-        setup: 'pagemod remove attribute foo bar',
-        exec: {
-          output: /^[^:]+: 0\. [^:]+: 0\.\s*$/
-        },
-        post: function() {
-          is(getContent(options), initialHtml, "nothing changed in the page");
-        }
+      post: function() {
+        let deferred = promise.defer();
+        executeSoon(function() {
+          deferred.resolve();
+        });
+        return deferred.promise;
+      }
+    },
+    {
+      setup: 'pagemod remove attribute foo bar',
+      exec: {
+        output: /^[^:]+: 0\. [^:]+: 0\.\s*$/
       },
-      {
-        setup: 'pagemod remove attribute foo p',
-        exec: {
-          output: /^[^:]+: 3\. [^:]+: 0\.\s*$/
-        },
-        post: function() {
-          is(getContent(options), initialHtml, "nothing changed in the page");
-        }
+      post: function() {
+        is(documentElement.innerHTML, initialHtml, "nothing changed in the page");
+      }
+    },
+    {
+      setup: 'pagemod remove attribute foo p',
+      exec: {
+        output: /^[^:]+: 3\. [^:]+: 0\.\s*$/
       },
-      {
-        setup: 'pagemod remove attribute id p,span',
-        exec: {
-          output: /^[^:]+: 5\. [^:]+: 1\.\s*$/
-        },
-        post: function() {
-          is(getContent(options).indexOf('<p id="someid">#someid'), -1,
-             "p#someid attribute removed");
-          isnot(getContent(options).indexOf("<p>#someid"), -1,
-             "p with someid content still exists");
+      post: function() {
+        is(documentElement.innerHTML, initialHtml, "nothing changed in the page");
+      }
+    },
+    {
+      setup: 'pagemod remove attribute id p,span',
+      exec: {
+        output: /^[^:]+: 5\. [^:]+: 1\.\s*$/
+      },
+      post: function() {
+        is(documentElement.innerHTML.indexOf('<p id="someid">#someid'), -1,
+           "p#someid attribute removed");
+        isnot(documentElement.innerHTML.indexOf("<p>#someid"), -1,
+           "p with someid content still exists");
 
-          resetContent(options);
-        }
-      },
-      {
-        setup: 'pagemod remove attribute Class p',
-        exec: {
-          output: /^[^:]+: 3\. [^:]+: 0\.\s*$/
-        },
-        post: function() {
-          is(getContent(options), initialHtml, "nothing changed in the page");
-        }
+        resetContent();
+      }
+    },
+    {
+      setup: 'pagemod remove attribute Class p',
+      exec: {
+        output: /^[^:]+: 3\. [^:]+: 0\.\s*$/
       },
-      {
-        setup: 'pagemod remove attribute Class p --ignoreCase',
-        exec: {
-          output: /^[^:]+: 3\. [^:]+: 1\.\s*$/
-        },
-        post: function() {
-          is(getContent(options).indexOf('<p class="someclass">.someclass'), -1,
-             "p.someclass attribute removed");
-          isnot(getContent(options).indexOf("<p>.someclass"), -1,
-             "p with someclass content still exists");
+      post: function() {
+        is(documentElement.innerHTML, initialHtml, "nothing changed in the page");
+      }
+    },
+    {
+      setup: 'pagemod remove attribute Class p --ignoreCase',
+      exec: {
+        output: /^[^:]+: 3\. [^:]+: 1\.\s*$/
+      },
+      post: function() {
+        is(documentElement.innerHTML.indexOf('<p class="someclass">.someclass'), -1,
+           "p.someclass attribute removed");
+        isnot(documentElement.innerHTML.indexOf("<p>.someclass"), -1,
+           "p with someclass content still exists");
 
-          resetContent(options);
-        }
-      },
-    ]);
-  };
+        resetContent();
+      }
+    },
+  ]);
+
+  // Shutdown
+  yield helpers.closeToolbar(options);
+  yield helpers.closeTab(options);
 }
rename from browser/devtools/commandline/test/browser_cmd_pref.js
rename to browser/devtools/commandline/test/browser_cmd_pref1.js
--- a/browser/devtools/commandline/test/browser_cmd_pref.js
+++ b/browser/devtools/commandline/test/browser_cmd_pref1.js
@@ -2,501 +2,153 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the pref commands work
 
 let prefBranch = Cc["@mozilla.org/preferences-service;1"]
                     .getService(Ci.nsIPrefService).getBranch(null)
                     .QueryInterface(Ci.nsIPrefBranch2);
 
-let supportsString = Cc["@mozilla.org/supports-string;1"]
-                      .createInstance(Ci.nsISupportsString)
-
-let require = (Cu.import("resource://gre/modules/devtools/Require.jsm", {})).require;
-
 let settings = require("gcli/settings");
 
-const TEST_URI = "data:text/html;charset=utf-8,gcli-pref";
-
-let tiltEnabledOrig;
-let tabSizeOrig;
-let remoteHostOrig;
+const TEST_URI = "data:text/html;charset=utf-8,gcli-pref1";
 
-let tests = {
-  setup: function(options) {
-    tiltEnabledOrig = prefBranch.getBoolPref("devtools.tilt.enabled");
-    tabSizeOrig = prefBranch.getIntPref("devtools.editor.tabsize");
-    remoteHostOrig = prefBranch.getComplexValue("devtools.debugger.remote-host",
-                                                    Ci.nsISupportsString).data;
+function test() {
+  return Task.spawn(spawnTest).then(finish, helpers.handleError);
+}
 
-    info("originally: devtools.tilt.enabled = " + tiltEnabledOrig);
-    info("originally: devtools.editor.tabsize = " + tabSizeOrig);
-    info("originally: devtools.debugger.remote-host = " + remoteHostOrig);
-  },
+function spawnTest() {
+  let options = yield helpers.openTab(TEST_URI);
+  yield helpers.openToolbar(options);
 
-  shutdown: function(options) {
-    prefBranch.setBoolPref("devtools.tilt.enabled", tiltEnabledOrig);
-    prefBranch.setIntPref("devtools.editor.tabsize", tabSizeOrig);
-    supportsString.data = remoteHostOrig;
-    prefBranch.setComplexValue("devtools.debugger.remote-host",
-                               Ci.nsISupportsString, supportsString);
-  },
+  let tiltEnabledOrig = prefBranch.getBoolPref("devtools.tilt.enabled");
+  info("originally: devtools.tilt.enabled = " + tiltEnabledOrig);
 
-  testPrefStatus: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pref',
-        check: {
-          input:  'pref',
-          hints:      ' reset',
-          markup: 'IIII',
-          status: 'ERROR'
-        },
-      },
-      {
-        setup: 'pref s',
-        check: {
-          input:  'pref s',
-          hints:        'et',
-          markup: 'IIIIVI',
-          status: 'ERROR'
-        },
+  yield helpers.audit(options, [
+    {
+      setup: 'pref',
+      check: {
+        input:  'pref',
+        hints:      ' reset',
+        markup: 'IIII',
+        status: 'ERROR'
       },
-      {
-        setup: 'pref sh',
-        check: {
-          input:  'pref sh',
-          hints:         'ow',
-          markup: 'IIIIVII',
-          status: 'ERROR'
-        },
-      },
-      {
-        setup: 'pref show ',
-        check: {
-          input:  'pref show ',
-          markup: 'VVVVVVVVVV',
-          status: 'ERROR'
-        },
-      },
-      {
-        setup: 'pref show usetexttospeech',
-        check: {
-          input:  'pref show usetexttospeech',
-          hints:                           ' -> accessibility.usetexttospeech',
-          markup: 'VVVVVVVVVVIIIIIIIIIIIIIII',
-          status: 'ERROR'
-        },
-      },
-      {
-        setup: 'pref show devtools.til',
-        check: {
-          input:  'pref show devtools.til',
-          hints:                        't.enabled',
-          markup: 'VVVVVVVVVVIIIIIIIIIIII',
-          status: 'ERROR',
-          tooltipState: 'true:importantFieldFlag',
-          args: {
-            setting: { value: undefined, status: 'INCOMPLETE' },
-          }
-        },
-      },
-      {
-        setup: 'pref reset devtools.tilt.enabled',
-        check: {
-          input:  'pref reset devtools.tilt.enabled',
-          hints:                                  '',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
-          status: 'VALID'
-        },
-      },
-      {
-        setup: 'pref show devtools.tilt.enabled 4',
-        check: {
-          input:  'pref show devtools.tilt.enabled 4',
-          hints:                                   '',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE',
-          status: 'ERROR'
-        },
+    },
+    {
+      setup: 'pref s',
+      check: {
+        input:  'pref s',
+        hints:        'et',
+        markup: 'IIIIVI',
+        status: 'ERROR'
       },
-      {
-        setup: 'pref set devtools.tilt.enabled 4',
-        check: {
-          input:  'pref set devtools.tilt.enabled 4',
-          hints:                                  '',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE',
-          status: 'ERROR',
-          args: {
-            setting: { arg: ' devtools.tilt.enabled' },
-            value: { status: 'ERROR', message: 'Can\'t use \'4\'.' },
-          }
-        },
-      },
-      {
-        setup: 'pref set devtools.editor.tabsize 4',
-        check: {
-          input:  'pref set devtools.editor.tabsize 4',
-          hints:                                    '',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
-          status: 'VALID',
-          args: {
-            setting: { arg: ' devtools.editor.tabsize' },
-            value: { value: 4 },
-          }
-        },
+    },
+    {
+      setup: 'pref sh',
+      check: {
+        input:  'pref sh',
+        hints:         'ow',
+        markup: 'IIIIVII',
+        status: 'ERROR'
       },
-      {
-        setup: 'pref list',
-        check: {
-          input:  'pref list',
-          hints:           ' -> pref set',
-          markup: 'IIIIVIIII',
-          status: 'ERROR'
-        },
-      },
-    ]);
-  },
-
-  testPrefSetEnable: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pref set devtools.editor.tabsize 9',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") },
-            value: { value: 9 }
-          },
-        },
-        exec: {
-          completed: true,
-          output: [ /void your warranty/, /I promise/ ],
-        },
-        post: function() {
-          is(prefBranch.getIntPref("devtools.editor.tabsize"),
-                                   tabSizeOrig,
-                                   "devtools.editor.tabsize is unchanged");
-        }
+    },
+    {
+      setup: 'pref show ',
+      check: {
+        input:  'pref show ',
+        markup: 'VVVVVVVVVV',
+        status: 'ERROR'
       },
-      {
-        setup: 'pref set devtools.gcli.allowSet true',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.gcli.allowSet") },
-            value: { value: true }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-        post: function() {
-          is(prefBranch.getBoolPref("devtools.gcli.allowSet"), true,
-                                    "devtools.gcli.allowSet is true");
-        }
+    },
+    {
+      setup: 'pref show usetexttospeech',
+      check: {
+        input:  'pref show usetexttospeech',
+        hints:                           ' -> accessibility.usetexttospeech',
+        markup: 'VVVVVVVVVVIIIIIIIIIIIIIII',
+        status: 'ERROR'
       },
-      {
-        setup: 'pref set devtools.editor.tabsize 10',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") },
-            value: { value: 10 }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-        post: function() {
-          is(prefBranch.getIntPref("devtools.editor.tabsize"), 10,
-                                   "devtools.editor.tabsize is 10");
-        }
-      },
-    ]);
-  },
-
-  testPrefBoolExec: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pref show devtools.tilt.enabled',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.tilt.enabled") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.tilt\.enabled: " + tiltEnabledOrig + "$"),
-        },
-      },
-      {
-        setup: 'pref set devtools.tilt.enabled true',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.tilt.enabled") },
-            value: { value: true }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-        post: function() {
-          is(prefBranch.getBoolPref("devtools.tilt.enabled"), true,
-                                    "devtools.tilt.enabled is true");
+    },
+    {
+      setup: 'pref show devtools.til',
+      check: {
+        input:  'pref show devtools.til',
+        hints:                        't.enabled',
+        markup: 'VVVVVVVVVVIIIIIIIIIIII',
+        status: 'ERROR',
+        tooltipState: 'true:importantFieldFlag',
+        args: {
+          setting: { value: undefined, status: 'INCOMPLETE' },
         }
       },
-      {
-        setup: 'pref show devtools.tilt.enabled',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.tilt.enabled") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.tilt\.enabled: true$"),
-        },
-      },
-      {
-        setup: 'pref set devtools.tilt.enabled false',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.tilt.enabled") },
-            value: { value: false }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-      },
-      {
-        setup: 'pref show devtools.tilt.enabled',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.tilt.enabled") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.tilt\.enabled: false$"),
-        },
-        post: function() {
-          is(prefBranch.getBoolPref("devtools.tilt.enabled"), false,
-                                    "devtools.tilt.enabled is false");
-        }
+    },
+    {
+      setup: 'pref reset devtools.tilt.enabled',
+      check: {
+        input:  'pref reset devtools.tilt.enabled',
+        hints:                                  '',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
+        status: 'VALID'
       },
-    ]);
-  },
-
-  testPrefNumberExec: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pref show devtools.editor.tabsize',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.editor\.tabsize: 10$"),
-        },
-      },
-      {
-        setup: 'pref set devtools.editor.tabsize 20',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") },
-            value: { value: 20 }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
+    },
+    {
+      setup: 'pref show devtools.tilt.enabled 4',
+      check: {
+        input:  'pref show devtools.tilt.enabled 4',
+        hints:                                   '',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE',
+        status: 'ERROR'
       },
-      {
-        setup: 'pref show devtools.editor.tabsize',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.editor\.tabsize: 20$"),
-        },
-        post: function() {
-          is(prefBranch.getIntPref("devtools.editor.tabsize"), 20,
-                                   "devtools.editor.tabsize is 20");
-        }
-      },
-      {
-        setup: 'pref set devtools.editor.tabsize 1',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") },
-            value: { value: 1 }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-      },
-      {
-        setup: 'pref show devtools.editor.tabsize',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.editor\.tabsize: 1$"),
-        },
-        post: function() {
-          is(prefBranch.getIntPref("devtools.editor.tabsize"), 1,
-                                   "devtools.editor.tabsize is 1");
+    },
+    {
+      setup: 'pref set devtools.tilt.enabled 4',
+      check: {
+        input:  'pref set devtools.tilt.enabled 4',
+        hints:                                  '',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE',
+        status: 'ERROR',
+        args: {
+          setting: { arg: ' devtools.tilt.enabled' },
+          value: { status: 'ERROR', message: 'Can\'t use \'4\'.' },
         }
       },
-    ]);
-  },
-
-  testPrefStringExec: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pref show devtools.debugger.remote-host',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.debugger.remote-host") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.debugger\.remote-host: " + remoteHostOrig + "$"),
-        },
-      },
-      {
-        setup: 'pref set devtools.debugger.remote-host e.com',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.debugger.remote-host") },
-            value: { value: "e.com" }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-      },
-      {
-        setup: 'pref show devtools.debugger.remote-host',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.debugger.remote-host") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.debugger\.remote-host: e.com$"),
-        },
-        post: function() {
-          var ecom = prefBranch.getComplexValue("devtools.debugger.remote-host",
-                                                Ci.nsISupportsString).data;
-          is(ecom, "e.com", "devtools.debugger.remote-host is e.com");
+    },
+    {
+      setup: 'pref set devtools.editor.tabsize 4',
+      check: {
+        input:  'pref set devtools.editor.tabsize 4',
+        hints:                                    '',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {
+          setting: { arg: ' devtools.editor.tabsize' },
+          value: { value: 4 },
         }
       },
-      {
-        setup: 'pref set devtools.debugger.remote-host moz.foo',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.debugger.remote-host") },
-            value: { value: "moz.foo" }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
+    },
+    {
+      setup: 'pref list',
+      check: {
+        input:  'pref list',
+        hints:           ' -> pref set',
+        markup: 'IIIIVIIII',
+        status: 'ERROR'
+      },
+    },
+    {
+      setup: 'pref show devtools.tilt.enabled',
+      check: {
+        args: {
+          setting: { value: settings.getSetting("devtools.tilt.enabled") }
         },
       },
-      {
-        setup: 'pref show devtools.debugger.remote-host',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.debugger.remote-host") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.debugger\.remote-host: moz.foo$"),
-        },
-        post: function() {
-          var mozfoo = prefBranch.getComplexValue("devtools.debugger.remote-host",
-                                                  Ci.nsISupportsString).data;
-          is(mozfoo, "moz.foo", "devtools.debugger.remote-host is moz.foo");
-        }
-      },
-    ]);
-  },
-
-  testPrefSetDisable: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pref set devtools.editor.tabsize 32',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") },
-            value: { value: 32 }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-        post: function() {
-          is(prefBranch.getIntPref("devtools.editor.tabsize"), 32,
-                                   "devtools.editor.tabsize is 32");
-        }
+      exec: {
+        output: "devtools.tilt.enabled: " + tiltEnabledOrig,
       },
-      {
-        setup: 'pref reset devtools.gcli.allowSet',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.gcli.allowSet") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-        post: function() {
-          is(prefBranch.getBoolPref("devtools.gcli.allowSet"), false,
-                                    "devtools.gcli.allowSet is false");
-        }
-      },
-      {
-        setup: 'pref set devtools.editor.tabsize 33',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") },
-            value: { value: 33 }
-          },
-        },
-        exec: {
-          completed: true,
-          output: [ /void your warranty/, /I promise/ ],
-        },
-        post: function() {
-          is(prefBranch.getIntPref("devtools.editor.tabsize"), 32,
-                                   "devtools.editor.tabsize is still 32");
-        }
-      },
-    ]);
-  },
-};
+      post: function() {
+        prefBranch.setBoolPref("devtools.tilt.enabled", tiltEnabledOrig);
+      }
+    },
+  ]);
 
-function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, tests);
-  }).then(finish);
+  yield helpers.closeToolbar(options);
+  yield helpers.closeTab(options);
 }
copy from browser/devtools/commandline/test/browser_cmd_pref.js
copy to browser/devtools/commandline/test/browser_cmd_pref2.js
--- a/browser/devtools/commandline/test/browser_cmd_pref.js
+++ b/browser/devtools/commandline/test/browser_cmd_pref2.js
@@ -2,501 +2,96 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the pref commands work
 
 let prefBranch = Cc["@mozilla.org/preferences-service;1"]
                     .getService(Ci.nsIPrefService).getBranch(null)
                     .QueryInterface(Ci.nsIPrefBranch2);
 
-let supportsString = Cc["@mozilla.org/supports-string;1"]
-                      .createInstance(Ci.nsISupportsString)
-
-let require = (Cu.import("resource://gre/modules/devtools/Require.jsm", {})).require;
-
 let settings = require("gcli/settings");
 
-const TEST_URI = "data:text/html;charset=utf-8,gcli-pref";
-
-let tiltEnabledOrig;
-let tabSizeOrig;
-let remoteHostOrig;
-
-let tests = {
-  setup: function(options) {
-    tiltEnabledOrig = prefBranch.getBoolPref("devtools.tilt.enabled");
-    tabSizeOrig = prefBranch.getIntPref("devtools.editor.tabsize");
-    remoteHostOrig = prefBranch.getComplexValue("devtools.debugger.remote-host",
-                                                    Ci.nsISupportsString).data;
+const TEST_URI = "data:text/html;charset=utf-8,gcli-pref2";
 
-    info("originally: devtools.tilt.enabled = " + tiltEnabledOrig);
-    info("originally: devtools.editor.tabsize = " + tabSizeOrig);
-    info("originally: devtools.debugger.remote-host = " + remoteHostOrig);
-  },
+function test() {
+  return Task.spawn(spawnTest).then(finish, helpers.handleError);
+}
 
-  shutdown: function(options) {
-    prefBranch.setBoolPref("devtools.tilt.enabled", tiltEnabledOrig);
-    prefBranch.setIntPref("devtools.editor.tabsize", tabSizeOrig);
-    supportsString.data = remoteHostOrig;
-    prefBranch.setComplexValue("devtools.debugger.remote-host",
-                               Ci.nsISupportsString, supportsString);
-  },
+function spawnTest() {
+  let options = yield helpers.openTab(TEST_URI);
+  yield helpers.openToolbar(options);
 
-  testPrefStatus: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pref',
-        check: {
-          input:  'pref',
-          hints:      ' reset',
-          markup: 'IIII',
-          status: 'ERROR'
-        },
-      },
-      {
-        setup: 'pref s',
-        check: {
-          input:  'pref s',
-          hints:        'et',
-          markup: 'IIIIVI',
-          status: 'ERROR'
-        },
-      },
-      {
-        setup: 'pref sh',
-        check: {
-          input:  'pref sh',
-          hints:         'ow',
-          markup: 'IIIIVII',
-          status: 'ERROR'
-        },
-      },
-      {
-        setup: 'pref show ',
-        check: {
-          input:  'pref show ',
-          markup: 'VVVVVVVVVV',
-          status: 'ERROR'
-        },
-      },
-      {
-        setup: 'pref show usetexttospeech',
-        check: {
-          input:  'pref show usetexttospeech',
-          hints:                           ' -> accessibility.usetexttospeech',
-          markup: 'VVVVVVVVVVIIIIIIIIIIIIIII',
-          status: 'ERROR'
-        },
-      },
-      {
-        setup: 'pref show devtools.til',
-        check: {
-          input:  'pref show devtools.til',
-          hints:                        't.enabled',
-          markup: 'VVVVVVVVVVIIIIIIIIIIII',
-          status: 'ERROR',
-          tooltipState: 'true:importantFieldFlag',
-          args: {
-            setting: { value: undefined, status: 'INCOMPLETE' },
-          }
-        },
-      },
-      {
-        setup: 'pref reset devtools.tilt.enabled',
-        check: {
-          input:  'pref reset devtools.tilt.enabled',
-          hints:                                  '',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
-          status: 'VALID'
+  let tabSizeOrig = prefBranch.getIntPref("devtools.editor.tabsize");
+  info("originally: devtools.editor.tabsize = " + tabSizeOrig);
+
+  yield helpers.audit(options, [
+    {
+      setup: 'pref show devtools.editor.tabsize',
+      check: {
+        args: {
+          setting: { value: settings.getSetting("devtools.editor.tabsize") }
         },
       },
-      {
-        setup: 'pref show devtools.tilt.enabled 4',
-        check: {
-          input:  'pref show devtools.tilt.enabled 4',
-          hints:                                   '',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE',
-          status: 'ERROR'
-        },
-      },
-      {
-        setup: 'pref set devtools.tilt.enabled 4',
-        check: {
-          input:  'pref set devtools.tilt.enabled 4',
-          hints:                                  '',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE',
-          status: 'ERROR',
-          args: {
-            setting: { arg: ' devtools.tilt.enabled' },
-            value: { status: 'ERROR', message: 'Can\'t use \'4\'.' },
-          }
-        },
-      },
-      {
-        setup: 'pref set devtools.editor.tabsize 4',
-        check: {
-          input:  'pref set devtools.editor.tabsize 4',
-          hints:                                    '',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
-          status: 'VALID',
-          args: {
-            setting: { arg: ' devtools.editor.tabsize' },
-            value: { value: 4 },
-          }
-        },
-      },
-      {
-        setup: 'pref list',
-        check: {
-          input:  'pref list',
-          hints:           ' -> pref set',
-          markup: 'IIIIVIIII',
-          status: 'ERROR'
-        },
+      exec: {
+        output: "devtools.editor.tabsize: " + tabSizeOrig,
       },
-    ]);
-  },
-
-  testPrefSetEnable: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pref set devtools.editor.tabsize 9',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") },
-            value: { value: 9 }
-          },
-        },
-        exec: {
-          completed: true,
-          output: [ /void your warranty/, /I promise/ ],
-        },
-        post: function() {
-          is(prefBranch.getIntPref("devtools.editor.tabsize"),
-                                   tabSizeOrig,
-                                   "devtools.editor.tabsize is unchanged");
-        }
-      },
-      {
-        setup: 'pref set devtools.gcli.allowSet true',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.gcli.allowSet") },
-            value: { value: true }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-        post: function() {
-          is(prefBranch.getBoolPref("devtools.gcli.allowSet"), true,
-                                    "devtools.gcli.allowSet is true");
-        }
-      },
-      {
-        setup: 'pref set devtools.editor.tabsize 10',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") },
-            value: { value: 10 }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-        post: function() {
-          is(prefBranch.getIntPref("devtools.editor.tabsize"), 10,
-                                   "devtools.editor.tabsize is 10");
-        }
-      },
-    ]);
-  },
-
-  testPrefBoolExec: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pref show devtools.tilt.enabled',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.tilt.enabled") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.tilt\.enabled: " + tiltEnabledOrig + "$"),
+    },
+    {
+      setup: 'pref set devtools.editor.tabsize 20',
+      check: {
+        args: {
+          setting: { value: settings.getSetting("devtools.editor.tabsize") },
+          value: { value: 20 }
         },
       },
-      {
-        setup: 'pref set devtools.tilt.enabled true',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.tilt.enabled") },
-            value: { value: true }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-        post: function() {
-          is(prefBranch.getBoolPref("devtools.tilt.enabled"), true,
-                                    "devtools.tilt.enabled is true");
-        }
+      exec: {
+        output: '',
       },
-      {
-        setup: 'pref show devtools.tilt.enabled',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.tilt.enabled") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.tilt\.enabled: true$"),
-        },
-      },
-      {
-        setup: 'pref set devtools.tilt.enabled false',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.tilt.enabled") },
-            value: { value: false }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
+      post: function() {
+        is(prefBranch.getIntPref("devtools.editor.tabsize"), 20,
+                                 "devtools.editor.tabsize is 20");
+      }
+    },
+    {
+      setup: 'pref show devtools.editor.tabsize',
+      check: {
+        args: {
+          setting: { value: settings.getSetting("devtools.editor.tabsize") }
         },
       },
-      {
-        setup: 'pref show devtools.tilt.enabled',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.tilt.enabled") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.tilt\.enabled: false$"),
-        },
-        post: function() {
-          is(prefBranch.getBoolPref("devtools.tilt.enabled"), false,
-                                    "devtools.tilt.enabled is false");
-        }
-      },
-    ]);
-  },
-
-  testPrefNumberExec: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pref show devtools.editor.tabsize',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.editor\.tabsize: 10$"),
-        },
-      },
-      {
-        setup: 'pref set devtools.editor.tabsize 20',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") },
-            value: { value: 20 }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-      },
-      {
-        setup: 'pref show devtools.editor.tabsize',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.editor\.tabsize: 20$"),
-        },
-        post: function() {
-          is(prefBranch.getIntPref("devtools.editor.tabsize"), 20,
-                                   "devtools.editor.tabsize is 20");
-        }
-      },
-      {
-        setup: 'pref set devtools.editor.tabsize 1',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") },
-            value: { value: 1 }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
+      exec: {
+        output: "devtools.editor.tabsize: 20",
+      }
+    },
+    {
+      setup: 'pref set devtools.editor.tabsize 1',
+      check: {
+        args: {
+          setting: { value: settings.getSetting("devtools.editor.tabsize") },
+          value: { value: 1 }
         },
       },
-      {
-        setup: 'pref show devtools.editor.tabsize',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.editor\.tabsize: 1$"),
-        },
-        post: function() {
-          is(prefBranch.getIntPref("devtools.editor.tabsize"), 1,
-                                   "devtools.editor.tabsize is 1");
-        }
-      },
-    ]);
-  },
-
-  testPrefStringExec: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pref show devtools.debugger.remote-host',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.debugger.remote-host") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.debugger\.remote-host: " + remoteHostOrig + "$"),
-        },
+      exec: {
+        output: '',
       },
-      {
-        setup: 'pref set devtools.debugger.remote-host e.com',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.debugger.remote-host") },
-            value: { value: "e.com" }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-      },
-      {
-        setup: 'pref show devtools.debugger.remote-host',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.debugger.remote-host") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.debugger\.remote-host: e.com$"),
-        },
-        post: function() {
-          var ecom = prefBranch.getComplexValue("devtools.debugger.remote-host",
-                                                Ci.nsISupportsString).data;
-          is(ecom, "e.com", "devtools.debugger.remote-host is e.com");
-        }
-      },
-      {
-        setup: 'pref set devtools.debugger.remote-host moz.foo',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.debugger.remote-host") },
-            value: { value: "moz.foo" }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
+    },
+    {
+      setup: 'pref show devtools.editor.tabsize',
+      check: {
+        args: {
+          setting: { value: settings.getSetting("devtools.editor.tabsize") }
         },
       },
-      {
-        setup: 'pref show devtools.debugger.remote-host',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.debugger.remote-host") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: new RegExp("^devtools\.debugger\.remote-host: moz.foo$"),
-        },
-        post: function() {
-          var mozfoo = prefBranch.getComplexValue("devtools.debugger.remote-host",
-                                                  Ci.nsISupportsString).data;
-          is(mozfoo, "moz.foo", "devtools.debugger.remote-host is moz.foo");
-        }
-      },
-    ]);
-  },
-
-  testPrefSetDisable: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'pref set devtools.editor.tabsize 32',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") },
-            value: { value: 32 }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-        post: function() {
-          is(prefBranch.getIntPref("devtools.editor.tabsize"), 32,
-                                   "devtools.editor.tabsize is 32");
-        }
+      exec: {
+        output: "devtools.editor.tabsize: 1",
       },
-      {
-        setup: 'pref reset devtools.gcli.allowSet',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.gcli.allowSet") }
-          },
-        },
-        exec: {
-          completed: true,
-          output: '',
-        },
-        post: function() {
-          is(prefBranch.getBoolPref("devtools.gcli.allowSet"), false,
-                                    "devtools.gcli.allowSet is false");
-        }
-      },
-      {
-        setup: 'pref set devtools.editor.tabsize 33',
-        check: {
-          args: {
-            setting: { value: settings.getSetting("devtools.editor.tabsize") },
-            value: { value: 33 }
-          },
-        },
-        exec: {
-          completed: true,
-          output: [ /void your warranty/, /I promise/ ],
-        },
-        post: function() {
-          is(prefBranch.getIntPref("devtools.editor.tabsize"), 32,
-                                   "devtools.editor.tabsize is still 32");
-        }
-      },
-    ]);
-  },
-};
+      post: function() {
+        is(prefBranch.getIntPref("devtools.editor.tabsize"), 1,
+                                 "devtools.editor.tabsize is 1");
+      }
+    },
+  ]);
 
-function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, tests);
-  }).then(finish);
+  prefBranch.setIntPref("devtools.editor.tabsize", tabSizeOrig);
+
+  yield helpers.closeToolbar(options);
+  yield helpers.closeTab(options);
 }
new file mode 100644
--- /dev/null
+++ b/browser/devtools/commandline/test/browser_cmd_pref3.js
@@ -0,0 +1,105 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests that the pref commands work
+
+let prefBranch = Cc["@mozilla.org/preferences-service;1"]
+                    .getService(Ci.nsIPrefService).getBranch(null)
+                    .QueryInterface(Ci.nsIPrefBranch2);
+
+let supportsString = Cc["@mozilla.org/supports-string;1"]
+                      .createInstance(Ci.nsISupportsString);
+
+let settings = require("gcli/settings");
+
+const TEST_URI = "data:text/html;charset=utf-8,gcli-pref3";
+
+function test() {
+  return Task.spawn(spawnTest).then(finish, helpers.handleError);
+}
+
+function spawnTest() {
+  let options = yield helpers.openTab(TEST_URI);
+  yield helpers.openToolbar(options);
+
+  let remoteHostOrig = prefBranch.getComplexValue("devtools.debugger.remote-host",
+                                                  Ci.nsISupportsString).data;
+  info("originally: devtools.debugger.remote-host = " + remoteHostOrig);
+
+  yield helpers.audit(options, [
+    {
+      setup: 'pref show devtools.debugger.remote-host',
+      check: {
+        args: {
+          setting: { value: settings.getSetting("devtools.debugger.remote-host") }
+        },
+      },
+      exec: {
+        output: new RegExp("^devtools\.debugger\.remote-host: " + remoteHostOrig + "$"),
+      },
+    },
+    {
+      setup: 'pref set devtools.debugger.remote-host e.com',
+      check: {
+        args: {
+          setting: { value: settings.getSetting("devtools.debugger.remote-host") },
+          value: { value: "e.com" }
+        },
+      },
+      exec: {
+        output: '',
+      },
+    },
+    {
+      setup: 'pref show devtools.debugger.remote-host',
+      check: {
+        args: {
+          setting: { value: settings.getSetting("devtools.debugger.remote-host") }
+        },
+      },
+      exec: {
+        output: new RegExp("^devtools\.debugger\.remote-host: e.com$"),
+      },
+      post: function() {
+        var ecom = prefBranch.getComplexValue("devtools.debugger.remote-host",
+                                              Ci.nsISupportsString).data;
+        is(ecom, "e.com", "devtools.debugger.remote-host is e.com");
+      }
+    },
+    {
+      setup: 'pref set devtools.debugger.remote-host moz.foo',
+      check: {
+        args: {
+          setting: { value: settings.getSetting("devtools.debugger.remote-host") },
+          value: { value: "moz.foo" }
+        },
+      },
+      exec: {
+        output: '',
+      },
+    },
+    {
+      setup: 'pref show devtools.debugger.remote-host',
+      check: {
+        args: {
+          setting: { value: settings.getSetting("devtools.debugger.remote-host") }
+        },
+      },
+      exec: {
+        output: new RegExp("^devtools\.debugger\.remote-host: moz.foo$"),
+      },
+      post: function() {
+        var mozfoo = prefBranch.getComplexValue("devtools.debugger.remote-host",
+                                                Ci.nsISupportsString).data;
+        is(mozfoo, "moz.foo", "devtools.debugger.remote-host is moz.foo");
+      }
+    },
+  ]);
+
+  supportsString.data = remoteHostOrig;
+  prefBranch.setComplexValue("devtools.debugger.remote-host",
+                             Ci.nsISupportsString, supportsString);
+
+  yield helpers.closeToolbar(options);
+  yield helpers.closeTab(options);
+}
--- a/browser/devtools/commandline/test/browser_cmd_restart.js
+++ b/browser/devtools/commandline/test/browser_cmd_restart.js
@@ -26,10 +26,10 @@ function test() {
           markup: 'VVVVVVVVVVVVVVVVV',
           status: 'VALID',
           args: {
             nocache: { value: true },
           }
         },
       },
     ]);
-  }).then(finish);
+  }).then(finish, helpers.handleError);
 }
--- a/browser/devtools/commandline/test/browser_cmd_screenshot.js
+++ b/browser/devtools/commandline/test/browser_cmd_screenshot.js
@@ -2,190 +2,182 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that screenshot command works properly
 const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
                  "test/browser_cmd_screenshot.html";
 
 let FileUtils = (Cu.import("resource://gre/modules/FileUtils.jsm", {})).FileUtils;
 
-let tests = {
-  testInput: function(options) {
-    return helpers.audit(options, [
-      {
-        setup: 'screenshot',
-        check: {
-          input:  'screenshot',
-          markup: 'VVVVVVVVVV',
-          status: 'VALID',
-          args: {
-          }
-        },
-      },
-      {
-        setup: 'screenshot abc.png',
-        check: {
-          input:  'screenshot abc.png',
-          markup: 'VVVVVVVVVVVVVVVVVV',
-          status: 'VALID',
-          args: {
-            filename: { value: "abc.png"},
-          }
-        },
-      },
-      {
-        setup: 'screenshot --fullpage',
-        check: {
-          input:  'screenshot --fullpage',
-          markup: 'VVVVVVVVVVVVVVVVVVVVV',
-          status: 'VALID',
-          args: {
-            fullpage: { value: true},
-          }
-        },
-      },
-      {
-        setup: 'screenshot abc --delay 5',
-        check: {
-          input:  'screenshot abc --delay 5',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
-          status: 'VALID',
-          args: {
-            filename: { value: "abc"},
-            delay: { value: 5 },
-          }
-        },
-      },
-      {
-        setup: 'screenshot --selector img#testImage',
-        check: {
-          input:  'screenshot --selector img#testImage',
-          markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
-          status: 'VALID',
-          args: {
-            selector: {
-              value: options.window.document.getElementById("testImage")
-            },
-          }
-        },
-      },
-    ]);
-  },
+function test() {
+  return Task.spawn(spawnTest).then(finish, helpers.handleError);
+}
 
-  testCaptureFile: function(options) {
-    let file = FileUtils.getFile("TmpD", [ "TestScreenshotFile.png" ]);
+function spawnTest() {
+  waitForExplicitFinish();
 
-    return helpers.audit(options, [
-      {
-        setup: 'screenshot ' + file.path,
-        check: {
-          args: {
-            filename: { value: "" + file.path },
-            fullpage: { value: false },
-            clipboard: { value: false },
-            chrome: { value: false },
-          },
-        },
-        exec: {
-          output: new RegExp("^Saved to "),
-        },
-        post: function() {
-          // Bug 849168: screenshot command tests fail in try but not locally
-          // ok(file.exists(), "Screenshot file exists");
-
-          if (file.exists()) {
-            file.remove(false);
-          }
-        }
-      },
-    ]);
-  },
-
-  testCaptureClipboard: function(options) {
-    let clipid = Ci.nsIClipboard;
-    let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
-    let trans = Cc["@mozilla.org/widget/transferable;1"]
-                  .createInstance(Ci.nsITransferable);
-    trans.init(null);
-    trans.addDataFlavor("image/png");
+  info("RUN TEST: non-private window");
+  let normWin = yield addWindow({ private: false });
+  yield addTabWithToolbarRunTests(normWin);
+  normWin.close();
 
-    return helpers.audit(options, [
-      {
-        setup: 'screenshot --fullpage --clipboard',
-        check: {
-          args: {
-            fullpage: { value: true },
-            clipboard: { value: true },
-            chrome: { value: false },
-          },
-        },
-        exec: {
-          output: new RegExp("^Copied to clipboard.$"),
-        },
-        post: function() {
-          try {
-            clip.getData(trans, clipid.kGlobalClipboard);
-            let str = new Object();
-            let strLength = new Object();
-            trans.getTransferData("image/png", str, strLength);
-
-            ok(str.value, "screenshot exists");
-            ok(strLength.value > 0, "screenshot has length");
-          }
-          finally {
-            Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
-
-            // Recent PB changes to the test I'm modifying removed the 'pb'
-            // variable, but left this line in tact. This seems so obviously
-            // wrong that I'm leaving this in in case the analysis is wrong
-            // pb.privateBrowsingEnabled = true;
-          }
-        }
-      },
-    ]);
-  },
-};
-
-function test() {
-  info("RUN TEST: non-private window");
-  let nonPrivDone = addWindow({ private: false }, addTabWithToolbarRunTests);
-
-  let privDone = nonPrivDone.then(function() {
-    info("RUN TEST: private window");
-    return addWindow({ private: true }, addTabWithToolbarRunTests);
-  });
-
-  privDone.then(finish, function(error) {
-    ok(false, 'Promise fail: ' + error);
-  });
+  info("RUN TEST: private window");
+  let pbWin = yield addWindow({ private: true });
+  yield addTabWithToolbarRunTests(pbWin);
+  pbWin.close();
 }
 
 function addTabWithToolbarRunTests(win) {
-  return helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, tests);
-  }, { chromeWindow: win });
+  let options = yield helpers.openTab(TEST_URI, { chromeWindow: win });
+  yield helpers.openToolbar(options);
+
+  // Test input status
+  yield helpers.audit(options, [
+    {
+      setup: 'screenshot',
+      check: {
+        input:  'screenshot',
+        markup: 'VVVVVVVVVV',
+        status: 'VALID',
+        args: {
+        }
+      },
+    },
+    {
+      setup: 'screenshot abc.png',
+      check: {
+        input:  'screenshot abc.png',
+        markup: 'VVVVVVVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {
+          filename: { value: "abc.png"},
+        }
+      },
+    },
+    {
+      setup: 'screenshot --fullpage',
+      check: {
+        input:  'screenshot --fullpage',
+        markup: 'VVVVVVVVVVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {
+          fullpage: { value: true},
+        }
+      },
+    },
+    {
+      setup: 'screenshot abc --delay 5',
+      check: {
+        input:  'screenshot abc --delay 5',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {
+          filename: { value: "abc"},
+          delay: { value: 5 },
+        }
+      },
+    },
+    {
+      setup: 'screenshot --selector img#testImage',
+      check: {
+        input:  'screenshot --selector img#testImage',
+        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
+        status: 'VALID',
+        args: {
+          selector: {
+            value: options.window.document.getElementById("testImage")
+          },
+        }
+      },
+    },
+  ]);
+
+  // Test capture to file
+  let file = FileUtils.getFile("TmpD", [ "TestScreenshotFile.png" ]);
+
+  yield helpers.audit(options, [
+    {
+      setup: 'screenshot ' + file.path,
+      check: {
+        args: {
+          filename: { value: "" + file.path },
+          fullpage: { value: false },
+          clipboard: { value: false },
+          chrome: { value: false },
+        },
+      },
+      exec: {
+        output: new RegExp("^Saved to "),
+      },
+      post: function() {
+        // Bug 849168: screenshot command tests fail in try but not locally
+        // ok(file.exists(), "Screenshot file exists");
+
+        if (file.exists()) {
+          file.remove(false);
+        }
+      }
+    },
+  ]);
+
+  // Test capture to clipboard
+  let clipid = Ci.nsIClipboard;
+  let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
+  let trans = Cc["@mozilla.org/widget/transferable;1"]
+                .createInstance(Ci.nsITransferable);
+  trans.init(null);
+  trans.addDataFlavor("image/png");
+
+  yield helpers.audit(options, [
+    {
+      setup: 'screenshot --fullpage --clipboard',
+      check: {
+        args: {
+          fullpage: { value: true },
+          clipboard: { value: true },
+          chrome: { value: false },
+        },
+      },
+      exec: {
+        output: new RegExp("^Copied to clipboard.$"),
+      },
+      post: function() {
+        try {
+          clip.getData(trans, clipid.kGlobalClipboard);
+          let str = new Object();
+          let strLength = new Object();
+          trans.getTransferData("image/png", str, strLength);
+
+          ok(str.value, "screenshot exists");
+          ok(strLength.value > 0, "screenshot has length");
+        }
+        finally {
+          Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
+
+          // Recent PB changes to the test I'm modifying removed the 'pb'
+          // variable, but left this line in tact. This seems so obviously
+          // wrong that I'm leaving this in in case the analysis is wrong
+          // pb.privateBrowsingEnabled = true;
+        }
+      }
+    },
+  ]);
+
+  yield helpers.closeToolbar(options);
+  yield helpers.closeTab(options);
 }
 
-function addWindow(windowOptions, callback) {
-  waitForExplicitFinish();
+function addWindow(windowOptions) {
   let deferred = promise.defer();
 
   let win = OpenBrowserWindow(windowOptions);
 
+  // This feels hacky, we should refactor it
   whenDelayedStartupFinished(win, function() {
     // Would like to get rid of this executeSoon, but without it the url
     // (TEST_URI) provided in addTabWithToolbarRunTests hasn't loaded
     executeSoon(function() {
-      try {
-        let reply = callback(win);
-        promise.resolve(reply).then(function() {
-          win.close();
-          deferred.resolve();
-        });
-      }
-      catch (ex) {
-        deferred.reject(ex);
-      }
+      deferred.resolve(win);
     });
   });
 
   return deferred.promise;
 }
--- a/browser/devtools/commandline/test/browser_cmd_settings.js
+++ b/browser/devtools/commandline/test/browser_cmd_settings.js
@@ -3,68 +3,45 @@
 
 // Tests that the pref commands work
 
 let prefBranch = Cc["@mozilla.org/preferences-service;1"]
                     .getService(Ci.nsIPrefService).getBranch(null)
                     .QueryInterface(Ci.nsIPrefBranch2);
 
 let supportsString = Cc["@mozilla.org/supports-string;1"]
-                      .createInstance(Ci.nsISupportsString)
-
-let require = (Cu.import("resource://gre/modules/devtools/Require.jsm", {})).require;
+                      .createInstance(Ci.nsISupportsString);
 
 let settings = require("gcli/settings");
 
 const TEST_URI = "data:text/html;charset=utf-8,gcli-settings";
 
-let tiltEnabled = undefined;
-let tabSize = undefined;
-let remoteHost = undefined;
+function test() {
+  return Task.spawn(spawnTest).then(finish, helpers.handleError);
+}
 
-let tiltEnabledOrig = undefined;
-let tabSizeOrig = undefined;
-let remoteHostOrig = undefined;
+function spawnTest() {
+  // Setup
+  let options = yield helpers.openTab(TEST_URI);
 
-let tests = {};
+  let tiltEnabled = settings.getSetting("devtools.tilt.enabled");
+  let tabSize = settings.getSetting("devtools.editor.tabsize");
+  let remoteHost = settings.getSetting("devtools.debugger.remote-host");
 
-tests.setup = function() {
-  tiltEnabled = settings.getSetting("devtools.tilt.enabled");
-  tabSize = settings.getSetting("devtools.editor.tabsize");
-  remoteHost = settings.getSetting("devtools.debugger.remote-host");
-
-  tiltEnabledOrig = prefBranch.getBoolPref("devtools.tilt.enabled");
-  tabSizeOrig = prefBranch.getIntPref("devtools.editor.tabsize");
-  remoteHostOrig = prefBranch.getComplexValue(
+  let tiltEnabledOrig = prefBranch.getBoolPref("devtools.tilt.enabled");
+  let tabSizeOrig = prefBranch.getIntPref("devtools.editor.tabsize");
+  let remoteHostOrig = prefBranch.getComplexValue(
           "devtools.debugger.remote-host",
           Components.interfaces.nsISupportsString).data;
 
   info("originally: devtools.tilt.enabled = " + tiltEnabledOrig);
   info("originally: devtools.editor.tabsize = " + tabSizeOrig);
   info("originally: devtools.debugger.remote-host = " + remoteHostOrig);
-};
 
-tests.shutdown = function() {
-  prefBranch.setBoolPref("devtools.tilt.enabled", tiltEnabledOrig);
-  prefBranch.setIntPref("devtools.editor.tabsize", tabSizeOrig);
-  supportsString.data = remoteHostOrig;
-  prefBranch.setComplexValue("devtools.debugger.remote-host",
-          Components.interfaces.nsISupportsString,
-          supportsString);
-
-  tiltEnabled = undefined;
-  tabSize = undefined;
-  remoteHost = undefined;
-
-  tiltEnabledOrig = undefined;
-  tabSizeOrig = undefined;
-  remoteHostOrig = undefined;
-};
-
-tests.testSettings = function() {
+  // Actual tests
   is(tiltEnabled.value, tiltEnabledOrig, "tiltEnabled default");
   is(tabSize.value, tabSizeOrig, "tabSize default");
   is(remoteHost.value, remoteHostOrig, "remoteHost default");
 
   tiltEnabled.setDefault();
   tabSize.setDefault();
   remoteHost.setDefault();
 
@@ -122,15 +99,19 @@ tests.testSettings = function() {
   tabSize.setDefault();
   remoteHost.setDefault();
 
   remoteHost.onChange.remove(remoteHostReCheck);
 
   is(tiltEnabled.value, tiltEnabledDefault, "tiltEnabled reset");
   is(tabSize.value, tabSizeDefault, "tabSize reset");
   is(remoteHost.value, remoteHostDefault, "remoteHost reset");
-};
 
-function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, tests);
-  }).then(finish);
+  // Cleanup
+  prefBranch.setBoolPref("devtools.tilt.enabled", tiltEnabledOrig);
+  prefBranch.setIntPref("devtools.editor.tabsize", tabSizeOrig);
+  supportsString.data = remoteHostOrig;
+  prefBranch.setComplexValue("devtools.debugger.remote-host",
+          Components.interfaces.nsISupportsString,
+          supportsString);
+
+  yield helpers.closeTab(options);
 }
--- a/browser/devtools/commandline/test/browser_gcli_async.js
+++ b/browser/devtools/commandline/test/browser_gcli_async.js
@@ -9,74 +9,45 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testAsync.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testAsync.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var helpers = require('gclitest/helpers');
-var canon = require('gcli/canon');
-var promise = require('util/promise');
+// var helpers = require('./helpers');
 
 exports.testBasic = function(options) {
-  var getData = function() {
-    var deferred = promise.defer();
-
-    var resolve = function() {
-      deferred.resolve([
-        'Shalom', 'Namasté', 'Hallo', 'Dydd-da',
-        'Chào', 'Hej', 'Saluton', 'Sawubona'
-      ]);
-    };
-
-    setTimeout(resolve, 10);
-    return deferred.promise;
-  };
-
-  var tsslow = {
-    name: 'tsslow',
-    params: [
-      {
-        name: 'hello',
-        type: {
-          name: 'selection',
-          data: getData
-        }
-      }
-    ],
-    exec: function(args, context) {
-      return 'Test completed';
-    }
-  };
-
-  canon.addCommand(tsslow);
-
   return helpers.audit(options, [
     {
       setup:    'tsslo',
       check: {
         input:  'tsslo',
         hints:       'w',
         markup: 'IIIII',
         cursor: 5,
@@ -100,18 +71,17 @@ exports.testBasic = function(options) {
           'Saluton', 'Sawubona'
         ],
         unassigned: [ ],
         args: {
           command: { name: 'tsslow' },
           hello: {
             value: undefined,
             arg: '',
-            status: 'INCOMPLETE',
-            message: ''
+            status: 'INCOMPLETE'
           },
         }
       }
     },
     {
       setup:    'tsslow S',
       check: {
         input:  'tsslow S',
@@ -122,24 +92,22 @@ exports.testBasic = function(options) {
         status: 'ERROR',
         predictions: [ 'Shalom', 'Saluton', 'Sawubona', 'Namasté' ],
         unassigned: [ ],
         args: {
           command: { name: 'tsslow' },
           hello: {
             value: undefined,
             arg: ' S',
-            status: 'INCOMPLETE',
-            message: ''
+            status: 'INCOMPLETE'
           },
         }
       }
     },
     {
-      skipIf: options.isJsdom,
       setup:    'tsslow S<TAB>',
       check: {
         input:  'tsslow Shalom ',
         hints:                '',
         markup: 'VVVVVVVVVVVVVV',
         cursor: 14,
         current: 'hello',
         status: 'VALID',
@@ -149,28 +117,12 @@ exports.testBasic = function(options) {
           command: { name: 'tsslow' },
           hello: {
             value: 'Shalom',
             arg: ' Shalom ',
             status: 'VALID',
             message: ''
           },
         }
-      },
-      post: function() {
-        canon.removeCommand(tsslow);
-      }
-    },
-    {
-      skipIf: options.isJsdom,
-      setup:    'tsslow ',
-      check: {
-        input:  'tsslow ',
-        markup: 'EEEEEEV',
-        cursor: 7,
-        status: 'ERROR'
       }
     }
   ]);
 };
-
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_canon.js
+++ b/browser/devtools/commandline/test/browser_gcli_canon.js
@@ -9,60 +9,66 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCanon.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCanon.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var helpers = require('gclitest/helpers');
-var canon = require('gcli/canon');
-// var assert = require('test/assert');
-var Canon = canon.Canon;
+// var assert = require('../testharness/assert');
+// var helpers = require('./helpers');
+var Canon = require('gcli/commands/commands').Canon;
 
 var startCount;
 var events;
 
 var canonChange = function(ev) {
   events++;
 };
 
 exports.setup = function(options) {
-  startCount = canon.getCommands().length;
+  startCount = options.requisition.canon.getCommands().length;
   events = 0;
 };
 
 exports.shutdown = function(options) {
   startCount = undefined;
   events = undefined;
 };
 
 exports.testAddRemove1 = function(options) {
+  var canon = options.requisition.canon;
+
   return helpers.audit(options, [
     {
       name: 'testadd add',
       setup: function() {
         canon.onCanonChange.add(canonChange);
 
         canon.addCommand({
           name: 'testadd',
@@ -138,16 +144,18 @@ exports.testAddRemove1 = function(option
         status: 'ERROR',
         unassigned: [ ],
       }
     }
   ]);
 };
 
 exports.testAddRemove2 = function(options) {
+  var canon = options.requisition.canon;
+
   canon.addCommand({
     name: 'testadd',
     exec: function() {
       return 3;
     }
   });
 
   assert.is(canon.getCommands().length,
@@ -178,32 +186,35 @@ exports.testAddRemove2 = function(option
         typed: 'testadd',
         status: 'ERROR'
       }
     }
   ]);
 };
 
 exports.testAddRemove3 = function(options) {
+  var canon = options.requisition.canon;
+
   canon.removeCommand({ name: 'nonexistant' });
   assert.is(canon.getCommands().length,
             startCount,
             'nonexistant1 command success');
   assert.is(events, 5, 'nonexistant1 event');
 
   canon.removeCommand('nonexistant');
   assert.is(canon.getCommands().length,
             startCount,
             'nonexistant2 command success');
   assert.is(events, 5, 'nonexistant2 event');
 
   canon.onCanonChange.remove(canonChange);
 };
 
 exports.testAltCanon = function(options) {
+  var canon = options.requisition.canon;
   var altCanon = new Canon();
 
   var tss = {
     name: 'tss',
     params: [
       { name: 'str', type: 'string' },
       { name: 'num', type: 'number' },
       { name: 'opt', type: { name: 'selection', data: [ '1', '2', '3' ] } },
@@ -212,31 +223,31 @@ exports.testAltCanon = function(options)
       return context.commandName + ':' +
               args.str + ':' + args.num + ':' + args.opt;
     }
   };
   altCanon.addCommand(tss);
 
   var commandSpecs = altCanon.getCommandSpecs();
   assert.is(JSON.stringify(commandSpecs),
-            '{"tss":{"name":"tss","description":"(No description)","params":[' +
-              '{"name":"str","type":"string","description":"(No description)"},' +
-              '{"name":"num","type":"number","description":"(No description)"},' +
-              '{"name":"opt","type":{"name":"selection","data":["1","2","3"]},"description":"(No description)"}'+
-            '],"isParent":false}}',
+            '[{"item":"command","name":"tss","params":[' +
+              '{"name":"str","type":"string"},' +
+              '{"name":"num","type":"number"},' +
+              '{"name":"opt","type":{"name":"selection","data":["1","2","3"]}}' +
+            '],"isParent":false}]',
             'JSON.stringify(commandSpecs)');
 
   var remoter = function(args, context) {
     assert.is(context.commandName, 'tss', 'commandName is tss');
 
     var cmd = altCanon.getCommand(context.commandName);
     return cmd.exec(args, context);
   };
 
-  canon.addProxyCommands('proxy', commandSpecs, remoter, 'test');
+  canon.addProxyCommands(commandSpecs, remoter, 'proxy', 'test');
 
   var parent = canon.getCommand('proxy');
   assert.is(parent.name, 'proxy', 'Parent command called proxy');
 
   var child = canon.getCommand('proxy tss');
   assert.is(child.name, 'proxy tss', 'child command called proxy tss');
 
   return helpers.audit(options, [
@@ -262,11 +273,8 @@ exports.testAltCanon = function(options)
         canon.removeCommand('proxy tss');
 
         assert.is(canon.getCommand('proxy'), undefined, 'remove proxy');
         assert.is(canon.getCommand('proxy tss'), undefined, 'remove proxy tss');
       }
     }
   ]);
 };
-
-
-// });
rename from browser/devtools/commandline/test/browser_gcli_cli.js
rename to browser/devtools/commandline/test/browser_gcli_cli1.js
--- a/browser/devtools/commandline/test/browser_gcli_cli.js
+++ b/browser/devtools/commandline/test/browser_gcli_cli1.js
@@ -9,121 +9,117 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCli.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCli1.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
-var nodetype = require('gcli/types/node');
-
-// var assert = require('test/assert');
-
-exports.setup = function(options) {
-  mockCommands.setup();
-  nodetype.setDocument(options.window.document);
-};
-
-exports.shutdown = function(options) {
-  mockCommands.shutdown();
-  nodetype.unsetDocument();
-};
+// var assert = require('../testharness/assert');
+// var helpers = require('./helpers');
 
 exports.testBlank = function(options) {
-  var requisition = options.display.requisition;
-
   return helpers.audit(options, [
     {
       setup:    '',
       check: {
         input:  '',
         hints:  '',
         markup: '',
         cursor: 0,
         current: '__command',
         status: 'ERROR'
       },
       post: function() {
-        assert.is(requisition.commandAssignment.value, undefined);
+        assert.is(options.requisition.commandAssignment.value, undefined);
       }
     },
     {
       setup:    ' ',
       check: {
         input:  ' ',
         hints:   '',
         markup: 'V',
         cursor: 1,
         current: '__command',
         status: 'ERROR'
       },
       post: function() {
-        assert.is(requisition.commandAssignment.value, undefined);
+        assert.is(options.requisition.commandAssignment.value, undefined);
       }
     },
     {
       name: '| ',
       setup: function() {
-        helpers.setInput(options, ' ', 0);
+        return helpers.setInput(options, ' ', 0);
       },
       check: {
         input:  ' ',
         hints:   '',
         markup: 'V',
         cursor: 0,
         current: '__command',
         status: 'ERROR'
       },
       post: function() {
-        assert.is(requisition.commandAssignment.value, undefined);
+        assert.is(options.requisition.commandAssignment.value, undefined);
+      }
+    }
+  ]);
+};
+
+exports.testDelete = function(options) {
+  return helpers.audit(options, [
+    {
+      setup:    'x<BACKSPACE>',
+      check: {
+        input:  '',
+        hints:  '',
+        markup: '',
+        cursor: 0,
+        current: '__command',
+        status: 'ERROR'
+      },
+      post: function() {
+        assert.is(options.requisition.commandAssignment.value, undefined);
       }
     }
   ]);
 };
 
 exports.testIncompleteMultiMatch = function(options) {
   return helpers.audit(options, [
     {
-      setup:    't',
-      skipIf: options.isFirefox, // 't' hints at 'tilt' in firefox
-      check: {
-        input:  't',
-        hints:   'est',
-        markup: 'I',
-        cursor: 1,
-        current: '__command',
-        status: 'ERROR',
-        predictionsContains: [ 'tsb' ]
-      }
-    },
-    {
       setup:    'tsn ex',
       check: {
         input:  'tsn ex',
         hints:        't',
         markup: 'IIIVII',
         cursor: 6,
         current: '__command',
         status: 'ERROR',
@@ -163,18 +159,18 @@ exports.testTsv = function(options) {
         markup: 'VVV',
         cursor: 3,
         current: '__command',
         status: 'ERROR',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsv' },
-          optionType: { arg: '', status: 'INCOMPLETE', message: '' },
-          optionValue: { arg: '', status: 'INCOMPLETE', message: '' }
+          optionType: { arg: '', status: 'INCOMPLETE' },
+          optionValue: { arg: '', status: 'INCOMPLETE' }
         }
       }
     },
     {
       setup:    'tsv ',
       check: {
         input:  'tsv ',
         hints:      'option1 <optionValue>',
@@ -182,39 +178,39 @@ exports.testTsv = function(options) {
         cursor: 4,
         current: 'optionType',
         status: 'ERROR',
         predictions: [ 'option1', 'option2', 'option3' ],
         unassigned: [ ],
         tooltipState: 'true:importantFieldFlag',
         args: {
           command: { name: 'tsv' },
-          optionType: { arg: '', status: 'INCOMPLETE', message: '' },
-          optionValue: { arg: '', status: 'INCOMPLETE', message: '' }
+          optionType: { arg: '', status: 'INCOMPLETE' },
+          optionValue: { arg: '', status: 'INCOMPLETE' }
         }
       }
     },
     {
       name: 'ts|v',
       setup: function() {
-        helpers.setInput(options, 'tsv ', 2);
+        return helpers.setInput(options, 'tsv ', 2);
       },
       check: {
         input:  'tsv ',
         hints:      '<optionType> <optionValue>',
         markup: 'VVVV',
         cursor: 2,
         current: '__command',
         status: 'ERROR',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsv' },
-          optionType: { arg: '', status: 'INCOMPLETE', message: '' },
-          optionValue: { arg: '', status: 'INCOMPLETE', message: '' }
+          optionType: { arg: '', status: 'INCOMPLETE' },
+          optionValue: { arg: '', status: 'INCOMPLETE' }
         }
       }
     },
     {
       setup:    'tsv o',
       check: {
         input:  'tsv o',
         hints:       'ption1 <optionValue>',
@@ -226,23 +222,23 @@ exports.testTsv = function(options) {
         unassigned: [ ],
         tooltipState: 'true:importantFieldFlag',
         args: {
           command: { name: 'tsv' },
           optionType: {
             value: undefined,
             arg: ' o',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'optionType\'.'
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'optionValue\'.'
           }
         }
       }
     },
     {
       setup:    'tsv option',
       check: {
         input:  'tsv option',
@@ -255,28 +251,29 @@ exports.testTsv = function(options) {
         unassigned: [ ],
         tooltipState: 'true:importantFieldFlag',
         args: {
           command: { name: 'tsv' },
           optionType: {
             value: undefined,
             arg: ' option',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'optionType\'.'
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'optionValue\'.'
           }
         }
       }
     },
     {
+      skipRemainingIf: options.isNoDom,
       name: '|tsv option',
       setup: function() {
         return helpers.setInput(options, 'tsv option', 0);
       },
       check: {
         input:  'tsv option',
         hints:            ' <optionValue>',
         markup: 'VVVVEEEEEE',
@@ -286,23 +283,23 @@ exports.testTsv = function(options) {
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsv' },
           optionType: {
             value: undefined,
             arg: ' option',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'optionType\'.'
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'optionValue\'.'
           }
         }
       }
     },
     {
       setup:    'tsv option ',
       check: {
         input:  'tsv option ',
@@ -321,17 +318,17 @@ exports.testTsv = function(options) {
             arg: ' option ',
             status: 'ERROR',
             message: 'Can\'t use \'option\'.'
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'optionValue\'.'
           }
         }
       }
     },
     {
       setup:    'tsv option1',
       check: {
         input:  'tsv option1',
@@ -341,26 +338,26 @@ exports.testTsv = function(options) {
         current: 'optionType',
         status: 'ERROR',
         predictions: [ 'option1' ],
         unassigned: [ ],
         tooltipState: 'true:importantFieldFlag',
         args: {
           command: { name: 'tsv' },
           optionType: {
-            value: mockCommands.option1,
+            value: 'string',
             arg: ' option1',
             status: 'VALID',
             message: ''
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'optionValue\'.'
           }
         }
       }
     },
     {
       setup:    'tsv option1 ',
       check: {
         input:  'tsv option1 ',
@@ -369,26 +366,26 @@ exports.testTsv = function(options) {
         cursor: 12,
         current: 'optionValue',
         status: 'ERROR',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsv' },
           optionType: {
-            value: mockCommands.option1,
+            value: 'string',
             arg: ' option1 ',
             status: 'VALID',
             message: ''
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'optionValue\'.'
           }
         }
       }
     },
     {
       setup:    'tsv option2',
       check: {
         input:  'tsv option2',
@@ -398,51 +395,55 @@ exports.testTsv = function(options) {
         current: 'optionType',
         status: 'ERROR',
         predictions: [ 'option2' ],
         unassigned: [ ],
         tooltipState: 'true:importantFieldFlag',
         args: {
           command: { name: 'tsv' },
           optionType: {
-            value: mockCommands.option2,
+            value: 'number',
             arg: ' option2',
             status: 'VALID',
             message: ''
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'optionValue\'.'
           }
         }
       }
-    },
+    }
+  ]);
+};
+
+exports.testTsvValues = function(options) {
+  return helpers.audit(options, [
     {
       setup:    'tsv option1 6',
       check: {
         input:  'tsv option1 6',
         hints:               '',
         markup: 'VVVVVVVVVVVVV',
         cursor: 13,
         current: 'optionValue',
         status: 'VALID',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsv' },
           optionType: {
-            value: mockCommands.option1,
+            value: 'string',
             arg: ' option1',
             status: 'VALID',
             message: ''
           },
           optionValue: {
-            value: '6',
             arg: ' 6',
             status: 'VALID',
             message: ''
           }
         }
       }
     },
     {
@@ -454,29 +455,48 @@ exports.testTsv = function(options) {
         cursor: 13,
         current: 'optionValue',
         status: 'VALID',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsv' },
           optionType: {
-            value: mockCommands.option2,
+            value: 'number',
             arg: ' option2',
             status: 'VALID',
             message: ''
           },
           optionValue: {
-            value: 6,
             arg: ' 6',
             status: 'VALID',
             message: ''
           }
         }
       }
+    },
+    // Delegated remote types can't transfer value types so we only test for
+    // the value of 'value' when we're local
+    {
+      skipIf: options.isRemote,
+      setup: 'tsv option1 6',
+      check: {
+        args: {
+          optionValue: { value: '6' }
+        }
+      }
+    },
+    {
+      skipIf: options.isRemote,
+      setup: 'tsv option2 6',
+      check: {
+        args: {
+          optionValue: { value: 6 }
+        }
+      }
     }
   ]);
 };
 
 exports.testInvalid = function(options) {
   return helpers.audit(options, [
     {
       setup:    'zxjq',
@@ -517,809 +537,8 @@ exports.testInvalid = function(options) 
         status: 'ERROR',
         predictions: [ ],
         unassigned: [ ' one' ],
         tooltipState: 'true:isError'
       }
     }
   ]);
 };
-
-exports.testSingleString = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    'tsr',
-      check: {
-        input:  'tsr',
-        hints:     ' <text>',
-        markup: 'VVV',
-        cursor: 3,
-        current: '__command',
-        status: 'ERROR',
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsr' },
-          text: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsr ',
-      check: {
-        input:  'tsr ',
-        hints:      '<text>',
-        markup: 'VVVV',
-        cursor: 4,
-        current: 'text',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsr' },
-          text: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsr h',
-      check: {
-        input:  'tsr h',
-        hints:       '',
-        markup: 'VVVVV',
-        cursor: 5,
-        current: 'text',
-        status: 'VALID',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsr' },
-          text: {
-            value: 'h',
-            arg: ' h',
-            status: 'VALID',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsr "h h"',
-      check: {
-        input:  'tsr "h h"',
-        hints:           '',
-        markup: 'VVVVVVVVV',
-        cursor: 9,
-        current: 'text',
-        status: 'VALID',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsr' },
-          text: {
-            value: 'h h',
-            arg: ' "h h"',
-            status: 'VALID',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsr h h h',
-      check: {
-        input:  'tsr h h h',
-        hints:           '',
-        markup: 'VVVVVVVVV',
-        cursor: 9,
-        current: 'text',
-        status: 'VALID',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsr' },
-          text: {
-            value: 'h h h',
-            arg: ' h h h',
-            status: 'VALID',
-            message: ''
-          }
-        }
-      }
-    }
-  ]);
-};
-
-exports.testSingleNumber = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    'tsu',
-      check: {
-        input:  'tsu',
-        hints:     ' <num>',
-        markup: 'VVV',
-        cursor: 3,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsu' },
-          num: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsu ',
-      check: {
-        input:  'tsu ',
-        hints:      '<num>',
-        markup: 'VVVV',
-        cursor: 4,
-        current: 'num',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsu' },
-          num: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsu 1',
-      check: {
-        input:  'tsu 1',
-        hints:       '',
-        markup: 'VVVVV',
-        cursor: 5,
-        current: 'num',
-        status: 'VALID',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsu' },
-          num: { value: 1, arg: ' 1', status: 'VALID', message: '' }
-        }
-      }
-    },
-    {
-      setup:    'tsu x',
-      check: {
-        input:  'tsu x',
-        hints:       '',
-        markup: 'VVVVE',
-        cursor: 5,
-        current: 'num',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        tooltipState: 'true:isError',
-        args: {
-          command: { name: 'tsu' },
-          num: {
-            value: undefined,
-            arg: ' x',
-            status: 'ERROR',
-            message: 'Can\'t convert "x" to a number.'
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsu 1.5',
-      check: {
-        input:  'tsu 1.5',
-        hints:       '',
-        markup: 'VVVVEEE',
-        cursor: 7,
-        current: 'num',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsu' },
-          num: {
-            value: undefined,
-            arg: ' 1.5',
-            status: 'ERROR',
-            message: 'Can\'t convert "1.5" to an integer.'
-          }
-        }
-      }
-    }
-  ]);
-};
-
-exports.testSingleFloat = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    'tsf',
-      check: {
-        input:  'tsf',
-        hints:     ' <num>',
-        markup: 'VVV',
-        cursor: 3,
-        current: '__command',
-        status: 'ERROR',
-        error: '',
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsf' },
-          num: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsf 1',
-      check: {
-        input:  'tsf 1',
-        hints:       '',
-        markup: 'VVVVV',
-        cursor: 5,
-        current: 'num',
-        status: 'VALID',
-        error: '',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsf' },
-          num: { value: 1, arg: ' 1', status: 'VALID', message: '' }
-        }
-      }
-    },
-    {
-      setup:    'tsf 1.',
-      check: {
-        input:  'tsf 1.',
-        hints:        '',
-        markup: 'VVVVVV',
-        cursor: 6,
-        current: 'num',
-        status: 'VALID',
-        error: '',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsf' },
-          num: { value: 1, arg: ' 1.', status: 'VALID', message: '' }
-        }
-      }
-    },
-    {
-      setup:    'tsf 1.5',
-      check: {
-        input:  'tsf 1.5',
-        hints:         '',
-        markup: 'VVVVVVV',
-        cursor: 7,
-        current: 'num',
-        status: 'VALID',
-        error: '',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsf' },
-          num: { value: 1.5, arg: ' 1.5', status: 'VALID', message: '' }
-        }
-      }
-    },
-    {
-      setup:    'tsf 1.5x',
-      check: {
-        input:  'tsf 1.5x',
-        hints:          '',
-        markup: 'VVVVVVVV',
-        cursor: 8,
-        current: 'num',
-        status: 'VALID',
-        error: '',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsf' },
-          num: { value: 1.5, arg: ' 1.5x', status: 'VALID', message: '' }
-        }
-      }
-    },
-    {
-      name: 'tsf x (cursor=4)',
-      setup: function() {
-        return helpers.setInput(options, 'tsf x', 4);
-      },
-      check: {
-        input:  'tsf x',
-        hints:       '',
-        markup: 'VVVVE',
-        cursor: 4,
-        current: 'num',
-        status: 'ERROR',
-        error: 'Can\'t convert "x" to a number.',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsf' },
-          num: {
-            value: undefined,
-            arg: ' x',
-            status: 'ERROR',
-            message: 'Can\'t convert "x" to a number.'
-          }
-        }
-      }
-    }
-  ]);
-};
-
-exports.testElementDom = function(options) {
-  return helpers.audit(options, [
-    {
-      skipIf: options.isJsdom,
-      setup:    'tse :root',
-      check: {
-        input:  'tse :root',
-        hints:           ' [options]',
-        markup: 'VVVVVVVVV',
-        cursor: 9,
-        current: 'node',
-        status: 'VALID',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tse' },
-          node: {
-            value: options.window.document.documentElement,
-            arg: ' :root',
-            status: 'VALID',
-            message: ''
-          },
-          nodes: { arg: '', status: 'VALID', message: '' },
-          nodes2: { arg: '', status: 'VALID', message: '' },
-        }
-      }
-    }
-  ]);
-};
-
-exports.testElementWeb = function(options) {
-  var inputElement = options.window.document.getElementById('gcli-input');
-
-  return helpers.audit(options, [
-    {
-      skipIf: function gcliInputElementExists() {
-        return inputElement == null || options.isJsdom;
-      },
-      setup:    'tse #gcli-input',
-      check: {
-        input:  'tse #gcli-input',
-        hints:                 ' [options]',
-        markup: 'VVVVVVVVVVVVVVV',
-        cursor: 15,
-        current: 'node',
-        status: 'VALID',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tse' },
-          node: {
-            value: inputElement,
-            arg: ' #gcli-input',
-            status: 'VALID',
-            message: ''
-          },
-          nodes: { arg: '', status: 'VALID', message: '' },
-          nodes2: { arg: '', status: 'VALID', message: '' },
-        }
-      }
-    }
-  ]);
-};
-
-exports.testElement = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    'tse',
-      check: {
-        input:  'tse',
-        hints:     ' <node> [options]',
-        markup: 'VVV',
-        cursor: 3,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ 'tse', 'tselarr' ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tse' },
-          node: { value: undefined, arg: '', status: 'INCOMPLETE', message: '' },
-          nodes: { arg: '', status: 'VALID', message: '' },
-          nodes2: { arg: '', status: 'VALID', message: '' },
-        }
-      }
-    },
-    {
-      skipIf: options.isJsdom,
-      setup:    'tse #gcli-nomatch',
-      check: {
-        input:  'tse #gcli-nomatch',
-        hints:                   ' [options]',
-        markup: 'VVVVIIIIIIIIIIIII',
-        cursor: 17,
-        current: 'node',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        outputState: 'false:default',
-        tooltipState: 'true:isError',
-        args: {
-          command: { name: 'tse' },
-          node: {
-            value: undefined,
-            arg: ' #gcli-nomatch',
-            // This is somewhat debatable because this input can't be corrected
-            // simply by typing so it's and error rather than incomplete,
-            // however without digging into the CSS engine we can't tell that
-            // so we default to incomplete
-            status: 'INCOMPLETE',
-            message: 'No matches'
-          },
-          nodes: { arg: '', status: 'VALID', message: '' },
-          nodes2: { arg: '', status: 'VALID', message: '' },
-        }
-      }
-    },
-    {
-      setup:    'tse #',
-      check: {
-        input:  'tse #',
-        hints:       ' [options]',
-        markup: 'VVVVE',
-        cursor: 5,
-        current: 'node',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        tooltipState: 'true:isError',
-        args: {
-          command: { name: 'tse' },
-          node: {
-            value: undefined,
-            arg: ' #',
-            status: 'ERROR',
-            message: 'Syntax error in CSS query'
-          },
-          nodes: { arg: '', status: 'VALID', message: '' },
-          nodes2: { arg: '', status: 'VALID', message: '' },
-        }
-      }
-    },
-    {
-      setup:    'tse .',
-      check: {
-        input:  'tse .',
-        hints:       ' [options]',
-        markup: 'VVVVE',
-        cursor: 5,
-        current: 'node',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        tooltipState: 'true:isError',
-        args: {
-          command: { name: 'tse' },
-          node: {
-            value: undefined,
-            arg: ' .',
-            status: 'ERROR',
-            message: 'Syntax error in CSS query'
-          },
-          nodes: { arg: '', status: 'VALID', message: '' },
-          nodes2: { arg: '', status: 'VALID', message: '' },
-        }
-      }
-    },
-    {
-      skipIf: options.isJsdom,
-      setup:    'tse *',
-      check: {
-        input:  'tse *',
-        hints:       ' [options]',
-        markup: 'VVVVE',
-        cursor: 5,
-        current: 'node',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        tooltipState: 'true:isError',
-        args: {
-          command: { name: 'tse' },
-          node: {
-            value: undefined,
-            arg: ' *',
-            status: 'ERROR',
-            message: /^Too many matches \([0-9]*\)/
-          },
-          nodes: { arg: '', status: 'VALID', message: '' },
-          nodes2: { arg: '', status: 'VALID', message: '' },
-        }
-      }
-    }
-  ]);
-};
-
-exports.testNestedCommand = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    'tsn',
-      check: {
-        input:  'tsn',
-        hints:     ' deep down nested cmd',
-        markup: 'III',
-        cursor: 3,
-        current: '__command',
-        status: 'ERROR',
-        predictionsInclude: [
-          'tsn deep', 'tsn deep down', 'tsn deep down nested',
-          'tsn deep down nested cmd', 'tsn dif'
-        ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsn' }
-        }
-      }
-    },
-    {
-      setup:    'tsn ',
-      check: {
-        input:  'tsn ',
-        hints:      ' deep down nested cmd',
-        markup: 'IIIV',
-        cursor: 4,
-        current: '__command',
-        status: 'ERROR',
-        unassigned: [ ]
-      }
-    },
-    {
-      skipIf: options.isPhantomjs,
-      setup:    'tsn x',
-      check: {
-        input:  'tsn x',
-        hints:       ' -> tsn ext',
-        markup: 'IIIVI',
-        cursor: 5,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ 'tsn ext' ],
-        unassigned: [ ]
-      }
-    },
-    {
-      setup:    'tsn dif',
-      check: {
-        input:  'tsn dif',
-        hints:         ' <text>',
-        markup: 'VVVVVVV',
-        cursor: 7,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsn dif' },
-          text: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsn dif ',
-      check: {
-        input:  'tsn dif ',
-        hints:          '<text>',
-        markup: 'VVVVVVVV',
-        cursor: 8,
-        current: 'text',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsn dif' },
-          text: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsn dif x',
-      check: {
-        input:  'tsn dif x',
-        hints:           '',
-        markup: 'VVVVVVVVV',
-        cursor: 9,
-        current: 'text',
-        status: 'VALID',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsn dif' },
-          text: { value: 'x', arg: ' x', status: 'VALID', message: '' }
-        }
-      }
-    },
-    {
-      setup:    'tsn ext',
-      check: {
-        input:  'tsn ext',
-        hints:         ' <text>',
-        markup: 'VVVVVVV',
-        cursor: 7,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ 'tsn ext', 'tsn exte', 'tsn exten', 'tsn extend' ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsn ext' },
-          text: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsn exte',
-      check: {
-        input:  'tsn exte',
-        hints:          ' <text>',
-        markup: 'VVVVVVVV',
-        cursor: 8,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ 'tsn exte', 'tsn exten', 'tsn extend' ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsn exte' },
-          text: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsn exten',
-      check: {
-        input:  'tsn exten',
-        hints:           ' <text>',
-        markup: 'VVVVVVVVV',
-        cursor: 9,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ 'tsn exten', 'tsn extend' ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsn exten' },
-          text: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsn extend',
-      check: {
-        input:  'tsn extend',
-        hints:            ' <text>',
-        markup: 'VVVVVVVVVV',
-        cursor: 10,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsn extend' },
-          text: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'ts ',
-      check: {
-        input:  'ts ',
-        hints:     '',
-        markup: 'EEV',
-        cursor: 3,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        tooltipState: 'true:isError'
-      }
-    },
-  ]);
-};
-
-// From Bug 664203
-exports.testDeeplyNested = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    'tsn deep down nested',
-      check: {
-        input:  'tsn deep down nested',
-        hints:                      ' cmd',
-        markup: 'IIIVIIIIVIIIIVIIIIII',
-        cursor: 20,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ 'tsn deep down nested cmd' ],
-        unassigned: [ ],
-        outputState: 'false:default',
-        tooltipState: 'false:default',
-        args: {
-          command: { name: 'tsn deep down nested' },
-        }
-      }
-    },
-    {
-      setup:    'tsn deep down nested cmd',
-      check: {
-        input:  'tsn deep down nested cmd',
-        hints:                          '',
-        markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
-        cursor: 24,
-        current: '__command',
-        status: 'VALID',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsn deep down nested cmd' },
-        }
-      }
-    }
-  ]);
-};
-
-
-// });
copy from browser/devtools/commandline/test/browser_gcli_cli.js
copy to browser/devtools/commandline/test/browser_gcli_cli2.js
--- a/browser/devtools/commandline/test/browser_gcli_cli.js
+++ b/browser/devtools/commandline/test/browser_gcli_cli2.js
@@ -9,525 +9,56 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCli.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCli2.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
+// var helpers = require('./helpers');
 
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
 var nodetype = require('gcli/types/node');
 
-// var assert = require('test/assert');
-
 exports.setup = function(options) {
-  mockCommands.setup();
-  nodetype.setDocument(options.window.document);
+  if (options.window) {
+    nodetype.setDocument(options.window.document);
+  }
 };
 
 exports.shutdown = function(options) {
-  mockCommands.shutdown();
   nodetype.unsetDocument();
 };
 
-exports.testBlank = function(options) {
-  var requisition = options.display.requisition;
-
-  return helpers.audit(options, [
-    {
-      setup:    '',
-      check: {
-        input:  '',
-        hints:  '',
-        markup: '',
-        cursor: 0,
-        current: '__command',
-        status: 'ERROR'
-      },
-      post: function() {
-        assert.is(requisition.commandAssignment.value, undefined);
-      }
-    },
-    {
-      setup:    ' ',
-      check: {
-        input:  ' ',
-        hints:   '',
-        markup: 'V',
-        cursor: 1,
-        current: '__command',
-        status: 'ERROR'
-      },
-      post: function() {
-        assert.is(requisition.commandAssignment.value, undefined);
-      }
-    },
-    {
-      name: '| ',
-      setup: function() {
-        helpers.setInput(options, ' ', 0);
-      },
-      check: {
-        input:  ' ',
-        hints:   '',
-        markup: 'V',
-        cursor: 0,
-        current: '__command',
-        status: 'ERROR'
-      },
-      post: function() {
-        assert.is(requisition.commandAssignment.value, undefined);
-      }
-    }
-  ]);
-};
-
-exports.testIncompleteMultiMatch = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    't',
-      skipIf: options.isFirefox, // 't' hints at 'tilt' in firefox
-      check: {
-        input:  't',
-        hints:   'est',
-        markup: 'I',
-        cursor: 1,
-        current: '__command',
-        status: 'ERROR',
-        predictionsContains: [ 'tsb' ]
-      }
-    },
-    {
-      setup:    'tsn ex',
-      check: {
-        input:  'tsn ex',
-        hints:        't',
-        markup: 'IIIVII',
-        cursor: 6,
-        current: '__command',
-        status: 'ERROR',
-        predictionsContains: [
-          'tsn ext', 'tsn exte', 'tsn exten', 'tsn extend'
-        ]
-      }
-    }
-  ]);
-};
-
-exports.testIncompleteSingleMatch = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    'tselar',
-      check: {
-        input:  'tselar',
-        hints:        'r',
-        markup: 'IIIIII',
-        cursor: 6,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ 'tselarr' ],
-        unassigned: [ ]
-      }
-    }
-  ]);
-};
-
-exports.testTsv = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    'tsv',
-      check: {
-        input:  'tsv',
-        hints:     ' <optionType> <optionValue>',
-        markup: 'VVV',
-        cursor: 3,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsv' },
-          optionType: { arg: '', status: 'INCOMPLETE', message: '' },
-          optionValue: { arg: '', status: 'INCOMPLETE', message: '' }
-        }
-      }
-    },
-    {
-      setup:    'tsv ',
-      check: {
-        input:  'tsv ',
-        hints:      'option1 <optionValue>',
-        markup: 'VVVV',
-        cursor: 4,
-        current: 'optionType',
-        status: 'ERROR',
-        predictions: [ 'option1', 'option2', 'option3' ],
-        unassigned: [ ],
-        tooltipState: 'true:importantFieldFlag',
-        args: {
-          command: { name: 'tsv' },
-          optionType: { arg: '', status: 'INCOMPLETE', message: '' },
-          optionValue: { arg: '', status: 'INCOMPLETE', message: '' }
-        }
-      }
-    },
-    {
-      name: 'ts|v',
-      setup: function() {
-        helpers.setInput(options, 'tsv ', 2);
-      },
-      check: {
-        input:  'tsv ',
-        hints:      '<optionType> <optionValue>',
-        markup: 'VVVV',
-        cursor: 2,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsv' },
-          optionType: { arg: '', status: 'INCOMPLETE', message: '' },
-          optionValue: { arg: '', status: 'INCOMPLETE', message: '' }
-        }
-      }
-    },
-    {
-      setup:    'tsv o',
-      check: {
-        input:  'tsv o',
-        hints:       'ption1 <optionValue>',
-        markup: 'VVVVI',
-        cursor: 5,
-        current: 'optionType',
-        status: 'ERROR',
-        predictions: [ 'option1', 'option2', 'option3' ],
-        unassigned: [ ],
-        tooltipState: 'true:importantFieldFlag',
-        args: {
-          command: { name: 'tsv' },
-          optionType: {
-            value: undefined,
-            arg: ' o',
-            status: 'INCOMPLETE',
-            message: ''
-          },
-          optionValue: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsv option',
-      check: {
-        input:  'tsv option',
-        hints:            '1 <optionValue>',
-        markup: 'VVVVIIIIII',
-        cursor: 10,
-        current: 'optionType',
-        status: 'ERROR',
-        predictions: [ 'option1', 'option2', 'option3' ],
-        unassigned: [ ],
-        tooltipState: 'true:importantFieldFlag',
-        args: {
-          command: { name: 'tsv' },
-          optionType: {
-            value: undefined,
-            arg: ' option',
-            status: 'INCOMPLETE',
-            message: ''
-          },
-          optionValue: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      name: '|tsv option',
-      setup: function() {
-        return helpers.setInput(options, 'tsv option', 0);
-      },
-      check: {
-        input:  'tsv option',
-        hints:            ' <optionValue>',
-        markup: 'VVVVEEEEEE',
-        cursor: 0,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsv' },
-          optionType: {
-            value: undefined,
-            arg: ' option',
-            status: 'INCOMPLETE',
-            message: ''
-          },
-          optionValue: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsv option ',
-      check: {
-        input:  'tsv option ',
-        hints:             '<optionValue>',
-        markup: 'VVVVEEEEEEV',
-        cursor: 11,
-        current: 'optionValue',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        tooltipState: 'false:default',
-        args: {
-          command: { name: 'tsv' },
-          optionType: {
-            value: undefined,
-            arg: ' option ',
-            status: 'ERROR',
-            message: 'Can\'t use \'option\'.'
-          },
-          optionValue: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsv option1',
-      check: {
-        input:  'tsv option1',
-        hints:             ' <optionValue>',
-        markup: 'VVVVVVVVVVV',
-        cursor: 11,
-        current: 'optionType',
-        status: 'ERROR',
-        predictions: [ 'option1' ],
-        unassigned: [ ],
-        tooltipState: 'true:importantFieldFlag',
-        args: {
-          command: { name: 'tsv' },
-          optionType: {
-            value: mockCommands.option1,
-            arg: ' option1',
-            status: 'VALID',
-            message: ''
-          },
-          optionValue: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsv option1 ',
-      check: {
-        input:  'tsv option1 ',
-        hints:              '<optionValue>',
-        markup: 'VVVVVVVVVVVV',
-        cursor: 12,
-        current: 'optionValue',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsv' },
-          optionType: {
-            value: mockCommands.option1,
-            arg: ' option1 ',
-            status: 'VALID',
-            message: ''
-          },
-          optionValue: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsv option2',
-      check: {
-        input:  'tsv option2',
-        hints:             ' <optionValue>',
-        markup: 'VVVVVVVVVVV',
-        cursor: 11,
-        current: 'optionType',
-        status: 'ERROR',
-        predictions: [ 'option2' ],
-        unassigned: [ ],
-        tooltipState: 'true:importantFieldFlag',
-        args: {
-          command: { name: 'tsv' },
-          optionType: {
-            value: mockCommands.option2,
-            arg: ' option2',
-            status: 'VALID',
-            message: ''
-          },
-          optionValue: {
-            value: undefined,
-            arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsv option1 6',
-      check: {
-        input:  'tsv option1 6',
-        hints:               '',
-        markup: 'VVVVVVVVVVVVV',
-        cursor: 13,
-        current: 'optionValue',
-        status: 'VALID',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsv' },
-          optionType: {
-            value: mockCommands.option1,
-            arg: ' option1',
-            status: 'VALID',
-            message: ''
-          },
-          optionValue: {
-            value: '6',
-            arg: ' 6',
-            status: 'VALID',
-            message: ''
-          }
-        }
-      }
-    },
-    {
-      setup:    'tsv option2 6',
-      check: {
-        input:  'tsv option2 6',
-        hints:               '',
-        markup: 'VVVVVVVVVVVVV',
-        cursor: 13,
-        current: 'optionValue',
-        status: 'VALID',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tsv' },
-          optionType: {
-            value: mockCommands.option2,
-            arg: ' option2',
-            status: 'VALID',
-            message: ''
-          },
-          optionValue: {
-            value: 6,
-            arg: ' 6',
-            status: 'VALID',
-            message: ''
-          }
-        }
-      }
-    }
-  ]);
-};
-
-exports.testInvalid = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    'zxjq',
-      check: {
-        input:  'zxjq',
-        hints:      '',
-        markup: 'EEEE',
-        cursor: 4,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        tooltipState: 'true:isError'
-      }
-    },
-    {
-      setup:    'zxjq ',
-      check: {
-        input:  'zxjq ',
-        hints:       '',
-        markup: 'EEEEV',
-        cursor: 5,
-        current: '__command',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ],
-        tooltipState: 'true:isError'
-      }
-    },
-    {
-      setup:    'zxjq one',
-      check: {
-        input:  'zxjq one',
-        hints:          '',
-        markup: 'EEEEVEEE',
-        cursor: 8,
-        current: '__unassigned',
-        status: 'ERROR',
-        predictions: [ ],
-        unassigned: [ ' one' ],
-        tooltipState: 'true:isError'
-      }
-    }
-  ]);
-};
-
 exports.testSingleString = function(options) {
   return helpers.audit(options, [
     {
       setup:    'tsr',
       check: {
         input:  'tsr',
         hints:     ' <text>',
         markup: 'VVV',
@@ -536,17 +67,17 @@ exports.testSingleString = function(opti
         status: 'ERROR',
         unassigned: [ ],
         args: {
           command: { name: 'tsr' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'text\'.'
           }
         }
       }
     },
     {
       setup:    'tsr ',
       check: {
         input:  'tsr ',
@@ -558,17 +89,17 @@ exports.testSingleString = function(opti
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsr' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'text\'.'
           }
         }
       }
     },
     {
       setup:    'tsr h',
       check: {
         input:  'tsr h',
@@ -651,17 +182,17 @@ exports.testSingleNumber = function(opti
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsu' },
           num: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'num\'.'
           }
         }
       }
     },
     {
       setup:    'tsu ',
       check: {
         input:  'tsu ',
@@ -673,17 +204,17 @@ exports.testSingleNumber = function(opti
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsu' },
           num: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'num\'.'
           }
         }
       }
     },
     {
       setup:    'tsu 1',
       check: {
         input:  'tsu 1',
@@ -762,17 +293,17 @@ exports.testSingleFloat = function(optio
         error: '',
         unassigned: [ ],
         args: {
           command: { name: 'tsf' },
           num: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'num\'.'
           }
         }
       }
     },
     {
       setup:    'tsf 1',
       check: {
         input:  'tsf 1',
@@ -840,16 +371,17 @@ exports.testSingleFloat = function(optio
         unassigned: [ ],
         args: {
           command: { name: 'tsf' },
           num: { value: 1.5, arg: ' 1.5x', status: 'VALID', message: '' }
         }
       }
     },
     {
+      skipRemainingIf: options.isNoDom,
       name: 'tsf x (cursor=4)',
       setup: function() {
         return helpers.setInput(options, 'tsf x', 4);
       },
       check: {
         input:  'tsf x',
         hints:       '',
         markup: 'VVVVE',
@@ -868,53 +400,25 @@ exports.testSingleFloat = function(optio
             message: 'Can\'t convert "x" to a number.'
           }
         }
       }
     }
   ]);
 };
 
-exports.testElementDom = function(options) {
-  return helpers.audit(options, [
-    {
-      skipIf: options.isJsdom,
-      setup:    'tse :root',
-      check: {
-        input:  'tse :root',
-        hints:           ' [options]',
-        markup: 'VVVVVVVVV',
-        cursor: 9,
-        current: 'node',
-        status: 'VALID',
-        predictions: [ ],
-        unassigned: [ ],
-        args: {
-          command: { name: 'tse' },
-          node: {
-            value: options.window.document.documentElement,
-            arg: ' :root',
-            status: 'VALID',
-            message: ''
-          },
-          nodes: { arg: '', status: 'VALID', message: '' },
-          nodes2: { arg: '', status: 'VALID', message: '' },
-        }
-      }
-    }
-  ]);
-};
-
 exports.testElementWeb = function(options) {
-  var inputElement = options.window.document.getElementById('gcli-input');
+  var inputElement = options.isNoDom ?
+      null :
+      options.window.document.getElementById('gcli-input');
 
   return helpers.audit(options, [
     {
       skipIf: function gcliInputElementExists() {
-        return inputElement == null || options.isJsdom;
+        return inputElement == null;
       },
       setup:    'tse #gcli-input',
       check: {
         input:  'tse #gcli-input',
         hints:                 ' [options]',
         markup: 'VVVVVVVVVVVVVVV',
         cursor: 15,
         current: 'node',
@@ -935,36 +439,36 @@ exports.testElementWeb = function(option
       }
     }
   ]);
 };
 
 exports.testElement = function(options) {
   return helpers.audit(options, [
     {
+      skipRemainingIf: options.isNoDom,
       setup:    'tse',
       check: {
         input:  'tse',
         hints:     ' <node> [options]',
         markup: 'VVV',
         cursor: 3,
         current: '__command',
         status: 'ERROR',
         predictions: [ 'tse', 'tselarr' ],
         unassigned: [ ],
         args: {
           command: { name: 'tse' },
-          node: { value: undefined, arg: '', status: 'INCOMPLETE', message: '' },
+          node: { value: undefined, arg: '', status: 'INCOMPLETE' },
           nodes: { arg: '', status: 'VALID', message: '' },
           nodes2: { arg: '', status: 'VALID', message: '' },
         }
       }
     },
     {
-      skipIf: options.isJsdom,
       setup:    'tse #gcli-nomatch',
       check: {
         input:  'tse #gcli-nomatch',
         hints:                   ' [options]',
         markup: 'VVVVIIIIIIIIIIIII',
         cursor: 17,
         current: 'node',
         status: 'ERROR',
@@ -1035,17 +539,16 @@ exports.testElement = function(options) 
             message: 'Syntax error in CSS query'
           },
           nodes: { arg: '', status: 'VALID', message: '' },
           nodes2: { arg: '', status: 'VALID', message: '' },
         }
       }
     },
     {
-      skipIf: options.isJsdom,
       setup:    'tse *',
       check: {
         input:  'tse *',
         hints:       ' [options]',
         markup: 'VVVVE',
         cursor: 5,
         current: 'node',
         status: 'ERROR',
@@ -1127,17 +630,17 @@ exports.testNestedCommand = function(opt
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn dif' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'text\'.'
           }
         }
       }
     },
     {
       setup:    'tsn dif ',
       check: {
         input:  'tsn dif ',
@@ -1149,17 +652,17 @@ exports.testNestedCommand = function(opt
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn dif' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'text\'.'
           }
         }
       }
     },
     {
       setup:    'tsn dif x',
       check: {
         input:  'tsn dif x',
@@ -1188,17 +691,17 @@ exports.testNestedCommand = function(opt
         predictions: [ 'tsn ext', 'tsn exte', 'tsn exten', 'tsn extend' ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn ext' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'text\'.'
           }
         }
       }
     },
     {
       setup:    'tsn exte',
       check: {
         input:  'tsn exte',
@@ -1210,17 +713,17 @@ exports.testNestedCommand = function(opt
         predictions: [ 'tsn exte', 'tsn exten', 'tsn extend' ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn exte' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'text\'.'
           }
         }
       }
     },
     {
       setup:    'tsn exten',
       check: {
         input:  'tsn exten',
@@ -1232,17 +735,17 @@ exports.testNestedCommand = function(opt
         predictions: [ 'tsn exten', 'tsn extend' ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn exten' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'text\'.'
           }
         }
       }
     },
     {
       setup:    'tsn extend',
       check: {
         input:  'tsn extend',
@@ -1254,17 +757,17 @@ exports.testNestedCommand = function(opt
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn extend' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: ''
+            message: 'Value required for \'text\'.'
           }
         }
       }
     },
     {
       setup:    'ts ',
       check: {
         input:  'ts ',
@@ -1315,11 +818,8 @@ exports.testDeeplyNested = function(opti
         unassigned: [ ],
         args: {
           command: { name: 'tsn deep down nested cmd' },
         }
       }
     }
   ]);
 };
-
-
-// });
rename from browser/devtools/commandline/test/browser_gcli_completion.js
rename to browser/devtools/commandline/test/browser_gcli_completion1.js
--- a/browser/devtools/commandline/test/browser_gcli_completion.js
+++ b/browser/devtools/commandline/test/browser_gcli_completion1.js
@@ -9,47 +9,43 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCompletion.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCompletion1.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
-
-exports.setup = function(options) {
-  mockCommands.setup();
-};
-
-exports.shutdown = function(options) {
-  mockCommands.shutdown();
-};
+// var helpers = require('./helpers');
 
 exports.testActivate = function(options) {
   return helpers.audit(options, [
     {
       setup: '',
       check: {
         hints: ''
       }
@@ -263,275 +259,34 @@ exports.testActivate = function(options)
       setup: 'tselar 1',
       check: {
         hints: ''
       }
     },
     {
       name: 'tselar |1',
       setup: function() {
-        helpers.setInput(options, 'tselar 1', 7);
+        return helpers.setInput(options, 'tselar 1', 7);
       },
       check: {
         hints: ''
       }
     },
     {
       name: 'tselar| 1',
       setup: function() {
-        helpers.setInput(options, 'tselar 1', 6);
+        return helpers.setInput(options, 'tselar 1', 6);
       },
       check: {
         hints: ' -> tselarr'
       }
     },
     {
       name: 'tsela|r 1',
       setup: function() {
-        helpers.setInput(options, 'tselar 1', 5);
+        return helpers.setInput(options, 'tselar 1', 5);
       },
       check: {
         hints: ' -> tselarr'
       }
     },
   ]);
 };
-
-exports.testLong = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    'tslong --sel',
-      check: {
-        input:  'tslong --sel',
-        hints:              ' <selection> <msg> [options]',
-        markup: 'VVVVVVVIIIII'
-      }
-    },
-    {
-      setup:    'tslong --sel<TAB>',
-      check: {
-        input:  'tslong --sel ',
-        hints:               'space <msg> [options]',
-        markup: 'VVVVVVVIIIIIV'
-      }
-    },
-    {
-      setup:    'tslong --sel ',
-      check: {
-        input:  'tslong --sel ',
-        hints:               'space <msg> [options]',
-        markup: 'VVVVVVVIIIIIV'
-      }
-    },
-    {
-      setup:    'tslong --sel s',
-      check: {
-        input:  'tslong --sel s',
-        hints:                'pace <msg> [options]',
-        markup: 'VVVVVVVIIIIIVI'
-      }
-    },
-    {
-      setup:    'tslong --num ',
-      check: {
-        input:  'tslong --num ',
-        hints:               '<number> <msg> [options]',
-        markup: 'VVVVVVVIIIIIV'
-      }
-    },
-    {
-      setup:    'tslong --num 42',
-      check: {
-        input:  'tslong --num 42',
-        hints:                 ' <msg> [options]',
-        markup: 'VVVVVVVVVVVVVVV'
-      }
-    },
-    {
-      setup:    'tslong --num 42 ',
-      check: {
-        input:  'tslong --num 42 ',
-        hints:                  '<msg> [options]',
-        markup: 'VVVVVVVVVVVVVVVV'
-      }
-    },
-    {
-      setup:    'tslong --num 42 --se',
-      check: {
-        input:  'tslong --num 42 --se',
-        hints:                      'l <msg> [options]',
-        markup: 'VVVVVVVVVVVVVVVVIIII'
-      }
-    },
-    {
-      skipIf: options.isJsdom,
-      setup:    'tslong --num 42 --se<TAB>',
-      check: {
-        input:  'tslong --num 42 --sel ',
-        hints:                        'space <msg> [options]',
-        markup: 'VVVVVVVVVVVVVVVVIIIIIV'
-      }
-    },
-    {
-      skipIf: options.isJsdom,
-      setup:    'tslong --num 42 --se<TAB><TAB>',
-      check: {
-        input:  'tslong --num 42 --sel space ',
-        hints:                              '<msg> [options]',
-        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVV'
-      }
-    },
-    {
-      setup:    'tslong --num 42 --sel ',
-      check: {
-        input:  'tslong --num 42 --sel ',
-        hints:                        'space <msg> [options]',
-        markup: 'VVVVVVVVVVVVVVVVIIIIIV'
-      }
-    },
-    {
-      setup:    'tslong --num 42 --sel space ',
-      check: {
-        input:  'tslong --num 42 --sel space ',
-        hints:                              '<msg> [options]',
-        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVV'
-      }
-    }
-  ]);
-};
-
-exports.testNoTab = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    'tss<TAB>',
-      check: {
-        input:  'tss ',
-        markup: 'VVVV',
-        hints: ''
-      }
-    },
-    {
-      setup:    'tss<TAB><TAB>',
-      check: {
-        input:  'tss ',
-        markup: 'VVVV',
-        hints: ''
-      }
-    },
-    {
-      setup:    'xxxx',
-      check: {
-        input:  'xxxx',
-        markup: 'EEEE',
-        hints: ''
-      }
-    },
-    {
-      name: '<TAB>',
-      setup: function() {
-        // Doing it this way avoids clearing the input buffer
-        return helpers.pressTab(options);
-      },
-      check: {
-        input:  'xxxx',
-        markup: 'EEEE',
-        hints: ''
-      }
-    }
-  ]);
-};
-
-exports.testOutstanding = function(options) {
-  // See bug 779800
-  /*
-  return helpers.audit(options, [
-    {
-      setup:    'tsg --txt1 ddd ',
-      check: {
-        input:  'tsg --txt1 ddd ',
-        hints:                 'aaa [options]',
-        markup: 'VVVVVVVVVVVVVVV'
-      }
-    },
-  ]);
-  */
-};
-
-exports.testCompleteIntoOptional = function(options) {
-  // From bug 779816
-  return helpers.audit(options, [
-    {
-      setup:    'tso ',
-      check: {
-        typed:  'tso ',
-        hints:      '[text]',
-        markup: 'VVVV',
-        status: 'VALID'
-      }
-    },
-    {
-      setup:    'tso<TAB>',
-      check: {
-        typed:  'tso ',
-        hints:      '[text]',
-        markup: 'VVVV',
-        status: 'VALID'
-      }
-    }
-  ]);
-};
-
-exports.testSpaceComplete = function(options) {
-  return helpers.audit(options, [
-    {
-      setup:    'tslong --sel2 wit',
-      check: {
-        input:  'tslong --sel2 wit',
-        hints:                   'h space <msg> [options]',
-        markup: 'VVVVVVVIIIIIIVIII',
-        cursor: 17,
-        current: 'sel2',
-        status: 'ERROR',
-        tooltipState: 'true:importantFieldFlag',
-        args: {
-          command: { name: 'tslong' },
-          msg: { status: 'INCOMPLETE', message: '' },
-          num: { status: 'VALID' },
-          sel: { status: 'VALID' },
-          bool: { value: false, status: 'VALID' },
-          num2: { status: 'VALID' },
-          bool2: { value: false, status: 'VALID' },
-          sel2: { arg: ' --sel2 wit', status: 'INCOMPLETE' }
-        }
-      }
-    },
-    {
-      skipIf: options.isJsdom,
-      setup:    'tslong --sel2 wit<TAB>',
-      check: {
-        input:  'tslong --sel2 \'with space\' ',
-        hints:                             '<msg> [options]',
-        markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVV',
-        cursor: 27,
-        current: 'sel2',
-        status: 'ERROR',
-        tooltipState: 'true:importantFieldFlag',
-        args: {
-          command: { name: 'tslong' },
-          msg: { status: 'INCOMPLETE', message: '' },
-          num: { status: 'VALID' },
-          sel: { status: 'VALID' },
-          bool: { value: false, status: 'VALID' },
-          num2: { status: 'VALID' },
-          bool2: { value: false, status: 'VALID' },
-          sel2: {
-            value: 'with space',
-            arg: ' --sel2 \'with space\' ',
-            status: 'VALID'
-          }
-        }
-      }
-    }
-  ]);
-};
-
-
-// });
copy from browser/devtools/commandline/test/browser_gcli_completion.js
copy to browser/devtools/commandline/test/browser_gcli_completion2.js
--- a/browser/devtools/commandline/test/browser_gcli_completion.js
+++ b/browser/devtools/commandline/test/browser_gcli_completion2.js
@@ -9,296 +9,43 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCompletion.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCompletion2.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
-
-exports.setup = function(options) {
-  mockCommands.setup();
-};
-
-exports.shutdown = function(options) {
-  mockCommands.shutdown();
-};
-
-exports.testActivate = function(options) {
-  return helpers.audit(options, [
-    {
-      setup: '',
-      check: {
-        hints: ''
-      }
-    },
-    {
-      setup: ' ',
-      check: {
-        hints: ''
-      }
-    },
-    {
-      setup: 'tsr',
-      check: {
-        hints: ' <text>'
-      }
-    },
-    {
-      setup: 'tsr ',
-      check: {
-        hints: '<text>'
-      }
-    },
-    {
-      setup: 'tsr b',
-      check: {
-        hints: ''
-      }
-    },
-    {
-      setup: 'tsb',
-      check: {
-        hints: ' [toggle]'
-      }
-    },
-    {
-      setup: 'tsm',
-      check: {
-        hints: ' <abc> <txt> <num>'
-      }
-    },
-    {
-      setup: 'tsm ',
-      check: {
-        hints: 'a <txt> <num>'
-      }
-    },
-    {
-      setup: 'tsm a',
-      check: {
-        hints: ' <txt> <num>'
-      }
-    },
-    {
-      setup: 'tsm a ',
-      check: {
-        hints: '<txt> <num>'
-      }
-    },
-    {
-      setup: 'tsm a  ',
-      check: {
-        hints: '<txt> <num>'
-      }
-    },
-    {
-      setup: 'tsm a  d',
-      check: {
-        hints: ' <num>'
-      }
-    },
-    {
-      setup: 'tsm a "d d"',
-      check: {
-        hints: ' <num>'
-      }
-    },
-    {
-      setup: 'tsm a "d ',
-      check: {
-        hints: ' <num>'
-      }
-    },
-    {
-      setup: 'tsm a "d d" ',
-      check: {
-        hints: '<num>'
-      }
-    },
-    {
-      setup: 'tsm a "d d ',
-      check: {
-        hints: ' <num>'
-      }
-    },
-    {
-      setup: 'tsm d r',
-      check: {
-        hints: ' <num>'
-      }
-    },
-    {
-      setup: 'tsm a d ',
-      check: {
-        hints: '<num>'
-      }
-    },
-    {
-      setup: 'tsm a d 4',
-      check: {
-        hints: ''
-      }
-    },
-    {
-      setup: 'tsg',
-      check: {
-        hints: ' <solo> [options]'
-      }
-    },
-    {
-      setup: 'tsg ',
-      check: {
-        hints: 'aaa [options]'
-      }
-    },
-    {
-      setup: 'tsg a',
-      check: {
-        hints: 'aa [options]'
-      }
-    },
-    {
-      setup: 'tsg b',
-      check: {
-        hints: 'bb [options]'
-      }
-    },
-    {
-      skipIf: options.isPhantomjs,
-      setup: 'tsg d',
-      check: {
-        hints: ' [options] -> ccc'
-      }
-    },
-    {
-      setup: 'tsg aa',
-      check: {
-        hints: 'a [options]'
-      }
-    },
-    {
-      setup: 'tsg aaa',
-      check: {
-        hints: ' [options]'
-      }
-    },
-    {
-      setup: 'tsg aaa ',
-      check: {
-        hints: '[options]'
-      }
-    },
-    {
-      setup: 'tsg aaa d',
-      check: {
-        hints: ' [options]'
-      }
-    },
-    {
-      setup: 'tsg aaa dddddd',
-      check: {
-        hints: ' [options]'
-      }
-    },
-    {
-      setup: 'tsg aaa dddddd ',
-      check: {
-        hints: '[options]'
-      }
-    },
-    {
-      setup: 'tsg aaa "d',
-      check: {
-        hints: ' [options]'
-      }
-    },
-    {
-      setup: 'tsg aaa "d d',
-      check: {
-        hints: ' [options]'
-      }
-    },
-    {
-      setup: 'tsg aaa "d d"',
-      check: {
-        hints: ' [options]'
-      }
-    },
-    {
-      setup: 'tsn ex ',
-      check: {
-        hints: ''
-      }
-    },
-    {
-      setup: 'selarr',
-      check: {
-        hints: ' -> tselarr'
-      }
-    },
-    {
-      setup: 'tselar 1',
-      check: {
-        hints: ''
-      }
-    },
-    {
-      name: 'tselar |1',
-      setup: function() {
-        helpers.setInput(options, 'tselar 1', 7);
-      },
-      check: {
-        hints: ''
-      }
-    },
-    {
-      name: 'tselar| 1',
-      setup: function() {
-        helpers.setInput(options, 'tselar 1', 6);
-      },
-      check: {
-        hints: ' -> tselarr'
-      }
-    },
-    {
-      name: 'tsela|r 1',
-      setup: function() {
-        helpers.setInput(options, 'tselar 1', 5);
-      },
-      check: {
-        hints: ' -> tselarr'
-      }
-    },
-  ]);
-};
+// var helpers = require('./helpers');
 
 exports.testLong = function(options) {
   return helpers.audit(options, [
     {
       setup:    'tslong --sel',
       check: {
         input:  'tslong --sel',
         hints:              ' <selection> <msg> [options]',
@@ -357,26 +104,24 @@ exports.testLong = function(options) {
       setup:    'tslong --num 42 --se',
       check: {
         input:  'tslong --num 42 --se',
         hints:                      'l <msg> [options]',
         markup: 'VVVVVVVVVVVVVVVVIIII'
       }
     },
     {
-      skipIf: options.isJsdom,
       setup:    'tslong --num 42 --se<TAB>',
       check: {
         input:  'tslong --num 42 --sel ',
         hints:                        'space <msg> [options]',
         markup: 'VVVVVVVVVVVVVVVVIIIIIV'
       }
     },
     {
-      skipIf: options.isJsdom,
       setup:    'tslong --num 42 --se<TAB><TAB>',
       check: {
         input:  'tslong --num 42 --sel space ',
         hints:                              '<msg> [options]',
         markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVV'
       }
     },
     {
@@ -420,16 +165,17 @@ exports.testNoTab = function(options) {
       setup:    'xxxx',
       check: {
         input:  'xxxx',
         markup: 'EEEE',
         hints: ''
       }
     },
     {
+      skipIf: options.isNoDom,
       name: '<TAB>',
       setup: function() {
         // Doing it this way avoids clearing the input buffer
         return helpers.pressTab(options);
       },
       check: {
         input:  'xxxx',
         markup: 'EEEE',
@@ -488,50 +234,46 @@ exports.testSpaceComplete = function(opt
         hints:                   'h space <msg> [options]',
         markup: 'VVVVVVVIIIIIIVIII',
         cursor: 17,
         current: 'sel2',
         status: 'ERROR',
         tooltipState: 'true:importantFieldFlag',
         args: {
           command: { name: 'tslong' },
-          msg: { status: 'INCOMPLETE', message: '' },
+          msg: { status: 'INCOMPLETE' },
           num: { status: 'VALID' },
           sel: { status: 'VALID' },
           bool: { value: false, status: 'VALID' },
           num2: { status: 'VALID' },
           bool2: { value: false, status: 'VALID' },
           sel2: { arg: ' --sel2 wit', status: 'INCOMPLETE' }
         }
       }
     },
     {
-      skipIf: options.isJsdom,
       setup:    'tslong --sel2 wit<TAB>',
       check: {
         input:  'tslong --sel2 \'with space\' ',
         hints:                             '<msg> [options]',
         markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVV',
         cursor: 27,
         current: 'sel2',
         status: 'ERROR',
         tooltipState: 'true:importantFieldFlag',
         args: {
           command: { name: 'tslong' },
-          msg: { status: 'INCOMPLETE', message: '' },
+          msg: { status: 'INCOMPLETE' },
           num: { status: 'VALID' },
           sel: { status: 'VALID' },
           bool: { value: false, status: 'VALID' },
           num2: { status: 'VALID' },
           bool2: { value: false, status: 'VALID' },
           sel2: {
             value: 'with space',
             arg: ' --sel2 \'with space\' ',
             status: 'VALID'
           }
         }
       }
     }
   ]);
 };
-
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_context.js
+++ b/browser/devtools/commandline/test/browser_gcli_context.js
@@ -9,47 +9,43 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testContext.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testContext.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
-
-exports.setup = function(options) {
-  mockCommands.setup();
-};
-
-exports.shutdown = function(options) {
-  mockCommands.shutdown();
-};
+// var helpers = require('./helpers');
 
 exports.testBaseline = function(options) {
   return helpers.audit(options, [
     // These 3 establish a baseline for comparison when we have used the
     // context command
     {
       setup:    'ext',
       check: {
@@ -99,65 +95,62 @@ exports.testContext = function(options) 
         input:  'context tsn',
         hints:             ' deep down nested cmd',
         markup: 'VVVVVVVVVVV',
         message: '',
         predictionsContains: [ 'tsn deep down nested cmd', 'tsn ext', 'tsn exte' ],
         args: {
           command: { name: 'context' },
           prefix: {
-            value: mockCommands.commands.tsn,
+            value: options.requisition.canon.getCommand('tsn'),
             status: 'VALID',
             message: ''
-          },
+          }
         }
       },
       exec: {
-        output: 'Using tsn as a command prefix',
-        completed: true,
+        output: 'Using tsn as a command prefix'
       }
     },
     // For comparison with earlier
     {
       setup:    'ext',
       check: {
         input:  'ext',
         hints:     ' <text>',
         markup: 'VVV',
         predictions: [ 'tsn ext', 'tsn exte', 'tsn exten', 'tsn extend' ],
         args: {
           command: { name: 'tsn ext' },
           text: {
             value: undefined,
             arg: '',
-            status: 'INCOMPLETE',
-            message: ''
-          },
+            status: 'INCOMPLETE'
+          }
         }
       }
     },
     {
       setup:    'ext test',
       check: {
         input:  'ext test',
         hints:          '',
         markup: 'VVVVVVVV',
         args: {
           command: { name: 'tsn ext' },
           text: {
             value: 'test',
             arg: ' test',
             status: 'VALID',
             message: ''
-          },
+          }
         }
       },
       exec: {
-        output: 'Exec: tsnExt text=test',
-        completed: true,
+        output: 'Exec: tsnExt text=test'
       }
     },
     {
       setup:    'tsn',
       check: {
         input:  'tsn',
         hints:     ' deep down nested cmd',
         markup: 'III',
@@ -176,17 +169,17 @@ exports.testContext = function(options) 
         hints:          '',
         markup: 'VVVVVVVV',
         options: [ 'true' ],
         message: '',
         predictions: [ 'true' ],
         unassigned: [ ],
         args: {
           command: { name: 'tsb' },
-          toggle: { value: true, arg: ' true', status: 'VALID', message: '' },
+          toggle: { value: true, arg: ' true', status: 'VALID', message: '' }
         }
       }
     },
     {
       // Bug 866710 - GCLI should allow argument merging for non-string parameters
       setup: 'context tsn ext',
       skip: true
     },
@@ -197,25 +190,24 @@ exports.testContext = function(options) 
         hints:                   '',
         markup: 'VVVVVVVVVVVVVVVVV',
         message: '',
         predictions: [ 'tsn ext', 'tsn exte', 'tsn exten', 'tsn extend' ],
         unassigned: [ ],
         args: {
           command: { name: 'context' },
           prefix: {
-            value: mockCommands.commands.tsnExt,
+            value: options.requisition.canon.getCommand('tsn ext'),
             status: 'VALID',
             message: ''
           }
         }
       },
       exec: {
-        output: 'Error: Can\'t use \'tsn ext\' as a prefix because it is not a parent command.',
-        completed: true,
+        output: 'Can\'t use \'tsn ext\' as a prefix because it is not a parent command.',
         error: true
       }
     },
     /*
     {
       setup:    'context "tsn deep"',
       check: {
         input:  'context "tsn deep"',
@@ -223,25 +215,24 @@ exports.testContext = function(options) 
         markup: 'VVVVVVVVVVVVVVVVVV',
         status: 'ERROR',
         message: '',
         predictions: [ 'tsn deep' ],
         unassigned: [ ],
         args: {
           command: { name: 'context' },
           prefix: {
-            value: mockCommands.commands.tsnDeep,
+            value: options.requisition.canon.getCommand('tsn deep'),
             status: 'VALID',
             message: ''
           }
         }
       },
       exec: {
-        output: '',
-        completed: true,
+        output: ''
       }
     },
     */
     {
       setup:    'context',
       check: {
         input:  'context',
         hints:         ' [prefix]',
@@ -250,18 +241,14 @@ exports.testContext = function(options) 
         unassigned: [ ],
         args: {
           command: { name: 'context' },
           prefix: { value: undefined, arg: '', status: 'VALID', message: '' },
         }
       },
       exec: {
         output: 'Command prefix is unset',
-        completed: true,
         type: 'string',
         error: false
       }
     }
   ]);
 };
-
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_date.js
+++ b/browser/devtools/commandline/test/browser_gcli_date.js
@@ -9,81 +9,75 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testDate.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testDate.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var assert = require('test/assert');
-
-var types = require('gcli/types');
-var Argument = require('gcli/argument').Argument;
-var Status = require('gcli/types').Status;
+// var assert = require('../testharness/assert');
+// var helpers = require('./helpers');
 
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
-
-exports.setup = function(options) {
-  mockCommands.setup();
-};
-
-exports.shutdown = function(options) {
-  mockCommands.shutdown();
-};
+var Status = require('gcli/types/types').Status;
 
 exports.testParse = function(options) {
-  var date = types.createType('date');
-  return date.parse(new Argument('now')).then(function(conversion) {
+  var date = options.requisition.types.createType('date');
+  return date.parseString('now').then(function(conversion) {
     // Date comparison - these 2 dates may not be the same, but how close is
     // close enough? If this test takes more than 30secs to run the it will
     // probably time out, so we'll assume that these 2 values must be within
     // 1 min of each other
     var gap = new Date().getTime() - conversion.value.getTime();
     assert.ok(gap < 60000, 'now is less than a minute away');
 
     assert.is(conversion.getStatus(), Status.VALID, 'now parse');
   });
 };
 
 exports.testMaxMin = function(options) {
   var max = new Date();
   var min = new Date();
+  var types = options.requisition.types;
   var date = types.createType({ name: 'date', max: max, min: min });
   assert.is(date.getMax(), max, 'max setup');
 
   var incremented = date.increment(min);
   assert.is(incremented, max, 'incremented');
 };
 
 exports.testIncrement = function(options) {
-  var date = types.createType('date');
-  return date.parse(new Argument('now')).then(function(conversion) {
+  var date = options.requisition.types.createType('date');
+  return date.parseString('now').then(function(conversion) {
     var plusOne = date.increment(conversion.value);
     var minusOne = date.decrement(plusOne);
 
     // See comments in testParse
     var gap = new Date().getTime() - minusOne.getTime();
     assert.ok(gap < 60000, 'now is less than a minute away');
   });
 };
@@ -127,17 +121,16 @@ exports.testInput = function(options) {
             arg: ' 1980-01-03',
             status: 'VALID',
             message: ''
           },
         }
       },
       exec: {
         output: [ /^Exec: tsdate/, /2001/, /1980/ ],
-        completed: true,
         type: 'string',
         error: false
       }
     },
     {
       setup:    'tsdate 2001/01/01 1980/01/03',
       check: {
         input:  'tsdate 2001/01/01 1980/01/03',
@@ -174,17 +167,16 @@ exports.testInput = function(options) {
             arg: ' 1980/01/03',
             status: 'VALID',
             message: ''
           },
         }
       },
       exec: {
         output: [ /^Exec: tsdate/, /2001/, /1980/ ],
-        completed: true,
         type: 'string',
         error: false
       }
     },
     {
       setup:    'tsdate now today',
       check: {
         input:  'tsdate now today',
@@ -216,17 +208,16 @@ exports.testInput = function(options) {
             arg: ' today',
             status: 'VALID',
             message: ''
           },
         }
       },
       exec: {
         output: [ /^Exec: tsdate/, new Date().getFullYear() ],
-        completed: true,
         type: 'string',
         error: false
       }
     },
     {
       setup:    'tsdate yesterday tomorrow',
       check: {
         input:  'tsdate yesterday tomorrow',
@@ -257,27 +248,28 @@ exports.testInput = function(options) {
             arg: ' tomorrow',
             status: 'VALID',
             message: ''
           },
         }
       },
       exec: {
         output: [ /^Exec: tsdate/, new Date().getFullYear() ],
-        completed: true,
         type: 'string',
         error: false
       }
     }
   ]);
 };
 
 exports.testIncrDecr = function(options) {
   return helpers.audit(options, [
     {
+      // createRequisitionAutomator doesn't fake UP/DOWN well enough
+      skipRemainingIf: options.isNoDom,
       setup:    'tsdate 2001-01-01<UP>',
       check: {
         input:  'tsdate 2001-01-02',
         hints:                    ' <d2>',
         markup: 'VVVVVVVVVVVVVVVVV',
         status: 'ERROR',
         message: '',
         args: {
@@ -293,18 +285,17 @@ exports.testIncrDecr = function(options)
               assert.is(d1.getMilliseconds(), 0, 'd1 millis');
             },
             arg: ' 2001-01-02',
             status: 'VALID',
             message: ''
           },
           d2: {
             value: undefined,
-            status: 'INCOMPLETE',
-            message: ''
+            status: 'INCOMPLETE'
           },
         }
       }
     },
     {
       // Check wrapping on decrement
       setup:    'tsdate 2001-02-01<DOWN>',
       check: {
@@ -326,18 +317,17 @@ exports.testIncrDecr = function(options)
               assert.is(d1.getMilliseconds(), 0, 'd1 millis');
             },
             arg: ' 2001-01-31',
             status: 'VALID',
             message: ''
           },
           d2: {
             value: undefined,
-            status: 'INCOMPLETE',
-            message: ''
+            status: 'INCOMPLETE'
           },
         }
       }
     },
     {
       // Check 'max' value capping on increment
       setup:    'tsdate 2001-02-01 "27 feb 2000"<UP>',
       check: {
@@ -376,11 +366,8 @@ exports.testIncrDecr = function(options)
             status: 'VALID',
             message: ''
           },
         }
       }
     }
   ]);
 };
-
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_exec.js
+++ b/browser/devtools/commandline/test/browser_gcli_exec.js
@@ -9,170 +9,176 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testExec.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testExec.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
+// var assert = require('../testharness/assert');
+// var helpers = require('./helpers');
 var nodetype = require('gcli/types/node');
-var canon = require('gcli/canon');
-// var assert = require('test/assert');
-// var mockCommands = require('gclitest/mockCommands');
-// var helpers = require('gclitest/helpers');
-
-
-exports.setup = function(options) {
-  mockCommands.setup();
-};
-
-exports.shutdown = function(options) {
-  mockCommands.shutdown();
-};
 
 var mockBody = {
   style: {}
 };
 
+var mockEmptyNodeList = {
+  length: 0,
+  item: function() { return null; }
+};
+
+var mockRootNodeList = {
+  length: 1,
+  item: function(i) { return mockBody; }
+};
+
 var mockDoc = {
   querySelectorAll: function(css) {
-    if (css === ':root') {
-      return {
-        length: 1,
-        item: function(i) {
-          return mockBody;
-        }
-      };
-    }
-    else {
-      return {
-        length: 0,
-        item: function() { return null; }
-      };
-    }
+    return (css === ':root') ? mockRootNodeList : mockEmptyNodeList;
   }
 };
 
 exports.testParamGroup = function(options) {
-  var tsg = canon.getCommand('tsg');
+  var tsg = options.requisition.canon.getCommand('tsg');
 
   assert.is(tsg.params[0].groupName, null, 'tsg param 0 group null');
   assert.is(tsg.params[1].groupName, 'First', 'tsg param 1 group First');
   assert.is(tsg.params[2].groupName, 'First', 'tsg param 2 group First');
   assert.is(tsg.params[3].groupName, 'Second', 'tsg param 3 group Second');
   assert.is(tsg.params[4].groupName, 'Second', 'tsg param 4 group Second');
 };
 
 exports.testWithHelpers = function(options) {
   return helpers.audit(options, [
     {
-      skipIf: options.isJsdom,
       setup:    'tss',
       check: {
         input:  'tss',
         hints:     '',
         markup: 'VVV',
         cursor: 3,
         current: '__command',
         status: 'VALID',
-        predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tss' },
         }
       },
       exec: {
-        output: 'Exec: tss',
-        completed: true,
+        output: /^Exec: tss/,
       }
     },
     {
       setup:    'tsv option1 10',
       check: {
         input:  'tsv option1 10',
         hints:                '',
         markup: 'VVVVVVVVVVVVVV',
         cursor: 14,
         current: 'optionValue',
         status: 'VALID',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsv' },
           optionType: {
-            value: mockCommands.option1,
+            value: 'string',
             arg: ' option1',
             status: 'VALID',
             message: ''
           },
           optionValue: {
-            value: '10',
             arg: ' 10',
             status: 'VALID',
             message: ''
           }
         }
       },
       exec: {
-        output: 'Exec: tsv optionType=[object Object], optionValue=10',
-        completed: true
+        output: 'Exec: tsv optionType=string, optionValue=10'
       }
     },
     {
       setup:    'tsv option2 10',
       check: {
         input:  'tsv option2 10',
         hints:                '',
         markup: 'VVVVVVVVVVVVVV',
         cursor: 14,
         current: 'optionValue',
         status: 'VALID',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsv' },
           optionType: {
-            value: mockCommands.option2,
+            value: 'number',
             arg: ' option2',
             status: 'VALID',
             message: ''
           },
           optionValue: {
-            value: 10,
             arg: ' 10',
             status: 'VALID',
             message: ''
           }
         }
       },
       exec: {
-        output: 'Exec: tsv optionType=[object Object], optionValue=10',
-        completed: true
+        output: 'Exec: tsv optionType=number, optionValue=10'
+      }
+    },
+    // Delegated remote types can't transfer value types so we only test for
+    // the value of optionValue when we're local
+    {
+      skipIf: options.isRemote,
+      setup: 'tsv option1 10',
+      check: {
+        args: { optionValue: { value: '10' } }
+      },
+      exec: {
+        output: 'Exec: tsv optionType=string, optionValue=10'
+      }
+    },
+    {
+      skipIf: options.isRemote,
+      setup: 'tsv option2 10',
+      check: {
+        args: { optionValue: { value: 10 } }
+      },
+      exec: {
+        output: 'Exec: tsv optionType=number, optionValue=10'
       }
     }
   ]);
 };
 
 exports.testExecText = function(options) {
   return helpers.audit(options, [
     {
@@ -192,18 +198,17 @@ exports.testExecText = function(options)
             value: 'fred',
             arg: ' fred',
             status: 'VALID',
             message: ''
           }
         }
       },
       exec: {
-        output: 'Exec: tsr text=fred',
-        completed: true,
+        output: 'Exec: tsr text=fred'
       }
     },
     {
       setup:    'tsr fred bloggs',
       check: {
         input:  'tsr fred bloggs',
         hints:                 '',
         markup: 'VVVVVVVVVVVVVVV',
@@ -218,18 +223,17 @@ exports.testExecText = function(options)
             value: 'fred bloggs',
             arg: ' fred bloggs',
             status: 'VALID',
             message: ''
           }
         }
       },
       exec: {
-        output: 'Exec: tsr text=fred bloggs',
-        completed: true,
+        output: 'Exec: tsr text=fred bloggs'
       }
     },
     {
       setup:    'tsr "fred bloggs"',
       check: {
         input:  'tsr "fred bloggs"',
         hints:                   '',
         markup: 'VVVVVVVVVVVVVVVVV',
@@ -244,18 +248,17 @@ exports.testExecText = function(options)
             value: 'fred bloggs',
             arg: ' "fred bloggs"',
             status: 'VALID',
             message: ''
           }
         }
       },
       exec: {
-        output: 'Exec: tsr text=fred bloggs',
-        completed: true,
+        output: 'Exec: tsr text=fred bloggs'
       }
     },
     {
       setup:    'tsr "fred bloggs',
       check: {
         input:  'tsr "fred bloggs',
         hints:                  '',
         markup: 'VVVVVVVVVVVVVVVV',
@@ -270,18 +273,17 @@ exports.testExecText = function(options)
             value: 'fred bloggs',
             arg: ' "fred bloggs',
             status: 'VALID',
             message: ''
           }
         }
       },
       exec: {
-        output: 'Exec: tsr text=fred bloggs',
-        completed: true,
+        output: 'Exec: tsr text=fred bloggs'
       }
     }
   ]);
 };
 
 exports.testExecBoolean = function(options) {
   return helpers.audit(options, [
     {
@@ -301,18 +303,17 @@ exports.testExecBoolean = function(optio
             value: false,
             arg: '',
             status: 'VALID',
             message: ''
           }
         }
       },
       exec: {
-        output: 'Exec: tsb toggle=false',
-        completed: true,
+        output: 'Exec: tsb toggle=false'
       }
     },
     {
       setup:    'tsb --toggle',
       check: {
         input:  'tsb --toggle',
         hints:              '',
         markup: 'VVVVVVVVVVVV',
@@ -328,18 +329,17 @@ exports.testExecBoolean = function(optio
             value: true,
             arg: ' --toggle',
             status: 'VALID',
             message: ''
           }
         }
       },
       exec: {
-        output: 'Exec: tsb toggle=true',
-        completed: true,
+        output: 'Exec: tsb toggle=true'
       }
     }
   ]);
 };
 
 exports.testExecNumber = function(options) {
   return helpers.audit(options, [
     {
@@ -350,43 +350,41 @@ exports.testExecNumber = function(option
         markup: 'VVVVVV',
         cursor: 6,
         current: 'num',
         status: 'VALID',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsu' },
-          num: { value: 10, arg: ' 10', status: 'VALID', message: '' },
+          num: { value: 10, arg: ' 10', status: 'VALID', message: '' }
         }
       },
       exec: {
-        output: 'Exec: tsu num=10',
-        completed: true,
+        output: 'Exec: tsu num=10'
       }
     },
     {
       setup:    'tsu --num 10',
       check: {
         input:  'tsu --num 10',
         hints:              '',
         markup: 'VVVVVVVVVVVV',
         cursor: 12,
         current: 'num',
         status: 'VALID',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsu' },
-          num: { value: 10, arg: ' --num 10', status: 'VALID', message: '' },
+          num: { value: 10, arg: ' --num 10', status: 'VALID', message: '' }
         }
       },
       exec: {
-        output: 'Exec: tsu num=10',
-        completed: true,
+        output: 'Exec: tsu num=10'
       }
     }
   ]);
 };
 
 exports.testExecScript = function(options) {
   return helpers.audit(options, [
     {
@@ -408,49 +406,63 @@ exports.testExecScript = function(option
             value: '1 + 1',
             arg: ' { 1 + 1 }',
             status: 'VALID',
             message: ''
           }
         }
       },
       exec: {
-        output: 'Exec: tsj javascript=1 + 1',
-        completed: true,
+        output: 'Exec: tsj javascript=1 + 1'
       }
     }
   ]);
 };
 
 exports.testExecNode = function(options) {
   var origDoc = nodetype.getDocument();
   nodetype.setDocument(mockDoc);
 
   return helpers.audit(options, [
     {
+      skipIf: options.isRemote, // No DOM on server
       setup:    'tse :root',
       check: {
         input:  'tse :root',
         hints:           ' [options]',
         markup: 'VVVVVVVVV',
         cursor: 9,
         current: 'node',
         status: 'VALID',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tse' },
-          node: { value: mockBody, arg: ' :root', status: 'VALID', message: '' },
-          nodes: { arg: '', status: 'VALID', message: '' },
-          nodes2: { arg: '', status: 'VALID', message: '' },
+          node: {
+            value: mockBody,
+            arg: ' :root',
+            status: 'VALID',
+            message: ''
+          },
+          nodes: {
+            value: mockEmptyNodeList,
+            arg: '',
+            status: 'VALID',
+            message: ''
+          },
+          nodes2: {
+            value: mockEmptyNodeList,
+            arg: '',
+            status: 'VALID',
+            message: ''
+          }
         }
       },
       exec: {
-        output: 'Exec: tse node=[object Object], nodes=[object Object], nodes2=[object Object]',
-        completed: true,
+        output: /^Exec: tse/
       },
       post: function() {
         nodetype.setDocument(origDoc);
       }
     }
   ]);
 };
 
@@ -464,22 +476,21 @@ exports.testExecSubCommand = function(op
         markup: 'VVVVVVVVVVVV',
         cursor: 12,
         current: 'text',
         status: 'VALID',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn dif' },
-          text: { value: 'fred', arg: ' fred', status: 'VALID', message: '' },
+          text: { value: 'fred', arg: ' fred', status: 'VALID', message: '' }
         }
       },
       exec: {
-        output: 'Exec: tsnDif text=fred',
-        completed: true,
+        output: 'Exec: tsnDif text=fred'
       }
     },
     {
       setup:    'tsn exten fred',
       check: {
         input:  'tsn exten fred',
         hints:                '',
         markup: 'VVVVVVVVVVVVVV',
@@ -489,18 +500,17 @@ exports.testExecSubCommand = function(op
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn exten' },
           text: { value: 'fred', arg: ' fred', status: 'VALID', message: '' },
         }
       },
       exec: {
-        output: 'Exec: tsnExten text=fred',
-        completed: true,
+        output: 'Exec: tsnExten text=fred'
       }
     },
     {
       setup:    'tsn extend fred',
       check: {
         input:  'tsn extend fred',
         hints:                 '',
         markup: 'VVVVVVVVVVVVVVV',
@@ -510,18 +520,17 @@ exports.testExecSubCommand = function(op
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn extend' },
           text: { value: 'fred', arg: ' fred', status: 'VALID', message: '' },
         }
       },
       exec: {
-        output: 'Exec: tsnExtend text=fred',
-        completed: true,
+        output: 'Exec: tsnExtend text=fred'
       }
     }
   ]);
 };
 
 exports.testExecArray = function(options) {
   return helpers.audit(options, [
     {
@@ -538,18 +547,17 @@ exports.testExecArray = function(options
         outputState: 'false:default',
         args: {
           command: { name: 'tselarr' },
           num: { value: '1', arg: ' 1', status: 'VALID', message: '' },
           arr: { /*value:,*/ arg: '{}', status: 'VALID', message: '' },
         }
       },
       exec: {
-        output: 'Exec: tselarr num=1, arr=',
-        completed: true,
+        output: 'Exec: tselarr num=1, arr='
       }
     },
     {
       setup:    'tselarr 1 a',
       check: {
         input:  'tselarr 1 a',
         hints:             '',
         markup: 'VVVVVVVVVVV',
@@ -560,18 +568,17 @@ exports.testExecArray = function(options
         unassigned: [ ],
         args: {
           command: { name: 'tselarr' },
           num: { value: '1', arg: ' 1', status: 'VALID', message: '' },
           arr: { /*value:a,*/ arg: '{ a}', status: 'VALID', message: '' },
         }
       },
       exec: {
-        output: 'Exec: tselarr num=1, arr=a',
-        completed: true,
+        output: 'Exec: tselarr num=1, arr=a'
       }
     },
     {
       setup:    'tselarr 1 a b',
       check: {
         input:  'tselarr 1 a b',
         hints:               '',
         markup: 'VVVVVVVVVVVVV',
@@ -582,18 +589,17 @@ exports.testExecArray = function(options
         unassigned: [ ],
         args: {
           command: { name: 'tselarr' },
           num: { value: '1', arg: ' 1', status: 'VALID', message: '' },
           arr: { /*value:a,b,*/ arg: '{ a, b}', status: 'VALID', message: '' },
         }
       },
       exec: {
-        output: 'Exec: tselarr num=1, arr=a,b',
-        completed: true,
+        output: 'Exec: tselarr num=1, arr=a,b'
       }
     }
   ]);
 };
 
 exports.testExecMultiple = function(options) {
   return helpers.audit(options, [
     {
@@ -610,18 +616,17 @@ exports.testExecMultiple = function(opti
         args: {
           command: { name: 'tsm' },
           abc: { value: 'a', arg: ' a', status: 'VALID', message: '' },
           txt: { value: '10', arg: ' 10', status: 'VALID', message: '' },
           num: { value: 10, arg: ' 10', status: 'VALID', message: '' },
         }
       },
       exec: {
-        output: 'Exec: tsm abc=a, txt=10, num=10',
-        completed: true,
+        output: 'Exec: tsm abc=a, txt=10, num=10'
       }
     }
   ]);
 };
 
 exports.testExecDefaults = function(options) {
   return helpers.audit(options, [
     {
@@ -641,17 +646,14 @@ exports.testExecDefaults = function(opti
           solo: { value: 'aaa', arg: ' aaa', status: 'VALID', message: '' },
           txt1: { value: undefined, arg: '', status: 'VALID', message: '' },
           bool: { value: false, arg: '', status: 'VALID', message: '' },
           txt2: { value: undefined, arg: '', status: 'VALID', message: '' },
           num: { value: undefined, arg: '', status: 'VALID', message: '' },
         }
       },
       exec: {
-        output: 'Exec: tsg solo=aaa, txt1=null, bool=false, txt2=d, num=42',
-        completed: true,
+        output: 'Exec: tsg solo=aaa, txt1=null, bool=false, txt2=d, num=42'
       }
     }
   ]);
 
 };
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_fail.js
+++ b/browser/devtools/commandline/test/browser_gcli_fail.js
@@ -9,92 +9,80 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFail.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFail.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
-
-exports.setup = function(options) {
-  mockCommands.setup();
-};
-
-exports.shutdown = function(options) {
-  mockCommands.shutdown();
-};
+// var helpers = require('./helpers');
 
 exports.testBasic = function(options) {
   return helpers.audit(options, [
     {
       setup: 'tsfail reject',
       exec: {
-        completed: false,
         output: 'rejected promise',
         type: 'error',
         error: true
       }
     },
     {
       setup: 'tsfail rejecttyped',
       exec: {
-        completed: false,
         output: '54',
         type: 'number',
         error: true
       }
     },
     {
       setup: 'tsfail throwerror',
       exec: {
-        completed: true,
-        output: 'Error: thrown error',
+        output: 'thrown error',
         type: 'error',
         error: true
       }
     },
     {
       setup: 'tsfail throwstring',
       exec: {
-        completed: true,
         output: 'thrown string',
         type: 'error',
         error: true
       }
     },
     {
       setup: 'tsfail noerror',
       exec: {
-        completed: true,
         output: 'no error',
         type: 'string',
         error: false
       }
     }
   ]);
 };
-
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_file.js
+++ b/browser/devtools/commandline/test/browser_gcli_file.js
@@ -9,59 +9,53 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFile.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFile.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
-
-exports.setup = function(options) {
-  mockCommands.setup();
-};
-
-exports.shutdown = function(options) {
-  mockCommands.shutdown();
-};
+// var helpers = require('./helpers');
 
 var local = false;
 
 exports.testBasic = function(options) {
-  var isPhantomjsFromFilesystem = (!options.isHttp && options.isPhantomjs);
   return helpers.audit(options, [
     {
       // These tests require us to be using node directly or to be in
-      // phantomjs connected to an allowexec enabled node server or to be in
-      // firefox. In short they only don't work when in phantomjs reading
-      // from the filesystem, but they do work in Firefox
-      skipRemainingIf: isPhantomjsFromFilesystem || options.isFirefox,
+      // PhantomJS connected to an execute enabled node server or to be in
+      // firefox.
+      skipRemainingIf: options.isPhantomjs || options.isFirefox,
       setup:    'tsfile open /',
       check: {
         input:  'tsfile open /',
         hints:               '',
         markup: 'VVVVVVVVVVVVI',
         cursor: 13,
         current: 'p1',
         status: 'ERROR',
@@ -838,11 +832,8 @@ exports.testFirefoxBasic = function(opti
             status: 'VALID',
             message: ''
           }
         }
       }
     }
   ]);
 };
-
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_fileparser.js
+++ b/browser/devtools/commandline/test/browser_gcli_fileparser.js
@@ -9,39 +9,44 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFileparser.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFileparser.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var assert = require('test/assert');
-var fileparser = require('util/fileparser');
+// var assert = require('../testharness/assert');
+var fileparser = require('gcli/util/fileparser');
 
 var local = false;
 
 exports.testGetPredictor = function(options) {
   if (!options.isNode || !local) {
     assert.log('Skipping tests due to install differences.');
     return;
   }
@@ -49,10 +54,8 @@ exports.testGetPredictor = function(opti
   var opts = { filetype: 'file', existing: 'yes' };
   var predictor = fileparser.getPredictor('/usr/locl/bin/nmp', opts);
   return predictor().then(function(replies) {
     assert.is(replies[0].name,
               '/usr/local/bin/npm',
               'predict npm');
   });
 };
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_filesystem.js
+++ b/browser/devtools/commandline/test/browser_gcli_filesystem.js
@@ -9,40 +9,45 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFilesystem.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFilesystem.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var assert = require('test/assert');
-// var helpers = require('gclitest/helpers');
-var filesystem = require('util/filesystem');
+// var assert = require('../testharness/assert');
+// var helpers = require('./helpers');
+var filesystem = require('gcli/util/filesystem');
 
 exports.testSplit = function(options) {
   if (!options.isNode) {
     return;
   }
 
   helpers.arrayIs(filesystem.split('', '/'),
                   [ '.' ],
@@ -69,10 +74,8 @@ exports.testJoin = function(options) {
   if (!options.isNode) {
     return;
   }
 
   assert.is(filesystem.join('usr', 'local', 'bin'),
             'usr/local/bin',
             'join to usr/local/bin');
 };
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_focus.js
+++ b/browser/devtools/commandline/test/browser_gcli_focus.js
@@ -9,57 +9,52 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFocus.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFocus.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
-
-exports.setup = function(options) {
-  mockCommands.setup();
-};
-
-exports.shutdown = function(options) {
-  mockCommands.shutdown();
-};
+// var helpers = require('./helpers');
 
 exports.testBasic = function(options) {
   return helpers.audit(options, [
     {
-      skipRemainingIf: options.isJsdom,
       name: 'exec setup',
       setup: function() {
         // Just check that we've got focus, and everything is clear
         helpers.focusInput(options);
-        return helpers.setInput(options, 'help');
+        return helpers.setInput(options, 'echo hi');
       },
       check: { },
       exec: { }
     },
     {
       setup:    'tsn deep',
       check: {
         input:  'tsn deep',
@@ -80,11 +75,8 @@ exports.testBasic = function(options) {
         cursor: 25,
         status: 'VALID',
         outputState: 'false:default',
         tooltipState: 'false:default'
       }
     }
   ]);
 };
-
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_history.js
+++ b/browser/devtools/commandline/test/browser_gcli_history.js
@@ -9,39 +9,44 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testHistory.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testHistory.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var assert = require('test/assert');
-var History = require('gcli/history').History;
+// var assert = require('../testharness/assert');
+var History = require('gcli/ui/history').History;
 
 exports.testSimpleHistory = function (options) {
   var history = new History({});
   history.add('foo');
   history.add('bar');
   assert.is(history.backward(), 'bar');
   assert.is(history.backward(), 'foo');
 
@@ -75,10 +80,8 @@ exports.testForwardsPastIndex = function
   assert.is(history.forward(), 'bar');
 
   // 'Present' time.
   assert.is(history.forward(), '');
 
   // Going to the 'future' just keeps giving us the empty string.
   assert.is(history.forward(), '');
 };
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_incomplete.js
+++ b/browser/devtools/commandline/test/browser_gcli_incomplete.js
@@ -9,60 +9,56 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testIncomplete.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testIncomplete.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var assert = require('test/assert');
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
-
-exports.setup = function(options) {
-  mockCommands.setup();
-};
-
-exports.shutdown = function(options) {
-  mockCommands.shutdown();
-};
+// var assert = require('../testharness/assert');
+// var helpers = require('./helpers');
 
 exports.testBasic = function(options) {
   return helpers.audit(options, [
     {
       setup: 'tsu 2 extra',
       check: {
         args: {
           num: { value: 2, type: 'Argument' }
         }
       },
       post: function() {
-        var requisition = options.display.requisition;
+        var requisition = options.requisition;
 
         assert.is(requisition._unassigned.length,
                   1,
                   'single unassigned: tsu 2 extra');
         assert.is(requisition._unassigned[0].param.type.isIncompleteName,
                   false,
                   'unassigned.isIncompleteName: tsu 2 extra');
       }
@@ -145,17 +141,16 @@ exports.testCompleted = function(options
           txt1: { value: undefined, status: 'VALID' },
           bool: { value: false, status: 'VALID' },
           txt2: { value: undefined, status: 'VALID' },
           num: { value: undefined, status: 'VALID' }
         }
       }
     },
     {
-      skipIf: options.isJsdom,
       setup:    'tsg -<TAB>',
       check: {
         input:  'tsg --txt1 ',
         hints:             '<string> <solo> [options]',
         markup: 'VVVVIIIIIIV',
         cursor: 11,
         status: 'ERROR',
         args: {
@@ -259,17 +254,17 @@ exports.testIncomplete = function(option
           solo: { type: 'BlankArgument' },
           txt1: { type: 'BlankArgument' },
           bool: { type: 'BlankArgument' },
           txt2: { type: 'BlankArgument' },
           num: { type: 'BlankArgument' }
         }
       },
       post: function() {
-        var requisition = options.display.requisition;
+        var requisition = options.requisition;
 
         assert.is(requisition._unassigned[0],
                   requisition.getAssignmentAt(5),
                   'unassigned -');
         assert.is(requisition._unassigned.length,
                   1,
                   'single unassigned - tsg -');
         assert.is(requisition._unassigned[0].param.type.isIncompleteName,
@@ -452,10 +447,8 @@ exports.testHidden = function(options) {
           visible: { value: 'xxx', status: 'VALID' },
           invisiblestring: { value: undefined, status: 'VALID' },
           invisibleboolean: { value: false, status: 'VALID' }
         }
       }
     }
   ]);
 };
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_inputter.js
+++ b/browser/devtools/commandline/test/browser_gcli_inputter.js
@@ -9,97 +9,104 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testInputter.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testInputter.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-var KeyEvent = require('util/util').KeyEvent;
-// var assert = require('test/assert');
-// var mockCommands = require('gclitest/mockCommands');
+// var assert = require('../testharness/assert');
+var KeyEvent = require('gcli/util/util').KeyEvent;
 
 var latestEvent;
 var latestData;
 
 var outputted = function(ev) {
   latestEvent = ev;
 
   ev.output.promise.then(function() {
     latestData = ev.output.data;
-    ev.output.onClose();
   });
 };
 
 
 exports.setup = function(options) {
-  mockCommands.setup();
-  options.display.requisition.commandOutputManager.onOutput.add(outputted);
+  options.requisition.commandOutputManager.onOutput.add(outputted);
 };
 
 exports.shutdown = function(options) {
-  mockCommands.shutdown();
-  options.display.requisition.commandOutputManager.onOutput.remove(outputted);
+  options.requisition.commandOutputManager.onOutput.remove(outputted);
 };
 
 exports.testOutput = function(options) {
   latestEvent = undefined;
   latestData = undefined;
 
-  var inputter = options.display.inputter;
-  var focusManager = options.display.focusManager;
+  var terminal = options.terminal;
+  if (!terminal) {
+    assert.log('Skipping testInputter.testOutput due to lack of terminal.');
+    return;
+  }
 
-  inputter.setInput('tss');
+  var focusManager = terminal.focusManager;
+
+  terminal.setInput('tss');
 
   var ev0 = { keyCode: KeyEvent.DOM_VK_RETURN };
-  inputter.onKeyDown(ev0);
+  terminal.onKeyDown(ev0);
 
-  assert.is(inputter.element.value, 'tss', 'inputter should do nothing on RETURN keyDown');
+  assert.is(terminal.getInputState().typed,
+            'tss',
+            'terminal should do nothing on RETURN keyDown');
   assert.is(latestEvent, undefined, 'no events this test');
   assert.is(latestData, undefined, 'no data this test');
 
   var ev1 = { keyCode: KeyEvent.DOM_VK_RETURN };
-  return inputter.handleKeyUp(ev1).then(function() {
+  return terminal.handleKeyUp(ev1).then(function() {
     assert.ok(latestEvent != null, 'events this test');
     assert.is(latestData, 'Exec: tss ', 'last command is tss');
 
-    assert.is(inputter.element.value, '', 'inputter should exec on RETURN keyUp');
+    assert.is(terminal.getInputState().typed,
+              '',
+              'terminal should exec on RETURN keyUp');
 
     assert.ok(focusManager._recentOutput, 'recent output happened');
 
     var ev2 = { keyCode: KeyEvent.DOM_VK_F1 };
-    return inputter.handleKeyUp(ev2).then(function() {
+    return terminal.handleKeyUp(ev2).then(function() {
       assert.ok(!focusManager._recentOutput, 'no recent output happened post F1');
       assert.ok(focusManager._helpRequested, 'F1 = help');
 
       var ev3 = { keyCode: KeyEvent.DOM_VK_ESCAPE };
-      return inputter.handleKeyUp(ev3).then(function() {
+      return terminal.handleKeyUp(ev3).then(function() {
         assert.ok(!focusManager._helpRequested, 'ESCAPE = anti help');
       });
     });
 
   });
 };
-
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_intro.js
+++ b/browser/devtools/commandline/test/browser_gcli_intro.js
@@ -9,45 +9,49 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testIntro.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testIntro.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var helpers = require('gclitest/helpers');
-var canon = require('gcli/canon');
+// var helpers = require('./helpers');
 
 exports.testIntroStatus = function(options) {
   return helpers.audit(options, [
     {
       skipRemainingIf: function commandIntroMissing() {
-        return canon.getCommand('intro') == null;
+        return options.requisition.canon.getCommand('intro') == null;
       },
       setup:    'intro',
       check: {
         typed:  'intro',
         markup: 'VVVVV',
         status: 'VALID',
         hints: ''
       }
@@ -58,16 +62,17 @@ exports.testIntroStatus = function(optio
         typed:  'intro foo',
         markup: 'VVVVVVEEE',
         status: 'ERROR',
         hints: ''
       }
     },
     {
       setup:    'intro',
+      skipIf: options.isNoDom,
       check: {
         typed:  'intro',
         markup: 'VVVVV',
         status: 'VALID',
         hints: ''
       },
       exec: {
         output: [
@@ -75,11 +80,8 @@ exports.testIntroStatus = function(optio
           /help/,
           /F1/,
           /Escape/
         ]
       }
     }
   ]);
 };
-
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_js.js
+++ b/browser/devtools/commandline/test/browser_gcli_js.js
@@ -9,86 +9,100 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testJs.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testJs.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var assert = require('test/assert');
-// var helpers = require('gclitest/helpers');
+// var assert = require('../testharness/assert');
+// var helpers = require('./helpers');
 var javascript = require('gcli/types/javascript');
-var canon = require('gcli/canon');
 
 var tempWindow;
 
 exports.setup = function(options) {
+  if (options.isNoDom) {
+    return;
+  }
+
   tempWindow = javascript.getGlobalObject();
   Object.defineProperty(options.window, 'donteval', {
     get: function() {
       assert.ok(false, 'donteval should not be used');
       return { cant: '', touch: '', 'this': '' };
     },
     enumerable: true,
     configurable : true
   });
   javascript.setGlobalObject(options.window);
 };
 
 exports.shutdown = function(options) {
+  if (options.isNoDom) {
+    return;
+  }
+
   javascript.setGlobalObject(tempWindow);
   tempWindow = undefined;
   delete options.window.donteval;
 };
 
+function jsTestAllowed(options) {
+  return options.isRemote || options.isNoDom ||
+         options.requisition.canon.getCommand('{') == null;
+}
+
 exports.testBasic = function(options) {
   return helpers.audit(options, [
     {
-      skipRemainingIf: function commandJsMissing() {
-        return canon.getCommand('{') == null;
-      },
+      skipRemainingIf: jsTestAllowed,
       setup:    '{',
       check: {
         input:  '{',
         hints:   '',
         markup: 'V',
         cursor: 1,
         current: 'javascript',
         status: 'ERROR',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: '{' },
           javascript: {
             value: undefined,
             arg: '{',
-            status: 'INCOMPLETE',
-            message: ''
+            status: 'INCOMPLETE'
           }
         }
       }
     },
     {
       setup:    '{ ',
       check: {
         input:  '{ ',
@@ -99,18 +113,17 @@ exports.testBasic = function(options) {
         status: 'ERROR',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: '{' },
           javascript: {
             value: undefined,
             arg: '{ ',
-            status: 'INCOMPLETE',
-            message: ''
+            status: 'INCOMPLETE'
           }
         }
       }
     },
     {
       setup:    '{ w',
       check: {
         input:  '{ w',
@@ -121,18 +134,17 @@ exports.testBasic = function(options) {
         status: 'ERROR',
         predictionsContains: [ 'window' ],
         unassigned: [ ],
         args: {
           command: { name: '{' },
           javascript: {
             value: 'w',
             arg: '{ w',
-            status: 'INCOMPLETE',
-            message: ''
+            status: 'INCOMPLETE'
           }
         }
       }
     },
     {
       setup:    '{ windo',
       check: {
         input:  '{ windo',
@@ -143,18 +155,17 @@ exports.testBasic = function(options) {
         status: 'ERROR',
         predictions: [ 'window' ],
         unassigned: [ ],
         args: {
           command: { name: '{' },
           javascript: {
             value: 'windo',
             arg: '{ windo',
-            status: 'INCOMPLETE',
-            message: ''
+            status: 'INCOMPLETE'
           }
         }
       }
     },
     {
       setup:    '{ window',
       check: {
         input:  '{ window',
@@ -187,18 +198,17 @@ exports.testBasic = function(options) {
         status: 'ERROR',
         predictionsContains: [ 'window.document' ],
         unassigned: [ ],
         args: {
           command: { name: '{' },
           javascript: {
             value: 'window.do',
             arg: '{ window.do',
-            status: 'INCOMPLETE',
-            message: ''
+            status: 'INCOMPLETE'
           }
         }
       }
     },
     {
       setup:    '{ window.document.title',
       check: {
         input:  '{ window.document.title',
@@ -221,36 +231,33 @@ exports.testBasic = function(options) {
       }
     }
   ]);
 };
 
 exports.testDocument = function(options) {
   return helpers.audit(options, [
     {
-      skipRemainingIf: function commandJsMissing() {
-        return canon.getCommand('{') == null;
-      },
+      skipRemainingIf: jsTestAllowed,
       setup:    '{ docu',
       check: {
         input:  '{ docu',
         hints:        'ment',
         markup: 'VVIIII',
         cursor: 6,
         current: 'javascript',
         status: 'ERROR',
         predictions: [ 'document' ],
         unassigned: [ ],
         args: {
           command: { name: '{' },
           javascript: {
             value: 'docu',
             arg: '{ docu',
-            status: 'INCOMPLETE',
-            message: ''
+            status: 'INCOMPLETE'
           }
         }
       }
     },
     {
       setup: '{ docu<TAB>',
       check: {
         input:  '{ document',
@@ -283,24 +290,22 @@ exports.testDocument = function(options)
         status: 'ERROR',
         predictions: [ 'document.title' ],
         unassigned: [ ],
         args: {
           command: { name: '{' },
           javascript: {
             value: 'document.titl',
             arg: '{ document.titl',
-            status: 'INCOMPLETE',
-            message: ''
+            status: 'INCOMPLETE'
           }
         }
       }
     },
     {
-      skipIf: options.isJsdom,
       setup: '{ document.titl<TAB>',
       check: {
         input:  '{ document.title ',
         hints:                   '',
         markup: 'VVVVVVVVVVVVVVVVV',
         cursor: 17,
         current: 'javascript',
         status: 'VALID',
@@ -338,43 +343,40 @@ exports.testDocument = function(options)
           }
         }
       }
     }
   ]);
 };
 
 exports.testDonteval = function(options) {
-  if (!options.isJsdom) {
-    // jsdom causes an eval here, maybe that's node/v8?
+  if (!options.isNoDom) {
+    // nodom causes an eval here, maybe that's node/v8?
     assert.ok('donteval' in options.window, 'donteval exists');
   }
 
   return helpers.audit(options, [
     {
-      skipRemainingIf: function commandJsMissing() {
-        return canon.getCommand('{') == null;
-      },
+      skipRemainingIf: jsTestAllowed,
       setup:    '{ don',
       check: {
         input:  '{ don',
         hints:       'teval',
         markup: 'VVIII',
         cursor: 5,
         current: 'javascript',
         status: 'ERROR',
         predictions: [ 'donteval' ],
         unassigned: [ ],
         args: {
           command: { name: '{' },
           javascript: {
             value: 'don',
             arg: '{ don',
-            status: 'INCOMPLETE',
-            message: ''
+            status: 'INCOMPLETE'
           }
         }
       }
     },
     {
       setup:    '{ donteval',
       check: {
         input:  '{ donteval',
@@ -466,10 +468,125 @@ exports.testDonteval = function(options)
             message: ''
           }
         }
       }
     }
   ]);
 };
 
-
-// });
+exports.testExec = function(options) {
+  return helpers.audit(options, [
+    {
+      skipRemainingIf: jsTestAllowed,
+      setup:    '{ 1+1',
+      check: {
+        input:  '{ 1+1',
+        hints:       '',
+        markup: 'VVVVV',
+        cursor: 5,
+        current: 'javascript',
+        status: 'VALID',
+        options: [ ],
+        message: '',
+        predictions: [ ],
+        unassigned: [ ],
+        args: {
+          javascript: {
+            value: '1+1',
+            arg: '{ 1+1',
+            status: 'VALID',
+            message: ''
+          }
+        }
+      },
+      exec: {
+        output: '2',
+        type: 'number',
+        error: false
+      }
+    },
+    {
+      setup:    '{ 1+1 }',
+      check: {
+        input:  '{ 1+1 }',
+        hints:         '',
+        markup: 'VVVVVVV',
+        cursor: 7,
+        current: 'javascript',
+        status: 'VALID',
+        options: [ ],
+        message: '',
+        predictions: [ ],
+        unassigned: [ ],
+        args: {
+          javascript: {
+            value: '1+1',
+            arg: '{ 1+1 }',
+            status: 'VALID',
+            message: ''
+          }
+        }
+      },
+      exec: {
+        output: '2',
+        type: 'number',
+        error: false
+      }
+    },
+    {
+      setup:    '{ "hello"',
+      check: {
+        input:  '{ "hello"',
+        hints:           '',
+        markup: 'VVVVVVVVV',
+        cursor: 9,
+        current: 'javascript',
+        status: 'VALID',
+        options: [ ],
+        message: '',
+        predictions: [ ],
+        unassigned: [ ],
+        args: {
+          javascript: {
+            value: '"hello"',
+            arg: '{ "hello"',
+            status: 'VALID',
+            message: ''
+          }
+        }
+      },
+      exec: {
+        output: 'hello',
+        type: 'string',
+        error: false
+      }
+    },
+    {
+      setup:    '{ "hello" + 1',
+      check: {
+        input:  '{ "hello" + 1',
+        hints:               '',
+        markup: 'VVVVVVVVVVVVV',
+        cursor: 13,
+        current: 'javascript',
+        status: 'VALID',
+        options: [ ],
+        message: '',
+        predictions: [ ],
+        unassigned: [ ],
+        args: {
+          javascript: {
+            value: '"hello" + 1',
+            arg: '{ "hello" + 1',
+            status: 'VALID',
+            message: ''
+          }
+        }
+      },
+      exec: {
+        output: 'hello1',
+        type: 'string',
+        error: false
+      }
+    }
+  ]);
+};
--- a/browser/devtools/commandline/test/browser_gcli_keyboard1.js
+++ b/browser/devtools/commandline/test/browser_gcli_keyboard1.js
@@ -9,103 +9,96 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard1.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard1.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
+var javascript = require('gcli/types/javascript');
+// var helpers = require('./helpers');
 
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
+var tempWindow;
 
 exports.setup = function(options) {
-  mockCommands.setup();
+  tempWindow = javascript.getGlobalObject();
+  javascript.setGlobalObject(options.window);
 };
 
 exports.shutdown = function(options) {
-  mockCommands.shutdown();
+  javascript.setGlobalObject(tempWindow);
+  tempWindow = undefined;
 };
 
-exports.testComplete = function(options) {
+exports.testSimple = function(options) {
   return helpers.audit(options, [
     {
-      setup: 'tsn e<DOWN><DOWN><DOWN><DOWN><DOWN><TAB>',
-      check: { input: 'tsn exte ' }
-    },
-    {
-      setup: 'tsn e<DOWN><DOWN><DOWN><DOWN><TAB>',
-      check: { input: 'tsn ext ' }
-    },
-    {
-      setup: 'tsn e<DOWN><DOWN><DOWN><TAB>',
-      check: { input: 'tsn extend ' }
-    },
-    {
-      setup: 'tsn e<DOWN><DOWN><TAB>',
-      check: { input: 'tsn exten ' }
-    },
-    {
-      setup: 'tsn e<DOWN><TAB>',
-      check: { input: 'tsn exte ' }
-    },
-    {
-      setup: 'tsn e<TAB>',
-      check: { input: 'tsn ext ' }
+      setup: 'tsela<TAB>',
+      check: { input: 'tselarr ', cursor: 8 }
     },
     {
-      setup: 'tsn e<UP><TAB>',
-      check: { input: 'tsn extend ' }
-    },
-    {
-      setup: 'tsn e<UP><UP><TAB>',
-      check: { input: 'tsn exten ' }
-    },
-    {
-      setup: 'tsn e<UP><UP><UP><TAB>',
-      check: { input: 'tsn exte ' }
+      setup: 'tsn di<TAB>',
+      check: { input: 'tsn dif ', cursor: 8 }
     },
     {
-      setup: 'tsn e<UP><UP><UP><UP><TAB>',
-      check: { input: 'tsn ext ' }
-    },
-    {
-      setup: 'tsn e<UP><UP><UP><UP><UP><TAB>',
-      check: { input: 'tsn extend ' }
-    },
-    {
-      setup: 'tsn e<UP><UP><UP><UP><UP><UP><TAB>',
-      check: { input: 'tsn exten ' }
-    },
-    {
-      setup: 'tsn e<UP><UP><UP><UP><UP><UP><UP><TAB>',
-      check: { input: 'tsn exte ' }
-    },
-    {
-      setup: 'tsn e<UP><UP><UP><UP><UP><UP><UP><UP><TAB>',
-      check: { input: 'tsn ext ' }
+      setup: 'tsg a<TAB>',
+      check: { input: 'tsg aaa ', cursor: 8 }
     }
   ]);
 };
 
+exports.testScript = function(options) {
+  return helpers.audit(options, [
+    {
+      skipIf: function commandJsMissing() {
+        return options.requisition.canon.getCommand('{') == null;
+      },
+      setup: '{ wind<TAB>',
+      check: { input: '{ window' }
+    },
+    {
+      skipIf: function commandJsMissing() {
+        return options.requisition.canon.getCommand('{') == null;
+      },
+      setup: '{ window.docum<TAB>',
+      check: { input: '{ window.document' }
+    }
+  ]);
+};
 
-// });
+exports.testJsdom = function(options) {
+  return helpers.audit(options, [
+    {
+      skipIf: function jsDomOrCommandJsMissing() {
+        return options.requisition.canon.getCommand('{') == null;
+      },
+      setup: '{ window.document.titl<TAB>',
+      check: { input: '{ window.document.title ' }
+    }
+  ]);
+};
--- a/browser/devtools/commandline/test/browser_gcli_keyboard2.js
+++ b/browser/devtools/commandline/test/browser_gcli_keyboard2.js
@@ -9,66 +9,43 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard2.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard2.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
-
-exports.setup = function(options) {
-  mockCommands.setup();
-};
-
-exports.shutdown = function(options) {
-  mockCommands.shutdown();
-};
-
-// Bug 664377: Add tests for internal completion. i.e. "tsela<TAB> 1"
-
-exports.testSimple = function(options) {
-  return helpers.audit(options, [
-    {
-      setup: 'tsela<TAB>',
-      check: { input: 'tselarr ', cursor: 8 }
-    },
-    {
-      setup: 'tsn di<TAB>',
-      check: { input: 'tsn dif ', cursor: 8 }
-    },
-    {
-      setup: 'tsg a<TAB>',
-      check: { input: 'tsg aaa ', cursor: 8 }
-    }
-  ]);
-};
+// var helpers = require('./helpers');
 
 exports.testIncr = function(options) {
   return helpers.audit(options, [
     /*
     // We currently refuse to increment/decrement things with a non-valid
     // status which makes sense for many cases, and is a decent default.
     // However in theory we could do better, these tests are there for then
     {
@@ -152,262 +129,8 @@ exports.testIncr = function(options) {
     // See notes above
     {
       setup: 'tsu 100<UP>',
       check: { input: 'tsu 10' }
     }
     */
   ]);
 };
-
-exports.testDecr = function(options) {
-  return helpers.audit(options, [
-    /*
-    // See notes at top of testIncr
-    {
-      setup: 'tsu -70<DOWN>',
-      check: { input: 'tsu -5' }
-    },
-    {
-      setup: 'tsu -7<DOWN>',
-      check: { input: 'tsu -5' }
-    },
-    {
-      setup: 'tsu -6<DOWN>',
-      check: { input: 'tsu -5' }
-    },
-    */
-    {
-      setup: 'tsu -5<DOWN>',
-      check: { input: 'tsu -5' }
-    },
-    {
-      setup: 'tsu -4<DOWN>',
-      check: { input: 'tsu -5' }
-    },
-    {
-      setup: 'tsu -3<DOWN>',
-      check: { input: 'tsu -5' }
-    },
-    {
-      setup: 'tsu -2<DOWN>',
-      check: { input: 'tsu -3' }
-    },
-    {
-      setup: 'tsu -1<DOWN>',
-      check: { input: 'tsu -3' }
-    },
-    {
-      setup: 'tsu 0<DOWN>',
-      check: { input: 'tsu -3' }
-    },
-    {
-      setup: 'tsu 1<DOWN>',
-      check: { input: 'tsu 0' }
-    },
-    {
-      setup: 'tsu 2<DOWN>',
-      check: { input: 'tsu 0' }
-    },
-    {
-      setup: 'tsu 3<DOWN>',
-      check: { input: 'tsu 0' }
-    },
-    {
-      setup: 'tsu 4<DOWN>',
-      check: { input: 'tsu 3' }
-    },
-    {
-      setup: 'tsu 5<DOWN>',
-      check: { input: 'tsu 3' }
-    },
-    {
-      setup: 'tsu 6<DOWN>',
-      check: { input: 'tsu 3' }
-    },
-    {
-      setup: 'tsu 7<DOWN>',
-      check: { input: 'tsu 6' }
-    },
-    {
-      setup: 'tsu 8<DOWN>',
-      check: { input: 'tsu 6' }
-    },
-    {
-      setup: 'tsu 9<DOWN>',
-      check: { input: 'tsu 6' }
-    },
-    {
-      setup: 'tsu 10<DOWN>',
-      check: { input: 'tsu 9' }
-    }
-    /*
-    // See notes at top of testIncr
-    {
-      setup: 'tsu 100<DOWN>',
-      check: { input: 'tsu 9' }
-    }
-    */
-  ]);
-};
-
-exports.testIncrFloat = function(options) {
-  return helpers.audit(options, [
-    /*
-    // See notes at top of testIncr
-    {
-      setup: 'tsf -70<UP>',
-      check: { input: 'tsf -6.5' }
-    },
-    */
-    {
-      setup: 'tsf -6.5<UP>',
-      check: { input: 'tsf -6' }
-    },
-    {
-      setup: 'tsf -6<UP>',
-      check: { input: 'tsf -4.5' }
-    },
-    {
-      setup: 'tsf -4.5<UP>',
-      check: { input: 'tsf -3' }
-    },
-    {
-      setup: 'tsf -4<UP>',
-      check: { input: 'tsf -3' }
-    },
-    {
-      setup: 'tsf -3<UP>',
-      check: { input: 'tsf -1.5' }
-    },
-    {
-      setup: 'tsf -1.5<UP>',
-      check: { input: 'tsf 0' }
-    },
-    {
-      setup: 'tsf 0<UP>',
-      check: { input: 'tsf 1.5' }
-    },
-    {
-      setup: 'tsf 1.5<UP>',
-      check: { input: 'tsf 3' }
-    },
-    {
-      setup: 'tsf 2<UP>',
-      check: { input: 'tsf 3' }
-    },
-    {
-      setup: 'tsf 3<UP>',
-      check: { input: 'tsf 4.5' }
-    },
-    {
-      setup: 'tsf 5<UP>',
-      check: { input: 'tsf 6' }
-    }
-    /*
-    // See notes at top of testIncr
-    {
-      setup: 'tsf 100<UP>',
-      check: { input: 'tsf -6.5' }
-    }
-    */
-  ]);
-};
-
-exports.testDecrFloat = function(options) {
-  return helpers.audit(options, [
-    /*
-    // See notes at top of testIncr
-    {
-      setup: 'tsf -70<DOWN>',
-      check: { input: 'tsf 11.5' }
-    },
-    */
-    {
-      setup: 'tsf -6.5<DOWN>',
-      check: { input: 'tsf -6.5' }
-    },
-    {
-      setup: 'tsf -6<DOWN>',
-      check: { input: 'tsf -6.5' }
-    },
-    {
-      setup: 'tsf -4.5<DOWN>',
-      check: { input: 'tsf -6' }
-    },
-    {
-      setup: 'tsf -4<DOWN>',
-      check: { input: 'tsf -4.5' }
-    },
-    {
-      setup: 'tsf -3<DOWN>',
-      check: { input: 'tsf -4.5' }
-    },
-    {
-      setup: 'tsf -1.5<DOWN>',
-      check: { input: 'tsf -3' }
-    },
-    {
-      setup: 'tsf 0<DOWN>',
-      check: { input: 'tsf -1.5' }
-    },
-    {
-      setup: 'tsf 1.5<DOWN>',
-      check: { input: 'tsf 0' }
-    },
-    {
-      setup: 'tsf 2<DOWN>',
-      check: { input: 'tsf 1.5' }
-    },
-    {
-      setup: 'tsf 3<DOWN>',
-      check: { input: 'tsf 1.5' }
-    },
-    {
-      setup: 'tsf 5<DOWN>',
-      check: { input: 'tsf 4.5' }
-    }
-    /*
-    // See notes at top of testIncr
-    {
-      setup: 'tsf 100<DOWN>',
-      check: { input: 'tsf 11.5' }
-    }
-    */
-  ]);
-};
-
-exports.testIncrSelection = function(options) {
-  /*
-  // Bug 829516:  GCLI up/down navigation over selection is sometimes bizarre
-  return helpers.audit(options, [
-    {
-      setup: 'tselarr <DOWN>',
-      check: { hints: '2' },
-      exec: {}
-    },
-    {
-      setup: 'tselarr <DOWN><DOWN>',
-      check: { hints: '3' },
-      exec: {}
-    },
-    {
-      setup: 'tselarr <DOWN><DOWN><DOWN>',
-      check: { hints: '1' },
-      exec: {}
-    }
-  ]);
-  */
-};
-
-exports.testDecrSelection = function(options) {
-  /*
-  // Bug 829516:  GCLI up/down navigation over selection is sometimes bizarre
-  return helpers.audit(options, [
-    {
-      setup: 'tselarr <UP>',
-      check: { hints: '3' }
-    }
-  ]);
-  */
-};
-
-// });
--- a/browser/devtools/commandline/test/browser_gcli_keyboard3.js
+++ b/browser/devtools/commandline/test/browser_gcli_keyboard3.js
@@ -9,83 +9,126 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard3.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard3.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-var javascript = require('gcli/types/javascript');
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
-var canon = require('gcli/canon');
-
-var tempWindow;
-
-exports.setup = function(options) {
-  mockCommands.setup();
-
-  tempWindow = javascript.getGlobalObject();
-  javascript.setGlobalObject(options.window);
-};
+// var helpers = require('./helpers');
 
-exports.shutdown = function(options) {
-  javascript.setGlobalObject(tempWindow);
-  tempWindow = undefined;
-
-  mockCommands.shutdown();
-};
-
-exports.testScript = function(options) {
+exports.testDecr = function(options) {
   return helpers.audit(options, [
+    /*
+    // See notes at top of testIncr in testKeyboard2.js
     {
-      skipIf: function commandJsMissing() {
-        return canon.getCommand('{') == null;
-      },
-      setup: '{ wind<TAB>',
-      check: { input: '{ window' }
+      setup: 'tsu -70<DOWN>',
+      check: { input: 'tsu -5' }
+    },
+    {
+      setup: 'tsu -7<DOWN>',
+      check: { input: 'tsu -5' }
+    },
+    {
+      setup: 'tsu -6<DOWN>',
+      check: { input: 'tsu -5' }
+    },
+    */
+    {
+      setup: 'tsu -5<DOWN>',
+      check: { input: 'tsu -5' }
+    },
+    {
+      setup: 'tsu -4<DOWN>',
+      check: { input: 'tsu -5' }
+    },
+    {
+      setup: 'tsu -3<DOWN>',
+      check: { input: 'tsu -5' }
+    },
+    {
+      setup: 'tsu -2<DOWN>',
+      check: { input: 'tsu -3' }
+    },
+    {
+      setup: 'tsu -1<DOWN>',
+      check: { input: 'tsu -3' }
+    },
+    {
+      setup: 'tsu 0<DOWN>',
+      check: { input: 'tsu -3' }
     },
     {
-      skipIf: function commandJsMissing() {
-        return canon.getCommand('{') == null;
-      },
-      setup: '{ window.docum<TAB>',
-      check: { input: '{ window.document' }
+      setup: 'tsu 1<DOWN>',
+      check: { input: 'tsu 0' }
+    },
+    {
+      setup: 'tsu 2<DOWN>',
+      check: { input: 'tsu 0' }
+    },
+    {
+      setup: 'tsu 3<DOWN>',
+      check: { input: 'tsu 0' }
+    },
+    {
+      setup: 'tsu 4<DOWN>',
+      check: { input: 'tsu 3' }
+    },
+    {
+      setup: 'tsu 5<DOWN>',
+      check: { input: 'tsu 3' }
+    },
+    {
+      setup: 'tsu 6<DOWN>',
+      check: { input: 'tsu 3' }
+    },
+    {
+      setup: 'tsu 7<DOWN>',
+      check: { input: 'tsu 6' }
+    },
+    {
+      setup: 'tsu 8<DOWN>',
+      check: { input: 'tsu 6' }
+    },
+    {
+      setup: 'tsu 9<DOWN>',
+      check: { input: 'tsu 6' }
+    },
+    {
+      setup: 'tsu 10<DOWN>',
+      check: { input: 'tsu 9' }
     }
+    /*
+    // See notes at top of testIncr
+    {
+      setup: 'tsu 100<DOWN>',
+      check: { input: 'tsu 9' }
+    }
+    */
   ]);
 };
-
-exports.testJsdom = function(options) {
-  return helpers.audit(options, [
-    {
-      skipIf: function jsDomOrCommandJsMissing() {
-        return options.isJsdom || canon.getCommand('{') == null;
-      },
-      setup: '{ window.document.titl<TAB>',
-      check: { input: '{ window.document.title ' }
-    }
-  ]);
-};
-
-
-// });
new file mode 100644
--- /dev/null
+++ b/browser/devtools/commandline/test/browser_gcli_keyboard4.js
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2012, Mozilla Foundation and contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+// <INJECTED SOURCE:START>
+
+// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
+// DO NOT EDIT IT DIRECTLY
+
+var exports = {};
+
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard4.js</p>";
+
+function test() {
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
+}
+
+// <INJECTED SOURCE:END>
+
+// var helpers = require('./helpers');
+
+exports.testIncrFloat = function(options) {
+  return helpers.audit(options, [
+    /*
+    // See notes at top of testIncr
+    {
+      setup: 'tsf -70<UP>',
+      check: { input: 'tsf -6.5' }
+    },
+    */
+    {
+      setup: 'tsf -6.5<UP>',
+      check: { input: 'tsf -6' }
+    },
+    {
+      setup: 'tsf -6<UP>',
+      check: { input: 'tsf -4.5' }
+    },
+    {
+      setup: 'tsf -4.5<UP>',
+      check: { input: 'tsf -3' }
+    },
+    {
+      setup: 'tsf -4<UP>',
+      check: { input: 'tsf -3' }
+    },
+    {
+      setup: 'tsf -3<UP>',
+      check: { input: 'tsf -1.5' }
+    },
+    {
+      setup: 'tsf -1.5<UP>',
+      check: { input: 'tsf 0' }
+    },
+    {
+      setup: 'tsf 0<UP>',
+      check: { input: 'tsf 1.5' }
+    },
+    {
+      setup: 'tsf 1.5<UP>',
+      check: { input: 'tsf 3' }
+    },
+    {
+      setup: 'tsf 2<UP>',
+      check: { input: 'tsf 3' }
+    },
+    {
+      setup: 'tsf 3<UP>',
+      check: { input: 'tsf 4.5' }
+    },
+    {
+      setup: 'tsf 5<UP>',
+      check: { input: 'tsf 6' }
+    }
+    /*
+    // See notes at top of testIncr
+    {
+      setup: 'tsf 100<UP>',
+      check: { input: 'tsf -6.5' }
+    }
+    */
+  ]);
+};
+
+exports.testDecrFloat = function(options) {
+  return helpers.audit(options, [
+    /*
+    // See notes at top of testIncr
+    {
+      setup: 'tsf -70<DOWN>',
+      check: { input: 'tsf 11.5' }
+    },
+    */
+    {
+      setup: 'tsf -6.5<DOWN>',
+      check: { input: 'tsf -6.5' }
+    },
+    {
+      setup: 'tsf -6<DOWN>',
+      check: { input: 'tsf -6.5' }
+    },
+    {
+      setup: 'tsf -4.5<DOWN>',
+      check: { input: 'tsf -6' }
+    },
+    {
+      setup: 'tsf -4<DOWN>',
+      check: { input: 'tsf -4.5' }
+    },
+    {
+      setup: 'tsf -3<DOWN>',
+      check: { input: 'tsf -4.5' }
+    },
+    {
+      setup: 'tsf -1.5<DOWN>',
+      check: { input: 'tsf -3' }
+    },
+    {
+      setup: 'tsf 0<DOWN>',
+      check: { input: 'tsf -1.5' }
+    },
+    {
+      setup: 'tsf 1.5<DOWN>',
+      check: { input: 'tsf 0' }
+    },
+    {
+      setup: 'tsf 2<DOWN>',
+      check: { input: 'tsf 1.5' }
+    },
+    {
+      setup: 'tsf 3<DOWN>',
+      check: { input: 'tsf 1.5' }
+    },
+    {
+      setup: 'tsf 5<DOWN>',
+      check: { input: 'tsf 4.5' }
+    }
+    /*
+    // See notes at top of testIncr
+    {
+      setup: 'tsf 100<DOWN>',
+      check: { input: 'tsf 11.5' }
+    }
+    */
+  ]);
+};
+
+exports.testIncrSelection = function(options) {
+  /*
+  // Bug 829516:  GCLI up/down navigation over selection is sometimes bizarre
+  return helpers.audit(options, [
+    {
+      setup: 'tselarr <DOWN>',
+      check: { hints: '2' },
+      exec: {}
+    },
+    {
+      setup: 'tselarr <DOWN><DOWN>',
+      check: { hints: '3' },
+      exec: {}
+    },
+    {
+      setup: 'tselarr <DOWN><DOWN><DOWN>',
+      check: { hints: '1' },
+      exec: {}
+    }
+  ]);
+  */
+};
+
+exports.testDecrSelection = function(options) {
+  /*
+  // Bug 829516:  GCLI up/down navigation over selection is sometimes bizarre
+  return helpers.audit(options, [
+    {
+      setup: 'tselarr <UP>',
+      check: { hints: '3' }
+    }
+  ]);
+  */
+};
new file mode 100644
--- /dev/null
+++ b/browser/devtools/commandline/test/browser_gcli_keyboard5.js
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012, Mozilla Foundation and contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+// <INJECTED SOURCE:START>
+
+// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
+// DO NOT EDIT IT DIRECTLY
+
+var exports = {};
+
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard5.js</p>";
+
+function test() {
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
+}
+
+// <INJECTED SOURCE:END>
+
+// var helpers = require('./helpers');
+
+exports.testCompleteDown = function(options) {
+  return helpers.audit(options, [
+    {
+      setup: 'tsn e<DOWN><DOWN><DOWN><DOWN><DOWN><TAB>',
+      check: { input: 'tsn exte ' }
+    },
+    {
+      setup: 'tsn e<DOWN><DOWN><DOWN><DOWN><TAB>',
+      check: { input: 'tsn ext ' }
+    },
+    {
+      setup: 'tsn e<DOWN><DOWN><DOWN><TAB>',
+      check: { input: 'tsn extend ' }
+    },
+    {
+      setup: 'tsn e<DOWN><DOWN><TAB>',
+      check: { input: 'tsn exten ' }
+    },
+    {
+      setup: 'tsn e<DOWN><TAB>',
+      check: { input: 'tsn exte ' }
+    },
+    {
+      setup: 'tsn e<TAB>',
+      check: { input: 'tsn ext ' }
+    }
+  ]);
+};
new file mode 100644
--- /dev/null
+++ b/browser/devtools/commandline/test/browser_gcli_keyboard6.js
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012, Mozilla Foundation and contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+// <INJECTED SOURCE:START>
+
+// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
+// DO NOT EDIT IT DIRECTLY
+
+var exports = {};
+
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard6.js</p>";
+
+function test() {
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
+}
+
+// <INJECTED SOURCE:END>
+
+// var helpers = require('./helpers');
+
+exports.testCompleteUp = function(options) {
+  return helpers.audit(options, [
+    {
+      setup: 'tsn e<UP><TAB>',
+      check: { input: 'tsn extend ' }
+    },
+    {
+      setup: 'tsn e<UP><UP><TAB>',
+      check: { input: 'tsn exten ' }
+    },
+    {
+      setup: 'tsn e<UP><UP><UP><TAB>',
+      check: { input: 'tsn exte ' }
+    },
+    {
+      setup: 'tsn e<UP><UP><UP><UP><TAB>',
+      check: { input: 'tsn ext ' }
+    },
+    {
+      setup: 'tsn e<UP><UP><UP><UP><UP><TAB>',
+      check: { input: 'tsn extend ' }
+    },
+    {
+      setup: 'tsn e<UP><UP><UP><UP><UP><UP><TAB>',
+      check: { input: 'tsn exten ' }
+    },
+    {
+      setup: 'tsn e<UP><UP><UP><UP><UP><UP><UP><TAB>',
+      check: { input: 'tsn exte ' }
+    },
+    {
+      setup: 'tsn e<UP><UP><UP><UP><UP><UP><UP><UP><TAB>',
+      check: { input: 'tsn ext ' }
+    }
+  ]);
+};
--- a/browser/devtools/commandline/test/browser_gcli_menu.js
+++ b/browser/devtools/commandline/test/browser_gcli_menu.js
@@ -9,47 +9,43 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testMenu.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testMenu.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
-
-exports.setup = function(options) {
-  mockCommands.setup();
-};
-
-exports.shutdown = function(options) {
-  mockCommands.shutdown();
-};
+// var helpers = require('./helpers');
 
 exports.testOptions = function(options) {
   return helpers.audit(options, [
     {
       setup:    'tslong',
       check: {
         input:  'tslong',
         markup: 'VVVVVV',
@@ -63,12 +59,8 @@ exports.testOptions = function(options) 
           bool2: { value: false, status: 'VALID' },
           sel2: { value: undefined, status: 'VALID' },
           num2: { value: undefined, status: 'VALID' }
         }
       }
     }
   ]);
 };
-
-
-// });
-
--- a/browser/devtools/commandline/test/browser_gcli_node.js
+++ b/browser/devtools/commandline/test/browser_gcli_node.js
@@ -9,66 +9,70 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// define(function(require, exports, module) {
-
+'use strict';
 // <INJECTED SOURCE:START>
 
 // THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
 // DO NOT EDIT IT DIRECTLY
 
 var exports = {};
 
-const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testNode.js</p>";
+var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testNode.js</p>";
 
 function test() {
-  helpers.addTabWithToolbar(TEST_URI, function(options) {
-    return helpers.runTests(options, exports);
-  }).then(finish);
+  return Task.spawn(function() {
+    let options = yield helpers.openTab(TEST_URI);
+    yield helpers.openToolbar(options);
+    gcli.addItems(mockCommands.items);
+
+    yield helpers.runTests(options, exports);
+
+    gcli.removeItems(mockCommands.items);
+    yield helpers.closeToolbar(options);
+    yield helpers.closeTab(options);
+  }).then(finish, helpers.handleError);
 }
 
 // <INJECTED SOURCE:END>
 
-'use strict';
-
-// var assert = require('test/assert');
-// var helpers = require('gclitest/helpers');
-// var mockCommands = require('gclitest/mockCommands');
+// var assert = require('../testharness/assert');
+// var helpers = require('./helpers');
 var nodetype = require('gcli/types/node');
 
 exports.setup = function(options) {
-  mockCommands.setup();
-  nodetype.setDocument(options.window.document);
+  if (options.window) {
+    nodetype.setDocument(options.window.document);
+  }
 };
 
 exports.shutdown = function(options) {
-  mockCommands.shutdown();
   nodetype.unsetDocument();
 };
 
 exports.testNode = function(options) {
   return helpers.audit(options, [
     {
       setup:    'tse ',
       check: {
         input:  'tse ',
         hints:      '<node> [options]',
         markup: 'VVVV',
         cursor: 4,
         current: 'node',
         status: 'ERROR',
         args: {
           command: { name: 'tse' },
-          node: { status: 'INCOMPLETE', message: '' },
+          node: { status: 'INCOMPLETE' },
           nodes: { status: 'VALID' },
           nodes2: { status: 'VALID' }
         }
       }
     },
     {
       setup:    'tse :',
       check: {
@@ -130,17 +134,16 @@ exports.testNode = function(options) {
             message: 'Syntax error in CSS query'
           },
           nodes: { status: 'VALID' },
           nodes2: { status: 'VALID' }
         }
       }
     },
     {
-      skipIf: options.isJsdom,
       setup:    'tse *',
       check: {
         input:  'tse *',
         hints:       ' [options]',
         markup: 'VVVVE',
         cursor: 5,
         current: 'node',
         status: 'ERROR',
@@ -156,21 +159,21 @@ exports.testNode = function(options) {
           nodes2: { status: 'VALID' }
         }
       }
     }
   ]);
 };
 
 exports.testNodeDom = function(options) {
-  var requisition = options.display.requisition;
+  var requisition = options.requisition;
 
   return helpers.audit(options, [
     {
-      skipIf: options.isJsdom,
+      skipRemainingIf: options.isNoDom,
       setup:    'tse :root'