Bug 1243452 - Make DebuggerClient.close return a Promise. r=jryans draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Wed, 31 Aug 2016 09:39:42 -0700
changeset 408553 ae834b182fa4f95317a70c2d73e6855783e18263
parent 407496 b18c8bcdc116eef8799880b7c50317bf54218474
child 408554 cd644f22ff59bd09800b6607072405fbe589a332
push id28249
push userbmo:poirot.alex@gmail.com
push dateThu, 01 Sep 2016 09:44:27 +0000
reviewersjryans
bugs1243452
milestone51.0a1
Bug 1243452 - Make DebuggerClient.close return a Promise. r=jryans MozReview-Commit-ID: 26PNAS431Hc
devtools/client/debugger/test/mochitest/browser_dbg_addonactor.js
devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-01.js
devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-02.js
devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-03.js
devtools/client/debugger/test/mochitest/browser_dbg_chrome-debugging.js
devtools/client/debugger/test/mochitest/browser_dbg_debugger-statement.js
devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-01.js
devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-02.js
devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-03.js
devtools/client/debugger/test/mochitest/browser_dbg_globalactor.js
devtools/client/debugger/test/mochitest/browser_dbg_listaddons.js
devtools/client/debugger/test/mochitest/browser_dbg_listtabs-01.js
devtools/client/debugger/test/mochitest/browser_dbg_listtabs-03.js
devtools/client/debugger/test/mochitest/browser_dbg_multiple-windows.js
devtools/client/debugger/test/mochitest/browser_dbg_navigation.js
devtools/client/debugger/test/mochitest/browser_dbg_tabactor-01.js
devtools/client/debugger/test/mochitest/browser_dbg_tabactor-02.js
devtools/client/debugger/test/mochitest/head.js
devtools/client/framework/target.js
devtools/client/framework/test/browser_two_tabs.js
devtools/client/responsive.html/manager.js
devtools/client/responsivedesign/responsivedesign.jsm
devtools/client/webconsole/hudservice.js
devtools/server/tests/browser/browser_animation_emitMutations.js
devtools/server/tests/browser/browser_animation_getFrames.js
devtools/server/tests/browser/browser_animation_getMultipleStates.js
devtools/server/tests/browser/browser_animation_getPlayers.js
devtools/server/tests/browser/browser_animation_getProperties.js
devtools/server/tests/browser/browser_animation_getStateAfterFinished.js
devtools/server/tests/browser/browser_animation_getSubTreeAnimations.js
devtools/server/tests/browser/browser_animation_keepFinished.js
devtools/server/tests/browser/browser_animation_playPauseIframe.js
devtools/server/tests/browser/browser_animation_playPauseSeveral.js
devtools/server/tests/browser/browser_animation_playerState.js
devtools/server/tests/browser/browser_animation_reconstructState.js
devtools/server/tests/browser/browser_animation_refreshTransitions.js
devtools/server/tests/browser/browser_animation_setCurrentTime.js
devtools/server/tests/browser/browser_animation_setPlaybackRate.js
devtools/server/tests/browser/browser_animation_simple.js
devtools/server/tests/browser/browser_animation_updatedState.js
devtools/server/tests/browser/browser_directorscript_actors.js
devtools/server/tests/browser/browser_directorscript_actors_error_events.js
devtools/server/tests/browser/browser_directorscript_actors_exports.js
devtools/server/tests/browser/browser_markers-cycle-collection.js
devtools/server/tests/browser/browser_markers-docloading-01.js
devtools/server/tests/browser/browser_markers-docloading-02.js
devtools/server/tests/browser/browser_markers-docloading-03.js
devtools/server/tests/browser/browser_markers-gc.js
devtools/server/tests/browser/browser_markers-minor-gc.js
devtools/server/tests/browser/browser_markers-parse-html.js
devtools/server/tests/browser/browser_markers-styles.js
devtools/server/tests/browser/browser_markers-timestamp.js
devtools/server/tests/browser/browser_navigateEvents.js
devtools/server/tests/browser/browser_perf-allocation-data.js
devtools/server/tests/browser/browser_perf-profiler-01.js
devtools/server/tests/browser/browser_perf-profiler-02.js
devtools/server/tests/browser/browser_perf-profiler-03.js
devtools/server/tests/browser/browser_perf-realtime-markers.js
devtools/server/tests/browser/browser_perf-recording-actor-01.js
devtools/server/tests/browser/browser_perf-recording-actor-02.js
devtools/server/tests/browser/browser_perf-samples-01.js
devtools/server/tests/browser/browser_perf-samples-02.js
devtools/server/tests/browser/browser_register_actor.js
devtools/server/tests/browser/browser_stylesheets_getTextEmpty.js
devtools/server/tests/browser/browser_stylesheets_nested-iframes.js
devtools/server/tests/browser/browser_timeline.js
devtools/server/tests/browser/browser_timeline_actors.js
devtools/server/tests/browser/browser_timeline_iframes.js
devtools/server/tests/browser/head.js
devtools/server/tests/mochitest/memory-helpers.js
devtools/server/tests/mochitest/test_device.html
devtools/server/tests/mochitest/test_framerate_01.html
devtools/server/tests/mochitest/test_framerate_02.html
devtools/server/tests/mochitest/test_framerate_03.html
devtools/server/tests/mochitest/test_framerate_04.html
devtools/server/tests/mochitest/test_framerate_05.html
devtools/server/tests/mochitest/test_framerate_06.html
devtools/server/tests/mochitest/test_getProcess.html
devtools/server/tests/mochitest/test_preference.html
devtools/server/tests/mochitest/test_settings.html
devtools/server/tests/mochitest/test_setupInParentChild.html
devtools/server/tests/unit/head_dbg.js
devtools/server/tests/unit/test_add_actors.js
devtools/server/tests/unit/test_breakpoint-01.js
devtools/server/tests/unit/test_breakpoint-02.js
devtools/server/tests/unit/test_breakpoint-03.js
devtools/server/tests/unit/test_breakpoint-04.js
devtools/server/tests/unit/test_breakpoint-05.js
devtools/server/tests/unit/test_breakpoint-06.js
devtools/server/tests/unit/test_breakpoint-07.js
devtools/server/tests/unit/test_breakpoint-08.js
devtools/server/tests/unit/test_breakpoint-09.js
devtools/server/tests/unit/test_breakpoint-10.js
devtools/server/tests/unit/test_breakpoint-11.js
devtools/server/tests/unit/test_breakpoint-12.js
devtools/server/tests/unit/test_breakpoint-13.js
devtools/server/tests/unit/test_breakpoint-14.js
devtools/server/tests/unit/test_breakpoint-16.js
devtools/server/tests/unit/test_breakpoint-17.js
devtools/server/tests/unit/test_breakpoint-18.js
devtools/server/tests/unit/test_client_close.js
devtools/server/tests/unit/test_client_request.js
devtools/server/tests/unit/test_memory_footprint.js
devtools/server/tests/unit/test_objectgrips-01.js
devtools/server/tests/unit/test_objectgrips-02.js
devtools/server/tests/unit/test_objectgrips-03.js
devtools/server/tests/unit/test_objectgrips-04.js
devtools/server/tests/unit/test_objectgrips-05.js
devtools/server/tests/unit/test_objectgrips-06.js
devtools/server/tests/unit/test_objectgrips-07.js
devtools/server/tests/unit/test_objectgrips-08.js
devtools/server/tests/unit/test_objectgrips-09.js
devtools/server/tests/unit/test_profiler_activation-02.js
devtools/server/tests/unit/test_profiler_bufferstatus.js
devtools/server/tests/unit/test_profiler_data.js
devtools/server/tests/unit/test_profiler_getbufferinfo.js
devtools/server/tests/unit/test_profiler_getfeatures.js
devtools/server/tests/unit/test_profiler_getsharedlibraryinformation.js
devtools/server/tests/unit/test_protocol_async.js
devtools/server/tests/unit/test_protocol_children.js
devtools/server/tests/unit/test_protocol_longstring.js
devtools/server/tests/unit/test_protocol_simple.js
devtools/server/tests/unit/test_protocol_stack.js
devtools/server/tests/unit/test_reattach-thread.js
devtools/server/tests/unit/test_registerClient.js
devtools/server/tests/unit/test_register_actor.js
devtools/server/tests/unit/test_requestTypes.js
devtools/server/tests/unit/test_stepping-01.js
devtools/server/tests/unit/test_stepping-02.js
devtools/server/tests/unit/test_stepping-03.js
devtools/server/tests/unit/test_stepping-04.js
devtools/server/tests/unit/test_stepping-05.js
devtools/server/tests/unit/test_stepping-06.js
devtools/shared/client/main.js
devtools/shared/transport/tests/unit/head_dbg.js
devtools/shared/webconsole/test/common.js
--- a/devtools/client/debugger/test/mochitest/browser_dbg_addonactor.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_addonactor.js
@@ -23,17 +23,17 @@ function test() {
     is(aType, "browser",
       "Root actor should identify itself as a browser.");
 
     installAddon()
       .then(attachAddonActorForId.bind(null, gClient, ADDON3_ID))
       .then(attachAddonThread)
       .then(testDebugger)
       .then(testSources)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(uninstallAddon)
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
@@ -83,19 +83,13 @@ function testSources() {
 
   return deferred.promise;
 }
 
 function uninstallAddon() {
   return removeAddon(gAddon);
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gClient = null;
   gAddon = null;
   gThreadClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-01.js
@@ -26,17 +26,17 @@ function test() {
     addTab(TAB_URL)
       .then(() => attachThreadActorForUrl(gClient, TAB_URL))
       .then(setupGlobals)
       .then(pauseDebuggee)
       .then(testBreakOnAll)
       .then(testBreakOnDisabled)
       .then(testBreakOnNone)
       .then(testBreakOnClick)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function setupGlobals(aThreadClient) {
@@ -179,22 +179,16 @@ function testBreakOnClick() {
     });
 
     triggerButtonClick();
   });
 
   return deferred.promise;
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 function unexpectedListener() {
   gClient.removeListener("paused", unexpectedListener);
   ok(false, "An unexpected hidden breakpoint was hit.");
   gThreadClient.resume(testBreakOnClick);
 }
 
 function triggerInputKeyup() {
   // Make sure that the focus is not on the input box so that a focus event
--- a/devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-02.js
@@ -24,17 +24,17 @@ function test() {
     is(aType, "browser",
       "Root actor should identify itself as a browser.");
 
     addTab(TAB_URL)
       .then(() => attachThreadActorForUrl(gClient, TAB_URL))
       .then(aThreadClient => gThreadClient = aThreadClient)
       .then(pauseDebuggee)
       .then(testBreakOnClick)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function pauseDebuggee() {
@@ -94,18 +94,12 @@ function testBreakOnClick() {
   return deferred.promise;
 }
 
 function triggerButtonClick(aNodeId) {
   let button = content.document.getElementById(aNodeId);
   EventUtils.sendMouseEvent({ type: "click" }, button);
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gClient = null;
   gThreadClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-03.js
@@ -23,17 +23,17 @@ function test() {
     is(aType, "browser",
       "Root actor should identify itself as a browser.");
 
     addTab(TAB_URL)
       .then(() => attachThreadActorForUrl(gClient, TAB_URL))
       .then(aThreadClient => gThreadClient = aThreadClient)
       .then(pauseDebuggee)
       .then(testBreakOnLoad)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function pauseDebuggee() {
@@ -86,18 +86,12 @@ function testBreakOnLoad() {
   return deferred.promise;
 }
 
 function triggerButtonClick() {
   let button = content.document.querySelector("button");
   EventUtils.sendMouseEvent({ type: "click" }, button);
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gClient = null;
   gThreadClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_chrome-debugging.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_chrome-debugging.js
@@ -81,17 +81,17 @@ function onNewSource(aEvent, aPacket) {
 
     gThreadClient.removeListener("newSource", onNewSource);
     gNewChromeSource.resolve();
   }
 }
 
 function resumeAndCloseConnection() {
   let deferred = promise.defer();
-  gThreadClient.resume(() => gClient.close(deferred.resolve));
+  gThreadClient.resume(() => deferred.resolve(gClient.close()));
   return deferred.promise;
 }
 
 registerCleanupFunction(function () {
   gClient = null;
   gThreadClient = null;
   gAttached = null;
   gNewGlobal = null;
--- a/devtools/client/debugger/test/mochitest/browser_dbg_debugger-statement.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_debugger-statement.js
@@ -26,17 +26,17 @@ function test() {
 
     addTab(TAB_URL)
       .then((aTab) => {
         gTab = aTab;
         return attachTabActorForUrl(gClient, TAB_URL);
       })
       .then(testEarlyDebuggerStatement)
       .then(testDebuggerStatement)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testEarlyDebuggerStatement([aGrip, aResponse]) {
@@ -77,17 +77,11 @@ function testDebuggerStatement([aGrip, a
   });
 
   // Reach around the debugging protocol and execute the debugger statement.
   callInTab(gTab, "runDebuggerStatement");
 
   return deferred.promise;
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-01.js
@@ -26,17 +26,17 @@ function test() {
 
     addTab(TAB_URL)
       .then((aTab) => {
         gTab = aTab;
         return attachThreadActorForUrl(gClient, TAB_URL);
       })
       .then(pauseDebuggee)
       .then(testEventListeners)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function pauseDebuggee(aThreadClient) {
@@ -137,17 +137,11 @@ function testEventListeners(aThreadClien
 
       aThreadClient.resume(deferred.resolve);
     });
   });
 
   return deferred.promise;
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-02.js
@@ -27,17 +27,17 @@ function test() {
 
     addTab(TAB_URL)
       .then((aTab) => {
         gTab = aTab;
         return attachThreadActorForUrl(gClient, TAB_URL);
       })
       .then(pauseDebuggee)
       .then(testEventListeners)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function pauseDebuggee(aThreadClient) {
@@ -113,17 +113,11 @@ function testEventListeners(aThreadClien
 
       aThreadClient.resume(deferred.resolve);
     });
   });
 
   return deferred.promise;
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-03.js
@@ -27,17 +27,17 @@ function test() {
 
     addTab(TAB_URL)
       .then((aTab) => {
         gTab = aTab;
         return attachThreadActorForUrl(gClient, TAB_URL);
       })
       .then(pauseDebuggee)
       .then(testEventListeners)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function pauseDebuggee(aThreadClient) {
@@ -72,17 +72,11 @@ function testEventListeners(aThreadClien
     // and one more from the video element controls.
     is(aPacket.listeners.length, 3, "Found all event listeners.");
     aThreadClient.resume(deferred.resolve);
   });
 
   return deferred.promise;
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_globalactor.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_globalactor.js
@@ -48,14 +48,14 @@ function test() {
                 return e.startsWith(actorPrefix);
               }).length;
             }
           }
 
           is(count, 2,
             "Only two actor exists in all pools. One tab actor and one global.");
 
-          gClient.close(finish);
+          gClient.close().then(finish);
         });
       });
     });
   });
 }
--- a/devtools/client/debugger/test/mochitest/browser_dbg_listaddons.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_listaddons.js
@@ -25,17 +25,17 @@ function test() {
     is(aType, "browser",
       "Root actor should identify itself as a browser.");
 
     promise.resolve(null)
       .then(testFirstAddon)
       .then(testSecondAddon)
       .then(testRemoveFirstAddon)
       .then(testRemoveSecondAddon)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testFirstAddon() {
@@ -98,21 +98,15 @@ function testRemoveSecondAddon() {
   return removeAddon(gAddon2).then(() => {
     return getAddonActorForId(gClient, ADDON2_ID).then(aGrip => {
       ok(addonListChanged, "Should be notified that list of addons changed.");
       ok(!aGrip, "Shouldn't find a addon actor for the second addon anymore.");
     });
   });
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gAddon1 = null;
   gAddon1Actor = null;
   gAddon2 = null;
   gAddon2Actor = null;
   gClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_listtabs-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_listtabs-01.js
@@ -24,17 +24,17 @@ function test() {
     is(aType, "browser",
       "Root actor should identify itself as a browser.");
 
     promise.resolve(null)
       .then(testFirstTab)
       .then(testSecondTab)
       .then(testRemoveTab)
       .then(testAttachRemovedTab)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testFirstTab() {
@@ -84,21 +84,15 @@ function testAttachRemovedTab() {
          "Connection is gone since the tab was removed.");
       deferred.resolve();
     });
 
     return deferred.promise;
   });
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gTab1 = null;
   gTab1Actor = null;
   gTab2 = null;
   gTab2Actor = null;
   gClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_listtabs-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_listtabs-03.js
@@ -42,26 +42,20 @@ function test() {
     is(newGrip.actor, tabGrip.actor, "Should have the same actor for the same tab");
 
     response = yield gClient.request({ to: tabGrip.actor, type: "attach" });
     is(response.type, "tabAttached", "Should have attached");
     response = yield gClient.request({ to: tabGrip.actor, type: "detach" });
     is(response.type, "detached", "Should have detached");
 
     yield removeTab(tab);
-    yield closeConnection();
+    yield gClient.close();
     finish();
   }));
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gTab1 = null;
   gTab1Actor = null;
   gTab2 = null;
   gTab2Actor = null;
   gClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_multiple-windows.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_multiple-windows.js
@@ -28,17 +28,17 @@ function test() {
 
     promise.resolve(null)
       .then(() => addTab(TAB1_URL))
       .then(testFirstTab)
       .then(() => addWindow(TAB2_URL))
       .then(testNewWindow)
       .then(testFocusFirst)
       .then(testRemoveTab)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testFirstTab(aTab) {
@@ -153,19 +153,13 @@ function continue_remove_tab(deferred)
 
     is(aResponse.selected, 0,
       "The original tab is selected.");
 
     deferred.resolve();
   });
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gNewTab = null;
   gNewWindow = null;
   gClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_navigation.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_navigation.js
@@ -58,17 +58,17 @@ function testNavigate([aGrip, aResponse]
 }
 
 function testDetach(aActor) {
   let deferred = promise.defer();
 
   gClient.addOneTimeListener("tabDetached", (aType, aPacket) => {
     ok(true, "Got a tab detach notification.");
     is(aPacket.from, aActor, "tab detach message comes from the expected actor");
-    gClient.close(deferred.resolve);
+    deferred.resolve(gClient.close());
   });
 
   removeTab(gBrowser.selectedTab);
   return deferred.promise;
 }
 
 registerCleanupFunction(function () {
   gClient = null;
--- a/devtools/client/debugger/test/mochitest/browser_dbg_tabactor-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_tabactor-01.js
@@ -25,17 +25,17 @@ function test() {
   gClient.connect().then(([aType, aTraits]) => {
     is(aType, "browser",
       "Root actor should identify itself as a browser.");
 
     addTab(TAB_URL)
       .then(() => attachTabActorForUrl(gClient, TAB_URL))
       .then(testTabActor)
       .then(closeTab)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testTabActor([aGrip, aResponse]) {
@@ -55,17 +55,11 @@ function testTabActor([aGrip, aResponse]
 
   return deferred.promise;
 }
 
 function closeTab() {
   return removeTab(gBrowser.selectedTab);
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_tabactor-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_tabactor-02.js
@@ -25,17 +25,17 @@ function test() {
   gClient.connect().then(([aType, aTraits]) => {
     is(aType, "browser",
       "Root actor should identify itself as a browser.");
 
     addTab(TAB_URL)
       .then(() => attachTabActorForUrl(gClient, TAB_URL))
       .then(testTabActor)
       .then(closeTab)
-      .then(closeConnection)
+      .then(() => gClient.close())
       .then(finish)
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testTabActor([aGrip, aResponse]) {
@@ -69,17 +69,11 @@ function closeTab(aTestActor) {
       is(e.message, "'ping' request packet has no destination.", "testTabActor1 went away.");
       deferred.resolve();
     }
 
     return deferred.promise;
   });
 }
 
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
 registerCleanupFunction(function () {
   gClient = null;
 });
--- a/devtools/client/debugger/test/mochitest/head.js
+++ b/devtools/client/debugger/test/mochitest/head.js
@@ -657,19 +657,17 @@ AddonDebugger.prototype = {
     this.debuggerPanel = toolbox.getCurrentPanel();
     yield waitForSourceShown(this.debuggerPanel, "");
 
     prepareDebugger(this.debuggerPanel);
     yield this._attachConsole();
   }),
 
   destroy: Task.async(function* () {
-    let deferred = promise.defer();
-    this.client.close(deferred.resolve);
-    yield deferred.promise;
+    yield this.client.close();
     yield this.debuggerPanel._toolbox.destroy();
     this.frame.remove();
     window.removeEventListener("message", this._onMessage);
   }),
 
   _attachConsole: function () {
     let deferred = promise.defer();
     this.client.attachConsole(this.target.form.consoleActor, ["ConsoleAPI"], (aResponse, aWebConsoleClient) => {
@@ -1073,21 +1071,17 @@ function generateMouseClickInTab(tab, pa
 
 function connect(client) {
   info("Connecting client.");
   return client.connect();
 }
 
 function close(client) {
   info("Waiting for client to close.\n");
-  return new Promise(function (resolve) {
-    client.close(() => {
-      resolve();
-    });
-  });
+  return client.close();
 }
 
 function listTabs(client) {
   info("Listing tabs.");
   return client.listTabs();
 }
 
 function findTab(tabs, url) {
--- a/devtools/client/framework/target.js
+++ b/devtools/client/framework/target.js
@@ -581,17 +581,17 @@ TabTarget.prototype = {
     } else if (this._client) {
       // If, on the other hand, this target was remoted, the promise will be
       // resolved after the remote connection is closed.
       this._teardownRemoteListeners();
 
       if (this.isLocalTab) {
         // We started with a local tab and created the client ourselves, so we
         // should close it.
-        this._client.close(cleanupAndResolve);
+        this._client.close().then(cleanupAndResolve);
       } else if (this.activeTab) {
         // The client was handed to us, so we are not responsible for closing
         // it. We just need to detach from the tab, if already attached.
         // |detach| may fail if the connection is already dead, so proceed with
         // cleanup directly after this.
         this.activeTab.detach();
         cleanupAndResolve();
       } else {
--- a/devtools/client/framework/test/browser_two_tabs.js
+++ b/devtools/client/framework/test/browser_two_tabs.js
@@ -141,12 +141,12 @@ function checkFirstTabActor() {
   });
 }
 
 function cleanup() {
   let container = gBrowser.tabContainer;
   container.addEventListener("TabClose", function onTabClose() {
     container.removeEventListener("TabClose", onTabClose);
 
-    gClient.close(finish);
+    gClient.close().then(finish);
   });
   gBrowser.removeTab(gTab1);
 }
--- a/devtools/client/responsive.html/manager.js
+++ b/devtools/client/responsive.html/manager.js
@@ -370,23 +370,21 @@ ResponsiveUI.prototype = {
     let swap = this.swap;
     this.browserWindow = null;
     this.tab = null;
     this.inited = null;
     this.toolWindow = null;
     this.swap = null;
 
     // Close the debugger client used to speak with emulation actor
-    let clientClosed = new Promise((resolve, reject) => {
-      this.client.close(resolve);
-      this.client = this.emulationFront = null;
-    });
+    let clientClosed = this.client.close();
     if (!isTabClosing) {
       yield clientClosed;
     }
+    this.client = this.emulationFront = null;
 
     // Undo the swap and return the content back to a normal tab
     swap.stop();
 
     this.destroyed = true;
 
     return true;
   }),
--- a/devtools/client/responsivedesign/responsivedesign.jsm
+++ b/devtools/client/responsivedesign/responsivedesign.jsm
@@ -383,20 +383,18 @@ ResponsiveUI.prototype = {
     this.container.removeAttribute("responsivemode");
     this.stack.removeAttribute("responsivemode");
 
     ActiveTabs.delete(this.tab);
     if (this.touchEventSimulator) {
       this.touchEventSimulator.stop();
     }
 
-    yield new Promise((resolve, reject) => {
-      this.client.close(resolve);
-      this.client = this.emulationFront = null;
-    });
+    yield this.client.close();
+    this.client = this.emulationFront = null;
 
     this._telemetry.toolClosed("responsive");
 
     if (this.tab.linkedBrowser.messageManager) {
       let stopped = this.waitForMessage("ResponsiveMode:Stop:Done");
       this.tab.linkedBrowser.messageManager.sendAsyncMessage("ResponsiveMode:Stop");
       yield stopped;
     }
--- a/devtools/client/webconsole/hudservice.js
+++ b/devtools/client/webconsole/hudservice.js
@@ -693,17 +693,17 @@ BrowserConsole.prototype = extend(WebCon
     }
 
     this._telemetry.toolClosed("browserconsole");
 
     this._bc_destroyer = promise.defer();
 
     let chromeWindow = this.chromeWindow;
     this.$destroy().then(() =>
-      this.target.client.close(() => {
+      this.target.client.close().then(() => {
         HUDService._browserConsoleID = null;
         chromeWindow.close();
         this._bc_destroyer.resolve(null);
       }));
 
     return this._bc_destroyer.promise;
   },
 });
--- a/devtools/server/tests/browser/browser_animation_emitMutations.js
+++ b/devtools/server/tests/browser/browser_animation_emitMutations.js
@@ -52,11 +52,11 @@ add_task(function* () {
   ok(true, "The mutations event was emitted");
   is(changes.length, 2, "There are 2 changes in the mutation event");
   ok(changes.every(({type}) => type === "removed"), "Both are removals");
   ok(changes[0].player === p1 || changes[0].player === p2,
     "The first removed player was one of the previously added players");
   ok(changes[1].player === p1 || changes[1].player === p2,
     "The second removed player was one of the previously added players");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_animation_getFrames.js
+++ b/devtools/server/tests/browser/browser_animation_getFrames.js
@@ -22,11 +22,11 @@ add_task(function* () {
   let frames = yield player.getFrames();
   is(frames.length, 2, "The correct number of keyframes was retrieved");
   ok(frames[0].transform, "Frame 0 has the transform property");
   ok(frames[1].transform, "Frame 1 has the transform property");
   // Note that we don't really test the content of the frame object here on
   // purpose. This object comes straight out of the web animations API
   // unmodified.
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_animation_getMultipleStates.js
+++ b/devtools/server/tests/browser/browser_animation_getMultipleStates.js
@@ -8,17 +8,17 @@
 // multiple animations.
 
 add_task(function* () {
   let {client, walker, animations} =
     yield initAnimationsFrontForUrl(MAIN_DOMAIN + "animation.html");
 
   yield playerHasAnInitialState(walker, animations);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 function* playerHasAnInitialState(walker, animations) {
   let state = yield getAnimationStateForNode(walker, animations,
     ".delayed-multiple-animations", 0);
 
   ok(state.duration, 50000,
--- a/devtools/server/tests/browser/browser_animation_getPlayers.js
+++ b/devtools/server/tests/browser/browser_animation_getPlayers.js
@@ -8,17 +8,17 @@
 
 add_task(function* () {
   let {client, walker, animations} =
     yield initAnimationsFrontForUrl(MAIN_DOMAIN + "animation.html");
 
   yield theRightNumberOfPlayersIsReturned(walker, animations);
   yield playersCanBePausedAndResumed(walker, animations);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 function* theRightNumberOfPlayersIsReturned(walker, animations) {
   let node = yield walker.querySelector(walker.rootNode, ".not-animated");
   let players = yield animations.getAnimationPlayersForNode(node);
   is(players.length, 0,
      "0 players were returned for the unanimated node");
--- a/devtools/server/tests/browser/browser_animation_getProperties.js
+++ b/devtools/server/tests/browser/browser_animation_getProperties.js
@@ -26,11 +26,11 @@ add_task(function* () {
 
   is(propertyObject.values.length, 2,
     "The correct number of property values was retrieved");
 
   // Note that we don't really test the content of the frame object here on
   // purpose. This object comes straight out of the web animations API
   // unmodified.
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_animation_getStateAfterFinished.js
+++ b/devtools/server/tests/browser/browser_animation_getStateAfterFinished.js
@@ -45,11 +45,11 @@ add_task(function* () {
 
   is(players[1].state.duration, 300000,
      "The duration of the second animation is correct");
   is(players[1].state.delay, 1000,
      "The delay of the second animation is correct");
   is(players[1].state.iterationCount, 100,
      "The iterationCount of the second animation is correct");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_animation_getSubTreeAnimations.js
+++ b/devtools/server/tests/browser/browser_animation_getSubTreeAnimations.js
@@ -28,11 +28,11 @@ add_task(function* () {
   players = yield animations.getAnimationPlayersForNode(frameBody);
 
   // Testing for a hard-coded number of animations here would intermittently
   // fail depending on how fast or slow the test is (indeed, the test page
   // contains short transitions, and delayed animations). So just make sure we
   // at least have the infinitely running animations.
   ok(players.length >= 4, "All subtree animations were retrieved");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_animation_keepFinished.js
+++ b/devtools/server/tests/browser/browser_animation_keepFinished.js
@@ -38,17 +38,17 @@ add_task(function* () {
   players = yield animations.getAnimationPlayersForNode(node);
   is(players.length, 0, "The added animation is surely finished");
 
   is(reportedMutations.length, 1, "Only one mutation was reported");
   is(reportedMutations[0].type, "added", "The mutation was an addition");
 
   animations.off("mutations", onMutations);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 function wait(ms) {
   return new Promise(resolve => {
     setTimeout(resolve, ms);
   });
 }
--- a/devtools/server/tests/browser/browser_animation_playPauseIframe.js
+++ b/devtools/server/tests/browser/browser_animation_playPauseIframe.js
@@ -26,17 +26,17 @@ add_task(function* () {
   yield checkState(animations, nodeInFrame1, "paused");
   yield checkState(animations, nodeInFrame2, "paused");
 
   info("Play all animations in the test document");
   yield animations.playAll();
   yield checkState(animations, nodeInFrame1, "running");
   yield checkState(animations, nodeInFrame2, "running");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 function* checkState(animations, nodeFront, playState) {
   info("Getting the AnimationPlayerFront for the test node");
   let [player] = yield animations.getAnimationPlayersForNode(nodeFront);
   yield player.ready;
   let state = yield player.getCurrentState();
--- a/devtools/server/tests/browser/browser_animation_playPauseSeveral.js
+++ b/devtools/server/tests/browser/browser_animation_playPauseSeveral.js
@@ -59,17 +59,17 @@ add_task(function* () {
   yield animations.toggleSeveral([players[0]], false);
   state1 = yield players[0].getCurrentState();
   is(state1.playState, "running",
     "The playState of the first player is running");
   state2 = yield players[1].getCurrentState();
   is(state2.playState, "running",
     "The playState of the second player is running");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 function* checkStates(walker, animations, selectors, playState) {
   info("Checking the playState of all the nodes that have infinite running " +
        "animations");
 
   for (let selector of selectors) {
--- a/devtools/server/tests/browser/browser_animation_playerState.js
+++ b/devtools/server/tests/browser/browser_animation_playerState.js
@@ -8,17 +8,17 @@
 
 add_task(function* () {
   let {client, walker, animations} =
     yield initAnimationsFrontForUrl(MAIN_DOMAIN + "animation.html");
 
   yield playerHasAnInitialState(walker, animations);
   yield playerStateIsCorrect(walker, animations);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 function* playerHasAnInitialState(walker, animations) {
   let node = yield walker.querySelector(walker.rootNode, ".simple-animation");
   let [player] = yield animations.getAnimationPlayersForNode(node);
 
   ok(player.initialState, "The player front has an initial state");
--- a/devtools/server/tests/browser/browser_animation_reconstructState.js
+++ b/devtools/server/tests/browser/browser_animation_reconstructState.js
@@ -8,17 +8,17 @@
 // state that change, the front reconstructs the whole state everytime.
 
 add_task(function* () {
   let {client, walker, animations} =
     yield initAnimationsFrontForUrl(MAIN_DOMAIN + "animation.html");
 
   yield playerHasCompleteStateAtAllTimes(walker, animations);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 function* playerHasCompleteStateAtAllTimes(walker, animations) {
   let node = yield walker.querySelector(walker.rootNode, ".simple-animation");
   let [player] = yield animations.getAnimationPlayersForNode(node);
   yield player.ready();
 
--- a/devtools/server/tests/browser/browser_animation_refreshTransitions.js
+++ b/devtools/server/tests/browser/browser_animation_refreshTransitions.js
@@ -39,17 +39,17 @@ add_task(function* () {
   reportedMutations = yield onMutations;
 
   is(reportedMutations.length, 4, "4 new mutation events were received");
   is(reportedMutations.filter(m => m.type === "removed").length, 2,
     "2 'removed' events were sent (for the old transitions)");
   is(reportedMutations.filter(m => m.type === "added").length, 2,
     "2 'added' events were sent (for the new transitions)");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 function expectMutationEvents(animationsFront, nbOfEvents) {
   return new Promise(resolve => {
     let reportedMutations = [];
     function onMutations(mutations) {
       reportedMutations = [...reportedMutations, ...mutations];
--- a/devtools/server/tests/browser/browser_animation_setCurrentTime.js
+++ b/devtools/server/tests/browser/browser_animation_setCurrentTime.js
@@ -9,17 +9,17 @@
 
 add_task(function* () {
   let {client, walker, animations} =
     yield initAnimationsFrontForUrl(MAIN_DOMAIN + "animation.html");
 
   yield testSetCurrentTime(walker, animations);
   yield testSetCurrentTimes(walker, animations);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 function* testSetCurrentTime(walker, animations) {
   info("Retrieve an animated node");
   let node = yield walker.querySelector(walker.rootNode, ".simple-animation");
 
   info("Retrieve the animation player for the node");
--- a/devtools/server/tests/browser/browser_animation_setPlaybackRate.js
+++ b/devtools/server/tests/browser/browser_animation_setPlaybackRate.js
@@ -41,11 +41,11 @@ add_task(function* () {
   yield animations.setPlaybackRates(players, .5);
 
   info("Query their states and check they are correct");
   for (let player of players) {
     let state = yield player.getCurrentState();
     is(state.playbackRate, .5, "The playbackRate was updated");
   }
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_animation_simple.js
+++ b/devtools/server/tests/browser/browser_animation_simple.js
@@ -25,11 +25,11 @@ add_task(function* () {
   }
   ok(didThrow, "An exception was thrown for a missing NodeActor");
 
   let invalidNode = yield walker.querySelector(walker.rootNode, "title");
   let players = yield animations.getAnimationPlayersForNode(invalidNode);
   ok(Array.isArray(players), "An array of players was returned");
   is(players.length, 0, "0 players have been returned for the invalid node");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_animation_updatedState.js
+++ b/devtools/server/tests/browser/browser_animation_updatedState.js
@@ -7,17 +7,17 @@
 // Check the animation player's updated state
 
 add_task(function* () {
   let {client, walker, animations} =
     yield initAnimationsFrontForUrl(MAIN_DOMAIN + "animation.html");
 
   yield playStateIsUpdatedDynamically(walker, animations);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 function* playStateIsUpdatedDynamically(walker, animations) {
   info("Getting the test node (which runs a very long animation)");
   // The animation lasts for 100s, to avoid intermittents.
   let node = yield walker.querySelector(walker.rootNode, ".long-animation");
 
--- a/devtools/server/tests/browser/browser_directorscript_actors.js
+++ b/devtools/server/tests/browser/browser_directorscript_actors.js
@@ -18,17 +18,17 @@ add_task(function* () {
   DirectorRegistry.clear();
   let directorManager = DirectorManagerFront(client, form);
 
   yield testDirectorScriptAttachEventAttributes(directorManager);
   yield testDirectorScriptMessagePort(directorManager);
   yield testDirectorScriptWindowEval(directorManager);
   yield testDirectorScriptUnloadOnDetach(directorManager);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
   DirectorRegistry.clear();
 });
 
 function* testDirectorScriptAttachEventAttributes(directorManager) {
   let attachEvent = yield installAndEnableDirectorScript(directorManager, {
     scriptId: "testDirectorScript_attachEventAttributes",
     scriptCode: "(" + (function () {
--- a/devtools/server/tests/browser/browser_directorscript_actors_error_events.js
+++ b/devtools/server/tests/browser/browser_directorscript_actors_error_events.js
@@ -18,17 +18,17 @@ add_task(function* () {
   DirectorRegistry.clear();
   let directorManager = DirectorManagerFront(client, form);
 
   yield testErrorOnRequire(directorManager);
   yield testErrorOnEvaluate(directorManager);
   yield testErrorOnAttach(directorManager);
   yield testErrorOnDetach(directorManager);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
   DirectorRegistry.clear();
 });
 
 function* testErrorOnRequire(directorManager) {
   // director script require method should raise a "not implemented" exception
   let errorOnRequire = yield installAndEnableDirectorScript(directorManager, {
     scriptId: "testDirectorScript_errorOnRequire",
--- a/devtools/server/tests/browser/browser_directorscript_actors_exports.js
+++ b/devtools/server/tests/browser/browser_directorscript_actors_exports.js
@@ -52,17 +52,17 @@ add_task(function* () {
     scriptOptions: {
       attachMethod: "attach"
     }
   });
   let { message } = errorUndefinedAttachMethod;
   ok(!!message, "testDirectorScript_undefinedAttachMethod error event received");
   assertIsDirectorScriptError(errorUndefinedAttachMethod);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
   DirectorRegistry.clear();
 });
 
 function assertIsDirectorScriptError(error) {
   ok(!!error.message, "errors should contain a message");
   ok(!!error.stack, "errors should contain a stack trace");
   ok(!!error.fileName, "errors should contain a fileName");
--- a/devtools/server/tests/browser/browser_markers-cycle-collection.js
+++ b/devtools/server/tests/browser/browser_markers-cycle-collection.js
@@ -23,11 +23,11 @@ add_task(function* () {
   let rec = yield front.startRecording({ withMarkers: true });
 
   let markers = yield waitForMarkerType(front, ["nsCycleCollector::Collect", "nsCycleCollector::ForgetSkippable"]);
   yield front.stopRecording(rec);
 
   ok(markers.some(m => m.name === "nsCycleCollector::Collect"), "got some nsCycleCollector::Collect markers");
   ok(markers.some(m => m.name === "nsCycleCollector::ForgetSkippable"), "got some nsCycleCollector::Collect markers");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_markers-docloading-01.js
+++ b/devtools/server/tests/browser/browser_markers-docloading-01.js
@@ -27,11 +27,11 @@ add_task(function* () {
   yield waitForMarkerType(front, MARKER_NAMES, () => true, e => e, "markers");
   yield front.stop(rec);
 
   ok(true, "Found the required marker names.");
 
   // Wait some more time to make sure the 'doc-loading' events never get fired.
   yield DevToolsUtils.waitForTime(1000);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_markers-docloading-02.js
+++ b/devtools/server/tests/browser/browser_markers-docloading-02.js
@@ -25,11 +25,11 @@ add_task(function* () {
 
   ok(true, "At least one doc-loading event got fired.");
 
   yield waitForMarkerType(front, MARKER_NAMES, () => true, e => e, "markers");
   yield front.stop(rec);
 
   ok(true, "Found the required marker names.");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_markers-docloading-03.js
+++ b/devtools/server/tests/browser/browser_markers-docloading-03.js
@@ -29,11 +29,11 @@ add_task(function* () {
 
   ok(true, "At least one doc-loading event got fired.");
 
   yield front.stop(rec);
 
   // Wait some more time to make sure the 'doc-loading' markers never get fired.
   yield DevToolsUtils.waitForTime(1000);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_markers-gc.js
+++ b/devtools/server/tests/browser/browser_markers-gc.js
@@ -40,11 +40,11 @@ add_task(function* () {
       ok(false, `markers must be in order. ${current.name} marker has later start time (${current.start}) thanprevious: ${previousStart}`);
       ordered = false;
     }
     return current.start;
   });
 
   is(ordered, true, "All GC and non-GC markers are in order by start time.");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_markers-minor-gc.js
+++ b/devtools/server/tests/browser/browser_markers-minor-gc.js
@@ -22,11 +22,11 @@ add_task(function* () {
   let rec = yield front.startRecording({ withMarkers: true });
 
   let markers = yield waitForMarkerType(front, ["MinorGC"]);
   yield front.stopRecording(rec);
 
   ok(markers.some(m => m.name === "MinorGC" && m.causeName),
      "got some MinorGC markers");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_markers-parse-html.js
+++ b/devtools/server/tests/browser/browser_markers-parse-html.js
@@ -19,11 +19,11 @@ add_task(function* () {
   yield front.connect();
   let rec = yield front.startRecording({ withMarkers: true });
 
   let markers = yield waitForMarkerType(front, MARKER_NAME);
   yield front.stopRecording(rec);
 
   ok(markers.some(m => m.name === MARKER_NAME), `got some ${MARKER_NAME} markers`);
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_markers-styles.js
+++ b/devtools/server/tests/browser/browser_markers-styles.js
@@ -24,11 +24,11 @@ add_task(function* () {
   });
 
   yield front.stopRecording(rec);
 
   ok(markers.some(m => m.name === MARKER_NAME), `got some ${MARKER_NAME} markers`);
   ok(markers.some(({restyleHint}) => restyleHint != void 0),
     "Some markers have a restyleHint.");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_markers-timestamp.js
+++ b/devtools/server/tests/browser/browser_markers-timestamp.js
@@ -33,11 +33,11 @@ add_task(function* () {
   ok(markers.length === 2, "found 2 TimeStamp markers");
   ok(markers.every(({start, end}) => typeof start === "number" && start === end),
     "All markers have equal start and end times");
   is(markers[0].causeName, void 0, "Unlabeled timestamps have an empty causeName");
   is(markers[1].causeName, "myLabel", "Labeled timestamps have correct causeName");
 
   pmmClearFrameScripts();
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_navigateEvents.js
+++ b/devtools/server/tests/browser/browser_navigateEvents.js
@@ -147,14 +147,14 @@ function test() {
 
   });
 }
 
 function cleanup() {
   let browser = gBrowser.selectedBrowser;
   browser.removeEventListener("DOMContentLoaded", onDOMContentLoaded);
   browser.removeEventListener("load", onLoad);
-  client.close(function () {
+  client.close().then(function () {
     Services.obs.addObserver(httpObserver, "http-on-modify-request", false);
     DebuggerServer.destroy();
     finish();
   });
 }
--- a/devtools/server/tests/browser/browser_perf-allocation-data.js
+++ b/devtools/server/tests/browser/browser_perf-allocation-data.js
@@ -28,11 +28,11 @@ add_task(function* () {
 
   let { frames, timestamps, sizes, sites } = rec.getAllocations();
 
   is(timestamps.length, sizes.length, "we have the same amount of timestamps and sizes");
   ok(timestamps.every(time => time > 0 && typeof time === "number"), "all timestamps have numeric values");
   ok(sizes.every(n => n > 0 && typeof n === "number"), "all sizes are positive numbers");
 
   yield front.destroy();
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_perf-profiler-01.js
+++ b/devtools/server/tests/browser/browser_perf-profiler-01.js
@@ -31,15 +31,15 @@ add_task(function* () {
     "The built-in profiler module should still be active (1).");
 
   rec = yield front.startRecording();
   yield front.stopRecording(rec);
   ok((yield pmmIsProfilerActive()),
     "The built-in profiler module should still be active (2).");
 
   yield front.destroy();
-  yield closeDebuggerClient(client);
+  yield client.close();
 
   ok(!(yield pmmIsProfilerActive()),
     "The built-in profiler module should no longer be active.");
 
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_perf-profiler-02.js
+++ b/devtools/server/tests/browser/browser_perf-profiler-02.js
@@ -27,20 +27,20 @@ add_task(function* () {
   let secondFront = PerformanceFront(client2, form2);
   yield secondFront.connect();
   pmmLoadFrameScripts(gBrowser);
 
   yield secondFront.startRecording();
 
   // Manually teardown the tabs so we can check profiler status
   yield secondFront.destroy();
-  yield closeDebuggerClient(client2);
+  yield client2.close();
   ok((yield pmmIsProfilerActive()),
     "The built-in profiler module should still be active.");
 
   yield firstFront.destroy();
-  yield closeDebuggerClient(client);
+  yield client.close();
   ok(!(yield pmmIsProfilerActive()),
     "The built-in profiler module should no longer be active.");
 
   gBrowser.removeCurrentTab();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_perf-profiler-03.js
+++ b/devtools/server/tests/browser/browser_perf-profiler-03.js
@@ -33,22 +33,22 @@ add_task(function* () {
 
   yield addTab(MAIN_DOMAIN + "doc_perf.html");
   let client2 = new DebuggerClient(DebuggerServer.connectPipe());
   let form2 = yield connectDebuggerClient(client2);
   let secondFront = PerformanceFront(client2, form2);
   yield secondFront.connect();
 
   yield secondFront.destroy();
-  yield closeDebuggerClient(client2);
+  yield client2.close();
   ok((yield pmmIsProfilerActive()),
     "The built-in profiler module should still be active.");
 
   yield firstFront.destroy();
-  yield closeDebuggerClient(client);
+  yield client.close();
   ok(!(yield pmmIsProfilerActive()),
     "The built-in profiler module should have been automatically stopped.");
 
   pmmClearFrameScripts();
 
   gBrowser.removeCurrentTab();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_perf-realtime-markers.js
+++ b/devtools/server/tests/browser/browser_perf-realtime-markers.js
@@ -39,17 +39,17 @@ add_task(function* () {
   yield front.stopRecording(rec);
   front.off("timeline-data", handler);
 
   is(counters.markers.length, 1, "one marker event fired.");
   is(counters.memory.length, 3, "three memory events fired.");
   is(counters.ticks.length, 3, "three ticks events fired.");
 
   yield front.destroy();
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 
   function handler(name, data) {
     if (name === "markers") {
       if (counters.markers.length >= 1) { return; }
       ok(data.markers[0].start, "received atleast one marker with `start`");
       ok(data.markers[0].end, "received atleast one marker with `end`");
       ok(data.markers[0].name, "received atleast one marker with `name`");
--- a/devtools/server/tests/browser/browser_perf-recording-actor-01.js
+++ b/devtools/server/tests/browser/browser_perf-recording-actor-01.js
@@ -63,17 +63,17 @@ add_task(function* () {
   ok(importedModel.isCompleted(), "All imported recordings should be completed");
   ok(!importedModel.isRecording(), "All imported recordings should not be recording");
   ok(importedModel.isImported(), "All imported recordings should be considerd imported");
 
   checkSystemInfo(importedModel, "Host");
   checkSystemInfo(importedModel, "Client");
 
   yield front.destroy();
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 function checkSystemInfo(recording, type) {
   let data = recording[`get${type}SystemInfo`]();
   for (let field of ["appid", "apptype", "vendor", "name", "version"]) {
     ok(data[field], `get${type}SystemInfo() has ${field} property`);
   }
--- a/devtools/server/tests/browser/browser_perf-recording-actor-02.js
+++ b/devtools/server/tests/browser/browser_perf-recording-actor-02.js
@@ -44,11 +44,11 @@ add_task(function* () {
 
   ok(checkCount >= 1, "atleast 1 event were fired until the buffer was filled");
   is(lastBufferStatus, 1, "buffer usage cannot surpass 100%");
   yield front.stopRecording(model);
 
   is(front.getBufferUsageForRecording(model), null, "buffer usage should be null when no longer recording.");
 
   yield front.destroy();
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_perf-samples-01.js
+++ b/devtools/server/tests/browser/browser_perf-samples-01.js
@@ -53,11 +53,11 @@ add_task(function* () {
     "The second recorded sample times were normalized.");
   ok(secondRecordingSamples[0][TIME_SLOT] > 0,
     "The second recorded sample times were normalized correctly.");
   ok(!secondRecordingSamples.find(e => e[TIME_SLOT] + secondRecordingStartTime <= firstRecording.getDuration()),
     "There should be no samples from the first recording in the second one, " +
     "even though the total number of frames did not overflow.");
 
   yield front.destroy();
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_perf-samples-02.js
+++ b/devtools/server/tests/browser/browser_perf-samples-02.js
@@ -40,17 +40,17 @@ add_task(function* () {
       }
     }
   }
 
   ok(sampleCount > 0,
     "At least some samples have been iterated over, checking for root nodes.");
 
   yield front.destroy();
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 /**
  * Inflate a particular sample's stack and return an array of strings.
  */
 function getInflatedStackLocations(thread, sample) {
   let stackTable = thread.stackTable;
--- a/devtools/server/tests/browser/browser_register_actor.js
+++ b/devtools/server/tests/browser/browser_register_actor.js
@@ -27,17 +27,17 @@ function test() {
           var tab = response.tabs[response.selected];
           ok(!!tab.helloActor, "Hello actor must exist");
 
           // Make sure actor's state is maintained across listTabs requests.
           checkActorState(tab.helloActor, () => {
 
             // Clean up
             actorFront.unregister().then(() => {
-              gClient.close(() => {
+              gClient.close().then(() => {
                 DebuggerServer.destroy();
                 gClient = null;
                 finish();
               });
             });
           });
         });
       });
--- a/devtools/server/tests/browser/browser_stylesheets_getTextEmpty.js
+++ b/devtools/server/tests/browser/browser_stylesheets_getTextEmpty.js
@@ -31,10 +31,10 @@ add_task(function* () {
      "getStyleSheets() returned the correct number of sheets");
 
   let sheet = sheets[0];
   yield sheet.update("", false);
   let longStr = yield sheet.getText();
   let source = yield longStr.string();
   is(source, "", "text is empty");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
 });
--- a/devtools/server/tests/browser/browser_stylesheets_nested-iframes.js
+++ b/devtools/server/tests/browser/browser_stylesheets_nested-iframes.js
@@ -29,10 +29,10 @@ add_task(function* () {
 
   // Bug 285395 limits the number of nested iframes to 10. There's one sheet per
   // frame so we should get 10 sheets. However, the limit might change in the
   // future so it's better not to rely on the limit. Asserting > 2 ensures that
   // the test page is actually loading nested iframes and this test is doing
   // something sensible (if we got this far, the test has served its purpose).
   ok(sheets.length > 2, sheets.length + " sheets found (expected 3 or more).");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
 });
--- a/devtools/server/tests/browser/browser_timeline.js
+++ b/devtools/server/tests/browser/browser_timeline.js
@@ -53,11 +53,11 @@ add_task(function* () {
 
   ok(markers.length > 0, "markers were returned");
 
   yield front.stop();
 
   isActive = yield front.isRecording();
   ok(!isActive, "Not recording after stop()");
 
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
--- a/devtools/server/tests/browser/browser_timeline_actors.js
+++ b/devtools/server/tests/browser/browser_timeline_actors.js
@@ -41,17 +41,17 @@ add_task(function* () {
 
   ok((yield waitUntil(() => updatedMemory > 1)),
     "Some memory measurements were emitted.");
   ok((yield waitUntil(() => updatedTicks > 1)),
     "Some refresh driver ticks were emitted.");
 
   info("Stop timeline marker recording");
   yield front.stop();
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 /**
  * Waits until a predicate returns true.
  *
  * @param function predicate
  *        Invoked once in a while until it returns true.
--- a/devtools/server/tests/browser/browser_timeline_iframes.js
+++ b/devtools/server/tests/browser/browser_timeline_iframes.js
@@ -26,16 +26,16 @@ add_task(function* () {
   for (let i = 0; i < 3; i++) {
     yield wait(300); // That's the time the child frame waits before changing styles.
     let markers = yield once(front, "markers");
     ok(markers.length, "Markers were received for operations in the child frame");
   }
 
   info("Stop timeline marker recording");
   yield front.stop();
-  yield closeDebuggerClient(client);
+  yield client.close();
   gBrowser.removeCurrentTab();
 });
 
 function wait(ms) {
   return new Promise(resolve =>
     setTimeout(resolve, ms));
 }
--- a/devtools/server/tests/browser/head.js
+++ b/devtools/server/tests/browser/head.js
@@ -78,25 +78,16 @@ function connectDebuggerClient(client) {
   return client.connect()
     .then(() => client.listTabs())
     .then(tabs => {
       return tabs.tabs[tabs.selected];
     });
 }
 
 /**
- * Close a debugger client's connection.
- * @param {DebuggerClient}
- * @return {Promise} Resolves when the connection is closed.
- */
-function closeDebuggerClient(client) {
-  return new Promise(resolve => client.close(resolve));
-}
-
-/**
  * Wait for eventName on target.
  * @param {Object} target An observable object that either supports on/off or
  * addEventListener/removeEventListener
  * @param {String} eventName
  * @param {Boolean} useCapture Optional, for addEventListener/removeEventListener
  * @return A promise that resolves when the event has been handled
  */
 function once(target, eventName, useCapture = false) {
--- a/devtools/server/tests/mochitest/memory-helpers.js
+++ b/devtools/server/tests/mochitest/memory-helpers.js
@@ -27,17 +27,17 @@ function startServerAndGetSelectedTabMem
       var form = response.tabs[response.selected];
       var memory = MemoryFront(client, form, response);
 
       return { memory, client };
     });
 }
 
 function destroyServerAndFinish(client) {
-  client.close(() => {
+  client.close().then(() => {
     DebuggerServer.destroy();
     SimpleTest.finish();
   });
 }
 
 function waitForTime(ms) {
   return new Promise((resolve, reject) => {
     setTimeout(resolve, ms);
--- a/devtools/server/tests/mochitest/test_device.html
+++ b/devtools/server/tests/mochitest/test_device.html
@@ -72,17 +72,17 @@ window.onload = function() {
         var profileDir = currProfD.path;
         ok(profileDir.indexOf(desc.profile.length > 0 && desc.profile) != -1, "valid profile name");
 
         var a = JSON.stringify(PermissionsTable);
         var b = JSON.stringify(permissions.rawPermissionsTable);
 
         is(a, b, "Permissions Tables is valid");
 
-        client.close(() => {
+        client.close().then(() => {
           DebuggerServer.destroy();
           SimpleTest.finish()
         });
       }
 
 
       d.getDescription().then((v) => desc = v)
       .then(() => d.getRawPermissionsTable())
--- a/devtools/server/tests/mochitest/test_framerate_01.html
+++ b/devtools/server/tests/mochitest/test_framerate_01.html
@@ -124,17 +124,17 @@ window.onload = function() {
         "The start and end framerate values should be equal.");
 
       is(typeof currFramerateStart, "number", "All values should be numbers.");
       ok(currFramerateStart <= 60, "All values were correctly clamped.")
 
       prevFramerateValue = currFramerateStart;
     }
 
-    client.close(() => {
+    client.close().then(() => {
       DebuggerServer.destroy();
       SimpleTest.finish()
     });
   }
 }
 </script>
 </pre>
 </body>
--- a/devtools/server/tests/mochitest/test_framerate_02.html
+++ b/devtools/server/tests/mochitest/test_framerate_02.html
@@ -94,17 +94,17 @@ window.onload = function() {
         is(timeline[0].value, 0,
           "The first framerate value should be 0.");
 
         is(timeline[1].delta, 100,
           "The last time delta should be 100 (the default interval value).");
         is(timeline[1].value, 0,
           "The last framerate value should be 0.");
 
-        client.close(() => {
+        client.close().then(() => {
           DebuggerServer.destroy();
           SimpleTest.finish()
         });
       });
     });
   });
 }
 </script>
--- a/devtools/server/tests/mochitest/test_framerate_03.html
+++ b/devtools/server/tests/mochitest/test_framerate_03.html
@@ -65,17 +65,17 @@ window.onload = function() {
     ok(!rawData.find(e => e > STOP_TICK),
       "There should be no tick after 3000ms.");
 
     for (var tick of rawData) {
       info("Testing tick: " + tick);
       is(typeof tick, "number", "All values should be numbers.");
     }
 
-    client.close(() => {
+    client.close().then(() => {
       DebuggerServer.destroy();
       SimpleTest.finish()
     });
   }
 }
 </script>
 </pre>
 </body>
--- a/devtools/server/tests/mochitest/test_framerate_04.html
+++ b/devtools/server/tests/mochitest/test_framerate_04.html
@@ -54,17 +54,17 @@ window.onload = function() {
     info("Difference in ticks: " + diff);
     ok(diff > 0, "More ticks should be recorded in the second batch.");
 
     ok(firstBatch.every((e) => secondBatch.indexOf(e) != -1),
       "All the ticks in the first batch should be in the second batch as well.");
     ok(secondBatch.every((e, i, array) => i < array.length - 1 ? e < array[i + 1] : true),
       "All the ticks in the final batch should be ascending in value.");
 
-    client.close(() => {
+    client.close().then(() => {
       DebuggerServer.destroy();
       SimpleTest.finish()
     });
   }
 }
 </script>
 </pre>
 <a id="testContent" target="_blank" href="inspector_getImageData.html">Test Document</a>
--- a/devtools/server/tests/mochitest/test_framerate_05.html
+++ b/devtools/server/tests/mochitest/test_framerate_05.html
@@ -53,17 +53,17 @@ window.onload = function() {
                   "The returned pending ticks should be empty (2).");
 
                 front.stopRecording().then(rawData => {
                   ok(rawData,
                     "The returned raw data should be an empty array (1).");
                   is(rawData.length, 0,
                     "The returned raw data should be an empty array (2).");
 
-                  client.close(() => {
+                  client.close().then(() => {
                     DebuggerServer.destroy();
                     SimpleTest.finish()
                   });
                 });
               });
             }, 1000);
           });
         }, 1000);
--- a/devtools/server/tests/mochitest/test_framerate_06.html
+++ b/devtools/server/tests/mochitest/test_framerate_06.html
@@ -64,17 +64,17 @@ window.onload = function() {
     // when we get ticks from other frames they're usually at diffs of < 1. Sometimes
     // ticks can still be less than 16ms even on one frame (usually following a very slow
     // frame), so use a low number (2) to be our threshold
     var THRESHOLD = 2;
     ok(ticks.length >= 20, "we should have atleast 20 ticks over the course of two seconds.");
     var belowThreshold = diffs.filter(v => v <= THRESHOLD);
     ok(belowThreshold.length <= 10, "we should have very few frames less than the threshold");
 
-    client.close(() => {
+    client.close().then(() => {
       DebuggerServer.destroy();
       SimpleTest.finish()
     });
   }
 }
 </script>
 </pre>
 <a id="testContent" target="_blank" href="inspector-traversal-data.html">Test Document</a>
--- a/devtools/server/tests/mochitest/test_getProcess.html
+++ b/devtools/server/tests/mochitest/test_getProcess.html
@@ -99,17 +99,17 @@ function runTests() {
           ok(response.result, 42, "console.eval worked");
           cleanup();
         });
       });
     });
   }
 
   function cleanup() {
-    client.close(function () {
+    client.close().then(function () {
       DebuggerServer.destroy();
       iframe.remove();
       SimpleTest.finish()
     });
   }
 
   connect();
 }
--- a/devtools/server/tests/mochitest/test_preference.html
+++ b/devtools/server/tests/mochitest/test_preference.html
@@ -70,17 +70,17 @@ function runTests() {
           is(prefs.allPrefs[key].hasUserValue, Services.prefs.prefHasUserValue(key), "valid hasUserValue (" + key + ")");
         });
 
         ["test.bool", "test.int", "test.string"].forEach(function(key) {
           ok(!prefs.allPrefs.hasOwnProperty(key), "expect no pref (" + key + ")");
           is(Services.prefs.getPrefType(key), Ci.nsIPrefBranch.PREF_INVALID, "pref (" + key + ") is clear");
         });
 
-        client.close(() => {
+        client.close().then(() => {
           DebuggerServer.destroy();
           SimpleTest.finish()
         });
       }
 
 
       p.getAllPrefs().then((json) => prefs["allPrefs"]  = json)
       .then(() => p.setBoolPref("test.bool", localPref.boolPref))
--- a/devtools/server/tests/mochitest/test_settings.html
+++ b/devtools/server/tests/mochitest/test_settings.html
@@ -76,17 +76,17 @@ function runTests() {
         is(settings["app.reportCrashes"], localSetting["app.reportCrashes"], "updated string setting");
         is(JSON.stringify(settings["app.someObject"]), JSON.stringify(localSetting["app.someObject"]), "updated object as string setting");
 
         is(resetSettings["wifi.enabled"], fakeSettings["wifi.enabled"], "reset to original bool setting");
         is(resetSettings["audio.volume.alarm"], fakeSettings["audio.volume.alarm"], "reset to original int setting");
         is(resetSettings["app.reportCrashes"], fakeSettings["app.reportCrashes"], "reset to original string setting");
         is(JSON.stringify(resetSettings["app.someObject"]), JSON.stringify(fakeSettings["app.someObject"]), "reset to original object setting");
 
-        client.close(() => {
+        client.close().then(() => {
           DebuggerServer.destroy();
           SimpleTest.finish();
         });
       }
 
       // settings.json doesn't exist outside of b2g so we will fake it.
       _setDefaultSettings(fakeSettings);
       s.setSetting("wifi.enabled", fakeSettings["wifi.enabled"])
--- a/devtools/server/tests/mochitest/test_setupInParentChild.html
+++ b/devtools/server/tests/mochitest/test_setupInParentChild.html
@@ -91,17 +91,17 @@ function runTests() {
     DebuggerServer.setupInChild({
       module: "chrome://mochitests/content/chrome/devtools/server/tests/mochitest/setup-in-child.js",
       setupChild: "setupChild",
       args: [1, "two", {three: true}]
     });
   });
 
   function cleanup() {
-    client.close(function () {
+    client.close().then(function () {
       DebuggerServer.destroy();
       iframe.remove();
       SimpleTest.finish()
     });
   }
 
 }
 </script>
--- a/devtools/server/tests/unit/head_dbg.js
+++ b/devtools/server/tests/unit/head_dbg.js
@@ -159,21 +159,17 @@ function createTestGlobal(name) {
 
 function connect(client) {
   dump("Connecting client.\n");
   return client.connect();
 }
 
 function close(client) {
   dump("Closing client.\n");
-  return new Promise(function (resolve) {
-    client.close(function () {
-      resolve();
-    });
-  });
+  return client.close();
 }
 
 function listTabs(client) {
   dump("Listing tabs.\n");
   return client.listTabs();
 }
 
 function findTab(tabs, title) {
--- a/devtools/server/tests/unit/test_add_actors.js
+++ b/devtools/server/tests/unit/test_add_actors.js
@@ -98,10 +98,10 @@ function test_stable_global_actor_instan
   gClient.listTabs(function onListTabs(aResponse) {
     do_check_eq(postInitGlobalActor, getActorInstance(connID, aResponse.postInitGlobalActor));
     do_check_eq(preInitGlobalActor, getActorInstance(connID, aResponse.preInitGlobalActor));
     run_next_test();
   });
 }
 
 function close_client() {
-  gClient.close(() => run_next_test());
+  gClient.close().then(() => run_next_test());
 }
--- a/devtools/server/tests/unit/test_breakpoint-01.js
+++ b/devtools/server/tests/unit/test_breakpoint-01.js
@@ -49,17 +49,17 @@ function test_simple_breakpoint()
         do_check_eq(aPacket.why.actors[0], bpClient.actor);
         // Check that the breakpoint worked.
         do_check_eq(gDebuggee.a, 1);
         do_check_eq(gDebuggee.b, undefined);
 
         // Remove the breakpoint.
         bpClient.remove(function (aResponse) {
           gThreadClient.resume(function () {
-            gClient.close(gCallback);
+            gClient.close().then(gCallback);
           });
         });
 
       });
 
       // Continue until the breakpoint is hit.
       gThreadClient.resume();
     });
--- a/devtools/server/tests/unit/test_breakpoint-02.js
+++ b/devtools/server/tests/unit/test_breakpoint-02.js
@@ -47,17 +47,17 @@ function test_breakpoint_running()
 
     let source = gThreadClient.source(aPacket.frame.where.source);
     source.setBreakpoint(location, function (aResponse) {
       // Eval scripts don't stick around long enough for the breakpoint to be set,
       // so just make sure we got the expected response from the actor.
       do_check_neq(aResponse.error, "noScript");
 
       do_execute_soon(function () {
-        gClient.close(gCallback);
+        gClient.close().then(gCallback);
       });
     });
   });
 
   Cu.evalInSandbox(
     "var line0 = Error().lineNumber;\n" +
     "debugger;\n" +
     "var a = 1;\n" +  // line0 + 2
--- a/devtools/server/tests/unit/test_breakpoint-03.js
+++ b/devtools/server/tests/unit/test_breakpoint-03.js
@@ -57,17 +57,17 @@ function test_skip_breakpoint()
         do_check_eq(aPacket.why.actors[0], bpClient.actor);
         // Check that the breakpoint worked.
         do_check_eq(gDebuggee.a, 1);
         do_check_eq(gDebuggee.b, undefined);
 
         // Remove the breakpoint.
         bpClient.remove(function (aResponse) {
           gThreadClient.resume(function () {
-            gClient.close(gCallback);
+            gClient.close().then(gCallback);
           });
         });
       });
 
       gThreadClient.resume();
     });
   });
 
--- a/devtools/server/tests/unit/test_breakpoint-04.js
+++ b/devtools/server/tests/unit/test_breakpoint-04.js
@@ -51,17 +51,17 @@ function test_child_breakpoint()
         do_check_eq(aPacket.why.actors[0], bpClient.actor);
         // Check that the breakpoint worked.
         do_check_eq(gDebuggee.a, 1);
         do_check_eq(gDebuggee.b, undefined);
 
         // Remove the breakpoint.
         bpClient.remove(function (aResponse) {
           gThreadClient.resume(function () {
-            gClient.close(gCallback);
+            gClient.close().then(gCallback);
           });
         });
       });
 
       // Continue until the breakpoint is hit.
       gThreadClient.resume();
     });
 
--- a/devtools/server/tests/unit/test_breakpoint-05.js
+++ b/devtools/server/tests/unit/test_breakpoint-05.js
@@ -53,17 +53,17 @@ function test_child_skip_breakpoint()
         do_check_eq(aPacket.why.actors[0], bpClient.actor);
         // Check that the breakpoint worked.
         do_check_eq(gDebuggee.a, 1);
         do_check_eq(gDebuggee.b, undefined);
 
         // Remove the breakpoint.
         bpClient.remove(function (aResponse) {
           gThreadClient.resume(function () {
-            gClient.close(gCallback);
+            gClient.close().then(gCallback);
           });
         });
       });
 
       // Continue until the breakpoint is hit.
       gThreadClient.resume();
     });
   });
--- a/devtools/server/tests/unit/test_breakpoint-06.js
+++ b/devtools/server/tests/unit/test_breakpoint-06.js
@@ -53,17 +53,17 @@ function test_nested_breakpoint()
         do_check_eq(aPacket.why.actors[0], bpClient.actor);
         // Check that the breakpoint worked.
         do_check_eq(gDebuggee.a, 1);
         do_check_eq(gDebuggee.b, undefined);
 
         // Remove the breakpoint.
         bpClient.remove(function (aResponse) {
           gThreadClient.resume(function () {
-            gClient.close(gCallback);
+            gClient.close().then(gCallback);
           });
         });
       });
 
       // Continue until the breakpoint is hit.
       gThreadClient.resume();
     });
 
--- a/devtools/server/tests/unit/test_breakpoint-07.js
+++ b/devtools/server/tests/unit/test_breakpoint-07.js
@@ -53,17 +53,17 @@ function test_second_child_skip_breakpoi
         do_check_eq(aPacket.why.actors[0], bpClient.actor);
         // Check that the breakpoint worked.
         do_check_eq(gDebuggee.a, 1);
         do_check_eq(gDebuggee.b, undefined);
 
         // Remove the breakpoint.
         bpClient.remove(function (aResponse) {
           gThreadClient.resume(function () {
-            gClient.close(gCallback);
+            gClient.close().then(gCallback);
           });
         });
       });
 
       // Continue until the breakpoint is hit.
       gThreadClient.resume();
     });
   });
--- a/devtools/server/tests/unit/test_breakpoint-08.js
+++ b/devtools/server/tests/unit/test_breakpoint-08.js
@@ -61,17 +61,17 @@ function test_child_skip_breakpoint()
           do_check_eq(aPacket.why.actors[0], bpClient.actor);
           // Check that the breakpoint worked.
           do_check_eq(gDebuggee.a, 1);
           do_check_eq(gDebuggee.b, undefined);
 
           // Remove the breakpoint.
           bpClient.remove(function (aResponse) {
             gThreadClient.resume(function () {
-              gClient.close(gCallback);
+              gClient.close().then(gCallback);
             });
           });
         });
 
         // Continue until the breakpoint is hit.
         gThreadClient.resume();
       });
     }
--- a/devtools/server/tests/unit/test_breakpoint-09.js
+++ b/devtools/server/tests/unit/test_breakpoint-09.js
@@ -79,10 +79,10 @@ function test_remove_breakpoint()
                    "  foo(true);\n" +         // line0 + 5
                    "}\n" +                    // line0 + 6
                    "debugger;\n" +            // line1 + 7
                    "foo();\n",                // line1 + 8
                    gDebuggee);
   if (!done) {
     do_check_true(false);
   }
-  gClient.close(gCallback);
+  gClient.close().then(gCallback);
 }
--- a/devtools/server/tests/unit/test_breakpoint-10.js
+++ b/devtools/server/tests/unit/test_breakpoint-10.js
@@ -57,17 +57,17 @@ function test_child_breakpoint()
           do_check_eq(aPacket.why.type, "breakpoint");
           do_check_eq(aPacket.why.actors[0], bpClient.actor);
           // Check that the breakpoint worked.
           do_check_eq(gDebuggee.i, 1);
 
           // Remove the breakpoint.
           bpClient.remove(function (aResponse) {
             gThreadClient.resume(function () {
-              gClient.close(gCallback);
+              gClient.close().then(gCallback);
             });
           });
         });
 
         // Continue until the breakpoint is hit again.
         gThreadClient.resume();
 
       });
--- a/devtools/server/tests/unit/test_breakpoint-11.js
+++ b/devtools/server/tests/unit/test_breakpoint-11.js
@@ -58,17 +58,17 @@ function test_child_breakpoint()
           do_check_eq(aPacket.why.actors[0], bpClient.actor);
           // Check that the breakpoint worked.
           do_check_eq(gDebuggee.a.b, 1);
           do_check_eq(gDebuggee.res, undefined);
 
           // Remove the breakpoint.
           bpClient.remove(function (aResponse) {
             gThreadClient.resume(function () {
-              gClient.close(gCallback);
+              gClient.close().then(gCallback);
             });
           });
         });
 
         // Continue until the breakpoint is hit again.
         gThreadClient.resume();
 
       });
--- a/devtools/server/tests/unit/test_breakpoint-12.js
+++ b/devtools/server/tests/unit/test_breakpoint-12.js
@@ -96,17 +96,17 @@ function set_breakpoints(source, locatio
 
       gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
         // We don't expect any more pauses after the breakpoint was hit once.
         do_check_true(false);
       });
       gThreadClient.resume(function () {
         // Give any remaining breakpoints a chance to trigger.
         do_timeout(1000, function () {
-          gClient.close(gCallback);
+          gClient.close().then(gCallback);
         });
       });
 
     });
     // Continue until the breakpoint is hit.
     gThreadClient.resume();
   });
 
--- a/devtools/server/tests/unit/test_breakpoint-13.js
+++ b/devtools/server/tests/unit/test_breakpoint-13.js
@@ -94,17 +94,17 @@ function test_simple_breakpoint()
         let packet = yield waiter;
         callback(packet);
       }
 
       // Remove the breakpoint and finish.
       let waiter = waitForPause(gThreadClient);
       gThreadClient.stepIn();
       yield waiter;
-      bpClient.remove(() => gThreadClient.resume(() => gClient.close(gCallback)));
+      bpClient.remove(() => gThreadClient.resume(() => gClient.close().then(gCallback)));
     }));
   });
 
   Cu.evalInSandbox("var line0 = Error().lineNumber;\n" +
                    "function foo() {\n" + // line0 + 1
                    "  this.a = 1;\n" +    // line0 + 2 <-- Breakpoint is set here.
                    "}\n" +                // line0 + 3
                    "debugger;\n" +        // line0 + 4
--- a/devtools/server/tests/unit/test_breakpoint-14.js
+++ b/devtools/server/tests/unit/test_breakpoint-14.js
@@ -92,17 +92,17 @@ function test_simple_breakpoint()
         let packet = yield waiter;
         callback(packet);
       }
 
       // Remove the breakpoint and finish.
       let waiter = waitForPause(gThreadClient);
       gThreadClient.stepOver();
       yield waiter;
-      bpClient.remove(() => gThreadClient.resume(() => gClient.close(gCallback)));
+      bpClient.remove(() => gThreadClient.resume(() => gClient.close().then(gCallback)));
     }));
   });
 
   Cu.evalInSandbox("var line0 = Error().lineNumber;\n" +
                    "function foo() {\n" + // line0 + 1
                    "  this.a = 1;\n" +    // line0 + 2 <-- Breakpoint is set here.
                    "}\n" +                // line0 + 3
                    "debugger;\n" +        // line0 + 4
--- a/devtools/server/tests/unit/test_breakpoint-16.js
+++ b/devtools/server/tests/unit/test_breakpoint-16.js
@@ -56,17 +56,17 @@ function test_column_breakpoint()
 
         do_check_eq(gDebuggee.acc, timesBreakpointHit);
         do_check_eq(aPacket.frame.environment.bindings.variables.i.value,
                     timesBreakpointHit);
 
         if (++timesBreakpointHit === 3) {
           gThreadClient.removeListener("paused", onPaused);
           bpClient.remove(function (aResponse) {
-            gThreadClient.resume(() => gClient.close(gCallback));
+            gThreadClient.resume(() => gClient.close().then(gCallback));
           });
         } else {
           gThreadClient.resume();
         }
       });
 
       // Continue until the breakpoint is hit.
       gThreadClient.resume();
--- a/devtools/server/tests/unit/test_breakpoint-17.js
+++ b/devtools/server/tests/unit/test_breakpoint-17.js
@@ -103,17 +103,17 @@ function test_remove_one(aFirst, aSecond
         return;
       }
 
       if (why.type == "debuggerStatement") {
         gClient.removeListener("paused", _onPaused);
         do_check_true(hitSecond,
                       "We should still hit `second`, but not `first`.");
 
-        gClient.close(gCallback);
+        gClient.close().then(gCallback);
         return;
       }
 
       do_check_true(false, "Should never get here");
     });
 
     gThreadClient.resume(() => gDebuggee.foo());
   });
--- a/devtools/server/tests/unit/test_breakpoint-18.js
+++ b/devtools/server/tests/unit/test_breakpoint-18.js
@@ -73,10 +73,10 @@ function testBPHit(event, { why }) {
 }
 
 function testDbgStatement(event, { why }) {
   // Should continue to the debugger statement.
   do_check_eq(why.type, "debuggerStatement");
   // Not break on another offset from the same line (that isn't an entry point
   // to the line)
   do_check_neq(why.type, "breakpoint");
-  gClient.close(gCallback);
+  gClient.close().then(gCallback);
 }
--- a/devtools/server/tests/unit/test_client_close.js
+++ b/devtools/server/tests/unit/test_client_close.js
@@ -24,16 +24,16 @@ function test_close(aTransport)
 {
   // Check that, if we fake a transport shutdown
   // (like if a device is unplugged)
   // the client is automatically closed,
   // and we can still call client.close.
   let onClosed = function () {
     gClient.removeListener("closed", onClosed);
     ok(true, "Client emitted 'closed' event");
-    gClient.close(function () {
+    gClient.close().then(function () {
       ok(true, "client.close() successfully called its callback");
       do_test_finished();
     });
   };
   gClient.addListener("closed", onClosed);
   aTransport.close();
 }
--- a/devtools/server/tests/unit/test_client_request.js
+++ b/devtools/server/tests/unit/test_client_request.js
@@ -155,17 +155,17 @@ function test_close_client_while_sending
 
   let expectReply = promise.defer();
   gClient.expectReply("root", function (response) {
     do_check_eq(response.error, "connectionClosed");
     do_check_eq(response.message, "server side packet can't be received as the connection just closed.");
     expectReply.resolve();
   });
 
-  gClient.close(() => {
+  gClient.close().then(() => {
     activeRequest.then(() => {
       ok(false, "First request unexpectedly succeed while closing the connection");
     }, response => {
       do_check_eq(response.error, "connectionClosed");
       do_check_eq(response.message, "'hello' active request packet to '" + gActorId + "' can't be sent as the connection just closed.");
     })
     .then(() => pendingRequest)
     .then(() => {
--- a/devtools/server/tests/unit/test_memory_footprint.js
+++ b/devtools/server/tests/unit/test_memory_footprint.js
@@ -46,10 +46,10 @@ function connect_client() {
 
 function list_tabs() {
   gClient.listTabs(function onListTabs(aResponse) {
     check_footprint("DebuggerClient.listTabs()", 3800);
   });
 }
 
 function close_client() {
-  gClient.close(run_next_test);
+  gClient.close().then(run_next_test);
 }
--- a/devtools/server/tests/unit/test_objectgrips-01.js
+++ b/devtools/server/tests/unit/test_objectgrips-01.js
@@ -42,17 +42,17 @@ function test_object_grip()
     let objClient = gThreadClient.pauseGrip(args[0]);
     objClient.getOwnPropertyNames(function (aResponse) {
       do_check_eq(aResponse.ownPropertyNames.length, 3);
       do_check_eq(aResponse.ownPropertyNames[0], "a");
       do_check_eq(aResponse.ownPropertyNames[1], "b");
       do_check_eq(aResponse.ownPropertyNames[2], "c");
 
       gThreadClient.resume(function () {
-        gClient.close(gCallback);
+        gClient.close().then(gCallback);
       });
     });
 
   });
 
   gDebuggee.eval("stopMe({ a: 1, b: true, c: 'foo' })");
 }
 
--- a/devtools/server/tests/unit/test_objectgrips-02.js
+++ b/devtools/server/tests/unit/test_objectgrips-02.js
@@ -45,17 +45,17 @@ function test_object_grip()
 
       let protoClient = gThreadClient.pauseGrip(aResponse.prototype);
       protoClient.getOwnPropertyNames(function (aResponse) {
         do_check_eq(aResponse.ownPropertyNames.length, 2);
         do_check_eq(aResponse.ownPropertyNames[0], "b");
         do_check_eq(aResponse.ownPropertyNames[1], "c");
 
         gThreadClient.resume(function () {
-          gClient.close(gCallback);
+          gClient.close().then(gCallback);
         });
       });
     });
 
   });
 
   gDebuggee.eval(function Constr() {
     this.a = 1;
--- a/devtools/server/tests/unit/test_objectgrips-03.js
+++ b/devtools/server/tests/unit/test_objectgrips-03.js
@@ -55,17 +55,17 @@ function test_object_grip()
         objClient.getProperty("a", function (aResponse) {
           do_check_eq(aResponse.descriptor.configurable, true);
           do_check_eq(aResponse.descriptor.enumerable, true);
           do_check_eq(aResponse.descriptor.get.type, "object");
           do_check_eq(aResponse.descriptor.get.class, "Function");
           do_check_eq(aResponse.descriptor.set.type, "undefined");
 
           gThreadClient.resume(function () {
-            gClient.close(gCallback);
+            gClient.close().then(gCallback);
           });
         });
       });
     });
 
   });
 
   gDebuggee.eval("stopMe({ x: 10, y: 'kaiju', get a() { return 42; } })");
--- a/devtools/server/tests/unit/test_objectgrips-04.js
+++ b/devtools/server/tests/unit/test_objectgrips-04.js
@@ -59,17 +59,17 @@ function test_object_grip()
 
       do_check_true(aResponse.prototype != undefined);
 
       let protoClient = gThreadClient.pauseGrip(aResponse.prototype);
       protoClient.getOwnPropertyNames(function (aResponse) {
         do_check_true(aResponse.ownPropertyNames.toString != undefined);
 
         gThreadClient.resume(function () {
-          gClient.close(gCallback);
+          gClient.close().then(gCallback);
         });
       });
     });
 
   });
 
   gDebuggee.eval("stopMe({ x: 10, y: 'kaiju', get a() { return 42; } })");
 }
--- a/devtools/server/tests/unit/test_objectgrips-05.js
+++ b/devtools/server/tests/unit/test_objectgrips-05.js
@@ -48,17 +48,17 @@ function test_object_grip()
 
     let obj2 = aPacket.frame.arguments[1];
     do_check_false(obj2.frozen);
 
     let obj2Client = gThreadClient.pauseGrip(obj2);
     do_check_false(obj2Client.isFrozen);
 
     gThreadClient.resume(_ => {
-      gClient.close(gCallback);
+      gClient.close().then(gCallback);
     });
   });
 
   gDebuggee.eval("(" + function () {
     let obj1 = {};
     Object.freeze(obj1);
     stopMe(obj1, {});
   } + "())");
--- a/devtools/server/tests/unit/test_objectgrips-06.js
+++ b/devtools/server/tests/unit/test_objectgrips-06.js
@@ -48,17 +48,17 @@ function test_object_grip()
 
     let obj2 = aPacket.frame.arguments[1];
     do_check_false(obj2.sealed);
 
     let obj2Client = gThreadClient.pauseGrip(obj2);
     do_check_false(obj2Client.isSealed);
 
     gThreadClient.resume(_ => {
-      gClient.close(gCallback);
+      gClient.close().then(gCallback);
     });
   });
 
   gDebuggee.eval("(" + function () {
     let obj1 = {};
     Object.seal(obj1);
     stopMe(obj1, {});
   } + "())");
--- a/devtools/server/tests/unit/test_objectgrips-07.js
+++ b/devtools/server/tests/unit/test_objectgrips-07.js
@@ -52,17 +52,17 @@ function test_object_grip()
 
     do_check_false(ne.extensible);
     do_check_false(neClient.isExtensible);
 
     do_check_true(e.extensible);
     do_check_true(eClient.isExtensible);
 
     gThreadClient.resume(_ => {
-      gClient.close(gCallback);
+      gClient.close().then(gCallback);
     });
   });
 
   gDebuggee.eval("(" + function () {
     let f = {};
     Object.freeze(f);
     let s = {};
     Object.seal(s);
--- a/devtools/server/tests/unit/test_objectgrips-08.js
+++ b/devtools/server/tests/unit/test_objectgrips-08.js
@@ -57,16 +57,16 @@ function test_object_grip()
       do_check_eq(aResponse.ownProperties.c.value.type, "NaN");
 
       do_check_eq(aResponse.ownProperties.d.configurable, true);
       do_check_eq(aResponse.ownProperties.d.enumerable, true);
       do_check_eq(aResponse.ownProperties.d.writable, true);
       do_check_eq(aResponse.ownProperties.d.value.type, "-0");
 
       gThreadClient.resume(function () {
-        gClient.close(gCallback);
+        gClient.close().then(gCallback);
       });
     });
   });
 
   gDebuggee.eval("stopMe({ a: Infinity, b: -Infinity, c: NaN, d: -0 })");
 }
 
--- a/devtools/server/tests/unit/test_objectgrips-09.js
+++ b/devtools/server/tests/unit/test_objectgrips-09.js
@@ -58,17 +58,17 @@ function test_object_grip()
       do_check_eq(obj2.ownProperties.z.enumerable, true);
       do_check_eq(obj2.ownProperties.z.writable, true);
       do_check_eq(obj2.ownProperties.z.value, 123);
 
       do_check_true(obj1.prototype != undefined);
       do_check_true(obj2.prototype != undefined);
 
       gThreadClient.resume(function () {
-        gClient.close(gCallback);
+        gClient.close().then(gCallback);
       });
     });
 
   });
 
   gDebuggee.eval("stopMe({ x: 10, y: 'kaiju'}, { z: 123 })");
 }
 
--- a/devtools/server/tests/unit/test_profiler_activation-02.js
+++ b/devtools/server/tests/unit/test_profiler_activation-02.js
@@ -16,17 +16,17 @@ function run_test()
   // Ensure the profiler is already running when the test starts.
   Profiler.StartProfiler(1000000, 1, ["js"], 1);
 
   DevToolsUtils.waitForTime(WAIT_TIME).then(() => {
 
     get_chrome_actors((client, form) => {
       let actor = form.profilerActor;
       test_start_time(client, actor, () => {
-        client.close(do_test_finished);
+        client.close().then(do_test_finished);
       });
     });
   });
 
   do_test_pending();
 }
 
 function test_start_time(client, actor, callback) {
--- a/devtools/server/tests/unit/test_profiler_bufferstatus.js
+++ b/devtools/server/tests/unit/test_profiler_bufferstatus.js
@@ -20,17 +20,17 @@ function run_test()
 
   get_chrome_actors((client, form) => {
     let actor = form.profilerActor;
     check_empty_buffer(client, actor, () => {
       activate_profiler(client, actor, startTime => {
         wait_for_samples(client, actor, () => {
           check_buffer(client, actor, () => {
             deactivate_profiler(client, actor, () => {
-              client.close(do_test_finished);
+              client.close().then(do_test_finished);
             });
           });
         });
       });
     });
   });
 
   do_test_pending();
--- a/devtools/server/tests/unit/test_profiler_data.js
+++ b/devtools/server/tests/unit/test_profiler_data.js
@@ -14,17 +14,17 @@ const MAX_WAIT_TIME = 20000; // ms
 
 function run_test()
 {
   get_chrome_actors((client, form) => {
     let actor = form.profilerActor;
     activate_profiler(client, actor, startTime => {
       test_data(client, actor, startTime, () => {
         deactivate_profiler(client, actor, () => {
-          client.close(do_test_finished);
+          client.close().then(do_test_finished);
         });
       });
     });
   });
 
   do_test_pending();
 }
 
--- a/devtools/server/tests/unit/test_profiler_getbufferinfo.js
+++ b/devtools/server/tests/unit/test_profiler_getbufferinfo.js
@@ -20,17 +20,17 @@ function run_test()
 
   get_chrome_actors((client, form) => {
     let actor = form.profilerActor;
     check_empty_buffer(client, actor, () => {
       activate_profiler(client, actor, startTime => {
         wait_for_samples(client, actor, () => {
           check_buffer(client, actor, () => {
             deactivate_profiler(client, actor, () => {
-              client.close(do_test_finished);
+              client.close().then(do_test_finished);
             });
           });
         });
       });
     });
   });
 
   do_test_pending();
--- a/devtools/server/tests/unit/test_profiler_getfeatures.js
+++ b/devtools/server/tests/unit/test_profiler_getfeatures.js
@@ -9,17 +9,17 @@
 
 const Profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler);
 
 function run_test()
 {
   get_chrome_actors((client, form) => {
     let actor = form.profilerActor;
     test_getfeatures(client, actor, () => {
-      client.close(() => {
+      client.close().then(() => {
         do_test_finished();
       });
     });
   });
 
   do_test_pending();
 }
 
--- a/devtools/server/tests/unit/test_profiler_getsharedlibraryinformation.js
+++ b/devtools/server/tests/unit/test_profiler_getsharedlibraryinformation.js
@@ -9,17 +9,17 @@
 
 const Profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler);
 
 function run_test()
 {
   get_chrome_actors((client, form) => {
     let actor = form.profilerActor;
     test_getsharedlibraryinformation(client, actor, () => {
-      client.close(() => {
+      client.close().then(() => {
         do_test_finished();
       });
     });
   });
 
   do_test_pending();
 }
 
--- a/devtools/server/tests/unit/test_protocol_async.js
+++ b/devtools/server/tests/unit/test_protocol_async.js
@@ -170,15 +170,15 @@ function run_test()
     calls.push(rootClient.simpleReturn().then(ret => {
       return deferAfterRejection.promise.then(function () {
         do_check_eq(sequence, 7); // Check right return order
         do_check_eq(ret, sequence++); // Check request handling order
       });
     }));
 
     promise.all(calls).then(() => {
-      client.close(() => {
+      client.close().then(() => {
         do_test_finished();
       });
     });
   });
   do_test_pending();
 }
--- a/devtools/server/tests/unit/test_protocol_children.js
+++ b/devtools/server/tests/unit/test_protocol_children.js
@@ -543,17 +543,17 @@ function run_test()
       };
       return rootFront.getChildren2(f());
     }).then(ret => {
       do_check_eq(ret.length, 2);
       do_check_true(ret[0] === childFront);
       do_check_true(ret[1] !== childFront);
       do_check_true(ret[1] instanceof ChildFront);
     }).then(() => {
-      client.close(() => {
+      client.close().then(() => {
         do_test_finished();
       });
     }).then(null, err => {
       do_report_unexpected_exception(err, "Failure executing test");
     });
   });
   do_test_pending();
 }
--- a/devtools/server/tests/unit/test_protocol_longstring.js
+++ b/devtools/server/tests/unit/test_protocol_longstring.js
@@ -202,17 +202,17 @@ function run_test()
       do_check_eq(value, LONG_STR);
     }).then(() => {
       return strfront.release();
     }).then(() => {
       trace.expectSend({"type":"release", "to":"<actorid>"});
       trace.expectReceive({"from":"<actorid>"});
       expectRootChildren(0);
     }).then(() => {
-      client.close(() => {
+      client.close().then(() => {
         do_test_finished();
       });
     }).then(null, err => {
       do_report_unexpected_exception(err, "Failure executing test");
     });
   });
   do_test_pending();
 }
--- a/devtools/server/tests/unit/test_protocol_simple.js
+++ b/devtools/server/tests/unit/test_protocol_simple.js
@@ -303,17 +303,17 @@ function run_test()
 
         do_check_true(res.zero === 0);
         do_check_true(res.farce === false);
         deferred.resolve();
       });
       rootClient.emitFalsyOptions();
       return deferred.promise;
     }).then(() => {
-      client.close(() => {
+      client.close().then(() => {
         do_test_finished();
       });
     }).then(null, err => {
       do_report_unexpected_exception(err, "Failure executing test");
     });
   });
   do_test_pending();
 }
--- a/devtools/server/tests/unit/test_protocol_stack.js
+++ b/devtools/server/tests/unit/test_protocol_stack.js
@@ -83,16 +83,16 @@ function run_test() {
           return;
         }
         stack = stack.asyncCaller || stack.caller;
       }
       ok(false, "Incomplete stack");
     }, () => {
       ok(false, "Request failed unexpectedly");
     }).then(() => {
-      client.close(() => {
+      client.close().then(() => {
         do_test_finished();
       });
     });
   });
 
   do_test_pending();
 }
--- a/devtools/server/tests/unit/test_reattach-thread.js
+++ b/devtools/server/tests/unit/test_reattach-thread.js
@@ -49,10 +49,10 @@ function test_reattach()
     do_check_eq(aThreadClient.state, "paused");
     do_check_eq(gTabClient.thread, aThreadClient);
     aThreadClient.resume(cleanup);
   });
 }
 
 function cleanup()
 {
-  gClient.close(do_test_finished);
+  gClient.close().then(do_test_finished);
 }
--- a/devtools/server/tests/unit/test_registerClient.js
+++ b/devtools/server/tests/unit/test_registerClient.js
@@ -81,15 +81,15 @@ function test_client_events()
     do_check_eq(type, "foo");
     do_check_eq(data.hello, "world");
     run_next_test();
   });
   gTestClient.start();
 }
 
 function close_client() {
-  gClient.close(() => {
+  gClient.close().then(() => {
     // Check that client.detach method is call on client destruction
     do_check_true(gTestClient.detached);
     run_next_test();
   });
 }
 
--- a/devtools/server/tests/unit/test_register_actor.js
+++ b/devtools/server/tests/unit/test_register_actor.js
@@ -91,17 +91,17 @@ function test_lazy_api() {
   function onRequest(aResponse) {
     do_check_eq(aResponse, "world");
 
     // Finally, the actor is loaded on the first request being made to it
     do_check_true(isActorLoaded);
     do_check_true(isActorInstanciated);
 
     Services.obs.removeObserver(onActorEvent, "actor", false);
-    client.close(() => run_next_test());
+    client.close().then(() => run_next_test());
   }
 }
 
 function cleanup() {
   DebuggerServer.destroy();
 
   // Check that all actors are unregistered on server destruction
   check_actors(false);
--- a/devtools/server/tests/unit/test_requestTypes.js
+++ b/devtools/server/tests/unit/test_requestTypes.js
@@ -11,17 +11,17 @@ function test_requestTypes_request(aClie
     var expectedRequestTypes = Object.keys(RootActor.
                                            prototype.
                                            requestTypes);
 
     do_check_true(Array.isArray(aResponse.requestTypes));
     do_check_eq(JSON.stringify(aResponse.requestTypes),
                 JSON.stringify(expectedRequestTypes));
 
-    aClient.close(() => {
+    aClient.close().then(() => {
       do_test_finished();
     });
   });
 }
 
 function run_test()
 {
   DebuggerServer.init();
--- a/devtools/server/tests/unit/test_stepping-01.js
+++ b/devtools/server/tests/unit/test_stepping-01.js
@@ -59,17 +59,17 @@ function test_simple_stepping()
           // When leaving a stack frame the line number doesn't change.
           do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
           do_check_eq(aPacket.why.type, "resumeLimit");
           // Check that stepping worked.
           do_check_eq(gDebuggee.a, 1);
           do_check_eq(gDebuggee.b, 2);
 
           gThreadClient.resume(function () {
-            gClient.close(gCallback);
+            gClient.close().then(gCallback);
           });
         });
         gThreadClient.stepOver();
       });
       gThreadClient.stepOver();
 
     });
     gThreadClient.stepOver();
--- a/devtools/server/tests/unit/test_stepping-02.js
+++ b/devtools/server/tests/unit/test_stepping-02.js
@@ -59,17 +59,17 @@ function test_simple_stepping()
           // When leaving a stack frame the line number doesn't change.
           do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
           do_check_eq(aPacket.why.type, "resumeLimit");
           // Check that stepping worked.
           do_check_eq(gDebuggee.a, 1);
           do_check_eq(gDebuggee.b, 2);
 
           gThreadClient.resume(function () {
-            gClient.close(gCallback);
+            gClient.close().then(gCallback);
           });
         });
         gThreadClient.stepIn();
       });
       gThreadClient.stepIn();
 
     });
     gThreadClient.stepIn();
--- a/devtools/server/tests/unit/test_stepping-03.js
+++ b/devtools/server/tests/unit/test_stepping-03.js
@@ -40,17 +40,17 @@ function test_simple_stepping()
       do_check_eq(aPacket.type, "paused");
       do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
       do_check_eq(aPacket.why.type, "resumeLimit");
       // Check that stepping worked.
       do_check_eq(gDebuggee.a, 1);
       do_check_eq(gDebuggee.b, 2);
 
       gThreadClient.resume(function () {
-        gClient.close(gCallback);
+        gClient.close().then(gCallback);
       });
     });
     gThreadClient.stepOut();
 
   });
 
   gDebuggee.eval("var line0 = Error().lineNumber;\n" +
                  "function f() {\n" + // line0 + 1
--- a/devtools/server/tests/unit/test_stepping-04.js
+++ b/devtools/server/tests/unit/test_stepping-04.js
@@ -49,17 +49,17 @@ function test_simple_stepping()
         do_check_eq(aPacket.type, "paused");
         do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 6);
         do_check_eq(aPacket.why.type, "resumeLimit");
         // Check that stepping worked.
         do_check_eq(gDebuggee.a, 1);
         do_check_eq(gDebuggee.b, undefined);
 
         gThreadClient.resume(function () {
-          gClient.close(gCallback);
+          gClient.close().then(gCallback);
         });
       });
       gThreadClient.stepOver();
 
     });
     gThreadClient.stepOver();
 
   });
--- a/devtools/server/tests/unit/test_stepping-05.js
+++ b/devtools/server/tests/unit/test_stepping-05.js
@@ -88,14 +88,14 @@ function test_next_pause()
 {
   gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
     // Check the return value.
     do_check_eq(aPacket.type, "paused");
     // Before fixing bug 785689, the type was resumeLimit.
     do_check_eq(aPacket.why.type, "debuggerStatement");
 
     gThreadClient.resume(function () {
-      gClient.close(gCallback);
+      gClient.close().then(gCallback);
     });
   });
 
   gDebuggee.eval("debugger;");
 }
--- a/devtools/server/tests/unit/test_stepping-06.js
+++ b/devtools/server/tests/unit/test_stepping-06.js
@@ -59,17 +59,17 @@ function test_simple_stepping()
             gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
               // Check that the exception was thrown.
               do_check_eq(aPacket.type, "paused");
               do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 11);
               do_check_eq(aPacket.why.type, "resumeLimit");
               do_check_eq(aPacket.why.frameFinished.throw, "ah");
 
               gThreadClient.resume(function () {
-                gClient.close(gCallback);
+                gClient.close().then(gCallback);
               });
             });
             gThreadClient.stepOut();
           });
           gThreadClient.resume();
         });
         gThreadClient.stepOut();
       });
--- a/devtools/shared/client/main.js
+++ b/devtools/shared/client/main.js
@@ -349,44 +349,46 @@ DebuggerClient.prototype = {
     return deferred.promise;
   },
 
   /**
    * Shut down communication with the debugging server.
    *
    * @param aOnClosed function
    *        If specified, will be called when the debugging connection
-   *        has been closed.
+   *        has been closed. This parameter is deprecated - please use
+   *        the returned Promise.
+   * @return Promise
+   *         Resolves after the underlying transport is closed.
    */
   close: function (aOnClosed) {
+    let deferred = promise.defer();
+    if (aOnClosed) {
+      deferred.promise.then(aOnClosed);
+    }
+
     // Disable detach event notifications, because event handlers will be in a
     // cleared scope by the time they run.
     this._eventsEnabled = false;
 
     let cleanup = () => {
       this._transport.close();
       this._transport = null;
     };
 
     // If the connection is already closed,
     // there is no need to detach client
     // as we won't be able to send any message.
     if (this._closed) {
       cleanup();
-      if (aOnClosed) {
-        aOnClosed();
-      }
-      return;
+      deferred.resolve();
+      return deferred.promise;
     }
 
-    if (aOnClosed) {
-      this.addOneTimeListener("closed", function (aEvent) {
-        aOnClosed();
-      });
-    }
+    this.addOneTimeListener("closed", deferred.resolve);
 
     // Call each client's `detach` method by calling
     // lastly registered ones first to give a chance
     // to detach child clients first.
     let clients = [...this._clients.values()];
     this._clients.clear();
     const detachClients = () => {
       let client = clients.pop();
@@ -397,16 +399,18 @@ DebuggerClient.prototype = {
       }
       if (client.detach) {
         client.detach(detachClients);
         return;
       }
       detachClients();
     };
     detachClients();
+
+    return deferred.promise;
   },
 
   /*
    * This function exists only to preserve DebuggerClient's interface;
    * new code should say 'client.mainRoot.listTabs()'.
    */
   listTabs: function (aOnResponse) { return this.mainRoot.listTabs(aOnResponse); },
 
--- a/devtools/shared/transport/tests/unit/head_dbg.js
+++ b/devtools/shared/transport/tests/unit/head_dbg.js
@@ -180,17 +180,17 @@ function initTestDebuggerServer() {
     type: { global: true, tab: true }
   });
   DebuggerServer.registerModule("xpcshell-test/testactors");
   // Allow incoming connections.
   DebuggerServer.init();
 }
 
 function finishClient(aClient) {
-  aClient.close(function () {
+  aClient.close().then(function () {
     do_test_finished();
   });
 }
 
 /**
  * Takes a relative file path and returns the absolute file url for it.
  */
 function getFileUrl(aName, aAllowMissing = false) {
--- a/devtools/shared/webconsole/test/common.js
+++ b/devtools/shared/webconsole/test/common.js
@@ -140,17 +140,17 @@ function _attachConsole(aListeners, aCal
         });
       });
     }
   });
 }
 
 function closeDebugger(aState, aCallback)
 {
-  aState.dbgClient.close(aCallback);
+  aState.dbgClient.close().then(aCallback);
   aState.dbgClient = null;
   aState.client = null;
 }
 
 function checkConsoleAPICalls(consoleCalls, expectedConsoleCalls)
 {
   is(consoleCalls.length, expectedConsoleCalls.length,
     "received correct number of console calls");