Bug 1297362 - Part 2: Eliminate CPOWs from Netmonitor mochitests C r?ochameau draft
authorJarda Snajdr <jsnajdr@gmail.com>
Tue, 23 Aug 2016 17:52:58 +0200
changeset 406766 32db2b3cdfe1832475c9c661dc34a8d9fd03e3fd
parent 406765 d11a7a19af39aafb25051e23846b56e980ce5314
child 406767 1f7243d1809eb4cf641dee6fe6baa7a904d90460
push id27819
push userbmo:jsnajdr@gmail.com
push dateMon, 29 Aug 2016 13:56:30 +0000
reviewersochameau
bugs1297362
milestone51.0a1
Bug 1297362 - Part 2: Eliminate CPOWs from Netmonitor mochitests C r?ochameau MozReview-Commit-ID: 6idC1iZkrEY
devtools/client/netmonitor/test/browser_net_cached-status.js
devtools/client/netmonitor/test/browser_net_cause.js
devtools/client/netmonitor/test/browser_net_cause_redirect.js
devtools/client/netmonitor/test/browser_net_charts-01.js
devtools/client/netmonitor/test/browser_net_charts-02.js
devtools/client/netmonitor/test/browser_net_charts-03.js
devtools/client/netmonitor/test/browser_net_charts-04.js
devtools/client/netmonitor/test/browser_net_charts-05.js
devtools/client/netmonitor/test/browser_net_charts-06.js
devtools/client/netmonitor/test/browser_net_charts-07.js
devtools/client/netmonitor/test/browser_net_clear.js
devtools/client/netmonitor/test/browser_net_complex-params.js
devtools/client/netmonitor/test/browser_net_content-type.js
devtools/client/netmonitor/test/browser_net_copy_headers.js
devtools/client/netmonitor/test/browser_net_copy_image_as_data_uri.js
devtools/client/netmonitor/test/browser_net_copy_params.js
devtools/client/netmonitor/test/browser_net_copy_response.js
devtools/client/netmonitor/test/browser_net_copy_svg_image_as_data_uri.js
devtools/client/netmonitor/test/browser_net_copy_url.js
devtools/client/netmonitor/test/browser_net_cors_requests.js
devtools/client/netmonitor/test/browser_net_curl-utils.js
devtools/client/netmonitor/test/browser_net_cyrillic-01.js
devtools/client/netmonitor/test/browser_net_cyrillic-02.js
--- a/devtools/client/netmonitor/test/browser_net_cached-status.js
+++ b/devtools/client/netmonitor/test/browser_net_cached-status.js
@@ -1,29 +1,23 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
+
 "use strict";
 
-// /////////////////
-//
-// Whitelisting this test.
-// As part of bug 1077403, the leaking uncaught rejection should be fixed.
-//
-thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: can't convert undefined to object");
-
 /**
  * Tests if cached requests have the correct status code
  */
 
-var test = Task.async(function* () {
-  let [tab, debuggee, monitor] = yield initNetMonitor(STATUS_CODES_URL, null, true);
+add_task(function* () {
+  let [tab, , monitor] = yield initNetMonitor(STATUS_CODES_URL, null, true);
   info("Starting test... ");
 
-  let { document, L10N, NetMonitorView } = monitor.panelWin;
+  let { NetMonitorView } = monitor.panelWin;
   let { RequestsMenu, NetworkDetails } = NetMonitorView;
 
   RequestsMenu.lazyUpdate = false;
   NetworkDetails._params.lazyEmpty = false;
 
   const REQUEST_DATA = [
     {
       method: "GET",
@@ -56,17 +50,17 @@ var test = Task.async(function* () {
       }
     },
     {
       method: "GET",
       uri: STATUS_CODES_SJS + "?sts=ok&cached",
       details: {
         status: 200,
         statusText: "OK (cached)",
-        displayedStatus : "cached",
+        displayedStatus: "cached",
         type: "plain",
         fullMimeType: "text/plain; charset=utf-8"
       }
     },
     {
       method: "GET",
       uri: STATUS_CODES_SJS + "?sts=redirect&cached",
       details: {
@@ -85,28 +79,33 @@ var test = Task.async(function* () {
         statusText: "Not Found",
         type: "html",
         fullMimeType: "text/html; charset=utf-8"
       }
     }
   ];
 
   info("Performing requests #1...");
-  debuggee.performCachedRequests();
-  yield waitForNetworkEvents(monitor, 3);
+  yield performRequestsAndWait();
 
   info("Performing requests #2...");
-  debuggee.performCachedRequests();
-  yield waitForNetworkEvents(monitor, 3);
+  yield performRequestsAndWait();
 
   let index = 0;
   for (let request of REQUEST_DATA) {
     let item = RequestsMenu.getItemAtIndex(index);
 
     info("Verifying request #" + index);
     yield verifyRequestItemTarget(item, request.method, request.uri, request.details);
 
     index++;
   }
 
   yield teardown(monitor);
-  finish();
+
+  function* performRequestsAndWait() {
+    let wait = waitForNetworkEvents(monitor, 3);
+    yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
+      content.wrappedJSObject.performCachedRequests();
+    });
+    yield wait;
+  }
 });
--- a/devtools/client/netmonitor/test/browser_net_cause.js
+++ b/devtools/client/netmonitor/test/browser_net_cause.js
@@ -11,18 +11,18 @@ const CAUSE_FILE_NAME = "html_cause-test
 const CAUSE_URL = EXAMPLE_URL + CAUSE_FILE_NAME;
 
 const EXPECTED_REQUESTS = [
   {
     method: "GET",
     url: CAUSE_URL,
     causeType: "document",
     causeUri: "",
-    // The document load is from JS function in e10s, native in non-e10s
-    stack: !gMultiProcessBrowser
+    // The document load has internal privileged JS code on the stack
+    stack: true
   },
   {
     method: "GET",
     url: EXAMPLE_URL + "stylesheet_request",
     causeType: "stylesheet",
     causeUri: CAUSE_URL,
     stack: false
   },
@@ -72,31 +72,31 @@ const EXPECTED_REQUESTS = [
     method: "POST",
     url: EXAMPLE_URL + "beacon_request",
     causeType: "beacon",
     causeUri: CAUSE_URL,
     stack: [{ fn: "performBeaconRequest", file: CAUSE_FILE_NAME, line: 30 }]
   },
 ];
 
-var test = Task.async(function* () {
+add_task(function* () {
   // the initNetMonitor function clears the network request list after the
   // page is loaded. That's why we first load a bogus page from SIMPLE_URL,
   // and only then load the real thing from CAUSE_URL - we want to catch
   // all the requests the page is making, not only the XHRs.
   // We can't use about:blank here, because initNetMonitor checks that the
   // page has actually made at least one request.
-  let [, debuggee, monitor] = yield initNetMonitor(SIMPLE_URL);
+  let [tab, , monitor] = yield initNetMonitor(SIMPLE_URL);
   let { $, NetMonitorView } = monitor.panelWin;
   let { RequestsMenu } = NetMonitorView;
   RequestsMenu.lazyUpdate = false;
 
-  debuggee.location = CAUSE_URL;
-
-  yield waitForNetworkEvents(monitor, EXPECTED_REQUESTS.length);
+  let wait = waitForNetworkEvents(monitor, EXPECTED_REQUESTS.length);
+  tab.linkedBrowser.loadURI(CAUSE_URL);
+  yield wait;
 
   is(RequestsMenu.itemCount, EXPECTED_REQUESTS.length,
     "All the page events should be recorded.");
 
   EXPECTED_REQUESTS.forEach((spec, i) => {
     let { method, url, causeType, causeUri, stack } = spec;
 
     let requestItem = RequestsMenu.getItemAtIndex(i);
@@ -136,10 +136,9 @@ var test = Task.async(function* () {
   expectedOrder.forEach((expectedCause, i) => {
     let { target } = RequestsMenu.getItemAtIndex(i);
     let causeLabel = target.querySelector(".requests-menu-cause-label");
     let cause = causeLabel.getAttribute("value");
     is(cause, expectedCause, `The request #${i} has the expected cause after sorting`);
   });
 
   yield teardown(monitor);
-  finish();
 });
--- a/devtools/client/netmonitor/test/browser_net_cause_redirect.js
+++ b/devtools/client/netmonitor/test/browser_net_cause_redirect.js
@@ -3,32 +3,33 @@
 
 "use strict";
 
 /**
  * Tests if request JS stack is property reported if the request is internally
  * redirected without hitting the network (HSTS is one of such cases)
  */
 
-var test = Task.async(function* () {
+add_task(function* () {
   const EXPECTED_REQUESTS = [
     // Request to HTTP URL, redirects to HTTPS, has callstack
     { status: 302, hasStack: true },
     // Serves HTTPS, sets the Strict-Transport-Security header, no stack
     { status: 200, hasStack: false },
     // Second request to HTTP redirects to HTTPS internally
     { status: 200, hasStack: true },
   ];
 
-  let [, debuggee, monitor] = yield initNetMonitor(CUSTOM_GET_URL);
+  let [tab, , monitor] = yield initNetMonitor(CUSTOM_GET_URL);
   let { RequestsMenu } = monitor.panelWin.NetMonitorView;
   RequestsMenu.lazyUpdate = false;
 
-  debuggee.performRequests(2, HSTS_SJS);
-  yield waitForNetworkEvents(monitor, EXPECTED_REQUESTS.length);
+  let wait = waitForNetworkEvents(monitor, EXPECTED_REQUESTS.length);
+  yield performRequests(2, HSTS_SJS);
+  yield wait;
 
   EXPECTED_REQUESTS.forEach(({status, hasStack}, i) => {
     let { attachment } = RequestsMenu.getItemAtIndex(i);
 
     is(attachment.status, status, `Request #${i} has the expected status`);
 
     let { stacktrace } = attachment.cause;
     let stackLen = stacktrace ? stacktrace.length : 0;
@@ -37,14 +38,20 @@ var test = Task.async(function* () {
       ok(stacktrace, `Request #${i} has a stacktrace`);
       ok(stackLen > 0, `Request #${i} has a stacktrace with ${stackLen} items`);
     } else {
       is(stackLen, 0, `Request #${i} has an empty stacktrace`);
     }
   });
 
   // Send a request to reset the HSTS policy to state before the test
-  debuggee.performRequests(1, HSTS_SJS + "?reset");
-  yield waitForNetworkEvents(monitor, 1);
+  wait = waitForNetworkEvents(monitor, 1);
+  yield performRequests(1, HSTS_SJS + "?reset");
+  yield wait;
 
   yield teardown(monitor);
-  finish();
+
+  function performRequests(count, url) {
+    return ContentTask.spawn(tab.linkedBrowser, { count, url }, function* (args) {
+      content.wrappedJSObject.performRequests(args.count, args.url);
+    });
+  }
 });
--- a/devtools/client/netmonitor/test/browser_net_charts-01.js
+++ b/devtools/client/netmonitor/test/browser_net_charts-01.js
@@ -1,77 +1,73 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// /////////////////
-//
-// Whitelisting this test.
-// As part of bug 1077403, the leaking uncaught rejection should be fixed.
-//
-thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: can't convert undefined to object");
+"use strict";
 
 /**
  * Makes sure Pie Charts have the right internal structure.
  */
 
-function test() {
-  initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [, , monitor] = yield initNetMonitor(SIMPLE_URL);
+  info("Starting test... ");
 
-    let { document, Chart } = aMonitor.panelWin;
-    let container = document.createElement("box");
+  let { document, Chart } = monitor.panelWin;
 
-    let pie = Chart.Pie(document, {
-      width: 100,
-      height: 100,
-      data: [{
-        size: 1,
-        label: "foo"
-      }, {
-        size: 2,
-        label: "bar"
-      }, {
-        size: 3,
-        label: "baz"
-      }]
-    });
+  let pie = Chart.Pie(document, {
+    width: 100,
+    height: 100,
+    data: [{
+      size: 1,
+      label: "foo"
+    }, {
+      size: 2,
+      label: "bar"
+    }, {
+      size: 3,
+      label: "baz"
+    }]
+  });
 
-    let node = pie.node;
-    let slices = node.querySelectorAll(".pie-chart-slice.chart-colored-blob");
-    let labels = node.querySelectorAll(".pie-chart-label");
+  let node = pie.node;
+  let slices = node.querySelectorAll(".pie-chart-slice.chart-colored-blob");
+  let labels = node.querySelectorAll(".pie-chart-label");
 
-    ok(node.classList.contains("pie-chart-container") &&
-       node.classList.contains("generic-chart-container"),
-      "A pie chart container was created successfully.");
+  ok(node.classList.contains("pie-chart-container") &&
+     node.classList.contains("generic-chart-container"),
+    "A pie chart container was created successfully.");
 
-    is(slices.length, 3,
-      "There should be 3 pie chart slices created.");
-    ok(slices[0].getAttribute("d").match(/\s*M 50,50 L 49\.\d+,97\.\d+ A 47\.5,47\.5 0 0 1 49\.\d+,2\.5\d* Z/),
-      "The first slice has the correct data.");
-    ok(slices[1].getAttribute("d").match(/\s*M 50,50 L 91\.\d+,26\.\d+ A 47\.5,47\.5 0 0 1 49\.\d+,97\.\d+ Z/),
-      "The second slice has the correct data.");
-    ok(slices[2].getAttribute("d").match(/\s*M 50,50 L 50\.\d+,2\.5\d* A 47\.5,47\.5 0 0 1 91\.\d+,26\.\d+ Z/),
-      "The third slice has the correct data.");
+  is(slices.length, 3,
+    "There should be 3 pie chart slices created.");
+  ok(slices[0].getAttribute("d").match(
+    /\s*M 50,50 L 49\.\d+,97\.\d+ A 47\.5,47\.5 0 0 1 49\.\d+,2\.5\d* Z/),
+    "The first slice has the correct data.");
+  ok(slices[1].getAttribute("d").match(
+    /\s*M 50,50 L 91\.\d+,26\.\d+ A 47\.5,47\.5 0 0 1 49\.\d+,97\.\d+ Z/),
+    "The second slice has the correct data.");
+  ok(slices[2].getAttribute("d").match(
+    /\s*M 50,50 L 50\.\d+,2\.5\d* A 47\.5,47\.5 0 0 1 91\.\d+,26\.\d+ Z/),
+    "The third slice has the correct data.");
 
-    ok(slices[0].hasAttribute("largest"),
-      "The first slice should be the largest one.");
-    ok(slices[2].hasAttribute("smallest"),
-      "The third slice should be the smallest one.");
+  ok(slices[0].hasAttribute("largest"),
+    "The first slice should be the largest one.");
+  ok(slices[2].hasAttribute("smallest"),
+    "The third slice should be the smallest one.");
 
-    ok(slices[0].getAttribute("name"), "baz",
-      "The first slice's name is correct.");
-    ok(slices[1].getAttribute("name"), "bar",
-      "The first slice's name is correct.");
-    ok(slices[2].getAttribute("name"), "foo",
-      "The first slice's name is correct.");
+  ok(slices[0].getAttribute("name"), "baz",
+    "The first slice's name is correct.");
+  ok(slices[1].getAttribute("name"), "bar",
+    "The first slice's name is correct.");
+  ok(slices[2].getAttribute("name"), "foo",
+    "The first slice's name is correct.");
 
-    is(labels.length, 3,
-      "There should be 3 pie chart labels created.");
-    is(labels[0].textContent, "baz",
-      "The first label's text is correct.");
-    is(labels[1].textContent, "bar",
-      "The first label's text is correct.");
-    is(labels[2].textContent, "foo",
-      "The first label's text is correct.");
+  is(labels.length, 3,
+    "There should be 3 pie chart labels created.");
+  is(labels[0].textContent, "baz",
+    "The first label's text is correct.");
+  is(labels[1].textContent, "bar",
+    "The first label's text is correct.");
+  is(labels[2].textContent, "foo",
+    "The first label's text is correct.");
 
-    teardown(aMonitor).then(finish);
-  });
-}
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/browser_net_charts-02.js
+++ b/devtools/client/netmonitor/test/browser_net_charts-02.js
@@ -1,49 +1,47 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Makes sure Pie Charts have the right internal structure when
  * initialized with empty data.
  */
 
-function test() {
-  initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [, , monitor] = yield initNetMonitor(SIMPLE_URL);
+  info("Starting test... ");
 
-    let { document, L10N, Chart } = aMonitor.panelWin;
-    let container = document.createElement("box");
+  let { document, L10N, Chart } = monitor.panelWin;
 
-    let pie = Chart.Pie(document, {
-      data: null,
-      width: 100,
-      height: 100
-    });
+  let pie = Chart.Pie(document, {
+    data: null,
+    width: 100,
+    height: 100
+  });
 
-    let node = pie.node;
-    let slices = node.querySelectorAll(".pie-chart-slice.chart-colored-blob");
-    let labels = node.querySelectorAll(".pie-chart-label");
-
-    ok(node.classList.contains("pie-chart-container") &&
-       node.classList.contains("generic-chart-container"),
-      "A pie chart container was created successfully.");
+  let node = pie.node;
+  let slices = node.querySelectorAll(".pie-chart-slice.chart-colored-blob");
+  let labels = node.querySelectorAll(".pie-chart-label");
 
-    is(slices.length, 1,
-      "There should be 1 pie chart slice created.");
-    ok(slices[0].getAttribute("d").match(/\s*M 50,50 L 50\.\d+,2\.5\d* A 47\.5,47\.5 0 1 1 49\.\d+,2\.5\d* Z/),
-      "The first slice has the correct data.");
+  ok(node.classList.contains("pie-chart-container") &&
+     node.classList.contains("generic-chart-container"),
+    "A pie chart container was created successfully.");
+
+  is(slices.length, 1, "There should be 1 pie chart slice created.");
+  ok(slices[0].getAttribute("d").match(
+    /\s*M 50,50 L 50\.\d+,2\.5\d* A 47\.5,47\.5 0 1 1 49\.\d+,2\.5\d* Z/),
+    "The first slice has the correct data.");
 
-    ok(slices[0].hasAttribute("largest"),
-      "The first slice should be the largest one.");
-    ok(slices[0].hasAttribute("smallest"),
-      "The first slice should also be the smallest one.");
-    ok(slices[0].getAttribute("name"), L10N.getStr("pieChart.loading"),
-      "The first slice's name is correct.");
+  ok(slices[0].hasAttribute("largest"),
+    "The first slice should be the largest one.");
+  ok(slices[0].hasAttribute("smallest"),
+    "The first slice should also be the smallest one.");
+  ok(slices[0].getAttribute("name"), L10N.getStr("pieChart.loading"),
+    "The first slice's name is correct.");
 
-    is(labels.length, 1,
-      "There should be 1 pie chart label created.");
-    is(labels[0].textContent, "Loading",
-      "The first label's text is correct.");
+  is(labels.length, 1, "There should be 1 pie chart label created.");
+  is(labels[0].textContent, "Loading", "The first label's text is correct.");
 
-    teardown(aMonitor).then(finish);
-  });
-}
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/browser_net_charts-03.js
+++ b/devtools/client/netmonitor/test/browser_net_charts-03.js
@@ -1,103 +1,104 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Makes sure Table Charts have the right internal structure.
  */
 
-function test() {
-  initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [, , monitor] = yield initNetMonitor(SIMPLE_URL);
+  info("Starting test... ");
 
-    let { document, L10N, Chart } = aMonitor.panelWin;
-    let container = document.createElement("box");
+  let { document, L10N, Chart } = monitor.panelWin;
 
-    let table = Chart.Table(document, {
-      title: "Table title",
-      data: [{
-        label1: 1,
-        label2: 11.1
-      }, {
-        label1: 2,
-        label2: 12.2
-      }, {
-        label1: 3,
-        label2: 13.3
-      }],
-      strings: {
-        label2: (value, index) => value + ["foo", "bar", "baz"][index]
-      },
-      totals: {
-        label1: value => "Hello " + L10N.numberWithDecimals(value, 2),
-        label2: value => "World " + L10N.numberWithDecimals(value, 2)
-      }
-    });
+  let table = Chart.Table(document, {
+    title: "Table title",
+    data: [{
+      label1: 1,
+      label2: 11.1
+    }, {
+      label1: 2,
+      label2: 12.2
+    }, {
+      label1: 3,
+      label2: 13.3
+    }],
+    strings: {
+      label2: (value, index) => value + ["foo", "bar", "baz"][index]
+    },
+    totals: {
+      label1: value => "Hello " + L10N.numberWithDecimals(value, 2),
+      label2: value => "World " + L10N.numberWithDecimals(value, 2)
+    }
+  });
 
-    let node = table.node;
-    let title = node.querySelector(".table-chart-title");
-    let grid = node.querySelector(".table-chart-grid");
-    let totals = node.querySelector(".table-chart-totals");
-    let rows = grid.querySelectorAll(".table-chart-row");
-    let sums = node.querySelectorAll(".table-chart-summary-label");
+  let node = table.node;
+  let title = node.querySelector(".table-chart-title");
+  let grid = node.querySelector(".table-chart-grid");
+  let totals = node.querySelector(".table-chart-totals");
+  let rows = grid.querySelectorAll(".table-chart-row");
+  let sums = node.querySelectorAll(".table-chart-summary-label");
 
-    ok(node.classList.contains("table-chart-container") &&
-       node.classList.contains("generic-chart-container"),
-      "A table chart container was created successfully.");
+  ok(node.classList.contains("table-chart-container") &&
+     node.classList.contains("generic-chart-container"),
+    "A table chart container was created successfully.");
 
-    ok(title,
-      "A title node was created successfully.");
-    is(title.getAttribute("value"), "Table title",
-      "The title node displays the correct text.");
+  ok(title, "A title node was created successfully.");
+  is(title.getAttribute("value"), "Table title",
+    "The title node displays the correct text.");
 
-    is(rows.length, 3,
-      "There should be 3 table chart rows created.");
+  is(rows.length, 3, "There should be 3 table chart rows created.");
 
-    ok(rows[0].querySelector(".table-chart-row-box.chart-colored-blob"),
-      "A colored blob exists for the firt row.");
-    is(rows[0].querySelectorAll("label")[0].getAttribute("name"), "label1",
-      "The first column of the first row exists.");
-    is(rows[0].querySelectorAll("label")[1].getAttribute("name"), "label2",
-      "The second column of the first row exists.");
-    is(rows[0].querySelectorAll("label")[0].getAttribute("value"), "1",
-      "The first column of the first row displays the correct text.");
-    is(rows[0].querySelectorAll("label")[1].getAttribute("value"), "11.1foo",
-      "The second column of the first row displays the correct text.");
+  ok(rows[0].querySelector(".table-chart-row-box.chart-colored-blob"),
+    "A colored blob exists for the firt row.");
+  is(rows[0].querySelectorAll("label")[0].getAttribute("name"), "label1",
+    "The first column of the first row exists.");
+  is(rows[0].querySelectorAll("label")[1].getAttribute("name"), "label2",
+    "The second column of the first row exists.");
+  is(rows[0].querySelectorAll("label")[0].getAttribute("value"), "1",
+    "The first column of the first row displays the correct text.");
+  is(rows[0].querySelectorAll("label")[1].getAttribute("value"), "11.1foo",
+    "The second column of the first row displays the correct text.");
 
-    ok(rows[1].querySelector(".table-chart-row-box.chart-colored-blob"),
-      "A colored blob exists for the second row.");
-    is(rows[1].querySelectorAll("label")[0].getAttribute("name"), "label1",
-      "The first column of the second row exists.");
-    is(rows[1].querySelectorAll("label")[1].getAttribute("name"), "label2",
-      "The second column of the second row exists.");
-    is(rows[1].querySelectorAll("label")[0].getAttribute("value"), "2",
-      "The first column of the second row displays the correct text.");
-    is(rows[1].querySelectorAll("label")[1].getAttribute("value"), "12.2bar",
-      "The second column of the first row displays the correct text.");
+  ok(rows[1].querySelector(".table-chart-row-box.chart-colored-blob"),
+    "A colored blob exists for the second row.");
+  is(rows[1].querySelectorAll("label")[0].getAttribute("name"), "label1",
+    "The first column of the second row exists.");
+  is(rows[1].querySelectorAll("label")[1].getAttribute("name"), "label2",
+    "The second column of the second row exists.");
+  is(rows[1].querySelectorAll("label")[0].getAttribute("value"), "2",
+    "The first column of the second row displays the correct text.");
+  is(rows[1].querySelectorAll("label")[1].getAttribute("value"), "12.2bar",
+    "The second column of the first row displays the correct text.");
 
-    ok(rows[2].querySelector(".table-chart-row-box.chart-colored-blob"),
-      "A colored blob exists for the third row.");
-    is(rows[2].querySelectorAll("label")[0].getAttribute("name"), "label1",
-      "The first column of the third row exists.");
-    is(rows[2].querySelectorAll("label")[1].getAttribute("name"), "label2",
-      "The second column of the third row exists.");
-    is(rows[2].querySelectorAll("label")[0].getAttribute("value"), "3",
-      "The first column of the third row displays the correct text.");
-    is(rows[2].querySelectorAll("label")[1].getAttribute("value"), "13.3baz",
-      "The second column of the third row displays the correct text.");
+  ok(rows[2].querySelector(".table-chart-row-box.chart-colored-blob"),
+    "A colored blob exists for the third row.");
+  is(rows[2].querySelectorAll("label")[0].getAttribute("name"), "label1",
+    "The first column of the third row exists.");
+  is(rows[2].querySelectorAll("label")[1].getAttribute("name"), "label2",
+    "The second column of the third row exists.");
+  is(rows[2].querySelectorAll("label")[0].getAttribute("value"), "3",
+    "The first column of the third row displays the correct text.");
+  is(rows[2].querySelectorAll("label")[1].getAttribute("value"), "13.3baz",
+    "The second column of the third row displays the correct text.");
 
-    is(sums.length, 2,
-      "There should be 2 total summaries created.");
+  is(sums.length, 2, "There should be 2 total summaries created.");
 
-    is(totals.querySelectorAll(".table-chart-summary-label")[0].getAttribute("name"), "label1",
-      "The first sum's type is correct.");
-    is(totals.querySelectorAll(".table-chart-summary-label")[0].getAttribute("value"), "Hello 6",
-      "The first sum's value is correct.");
+  is(totals.querySelectorAll(".table-chart-summary-label")[0].getAttribute("name"),
+    "label1",
+    "The first sum's type is correct.");
+  is(totals.querySelectorAll(".table-chart-summary-label")[0].getAttribute("value"),
+    "Hello 6",
+    "The first sum's value is correct.");
 
-    is(totals.querySelectorAll(".table-chart-summary-label")[1].getAttribute("name"), "label2",
-      "The second sum's type is correct.");
-    is(totals.querySelectorAll(".table-chart-summary-label")[1].getAttribute("value"), "World 36.60",
-      "The second sum's value is correct.");
+  is(totals.querySelectorAll(".table-chart-summary-label")[1].getAttribute("name"),
+    "label2",
+    "The second sum's type is correct.");
+  is(totals.querySelectorAll(".table-chart-summary-label")[1].getAttribute("value"),
+    "World 36.60",
+    "The second sum's value is correct.");
 
-    teardown(aMonitor).then(finish);
-  });
-}
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/browser_net_charts-04.js
+++ b/devtools/client/netmonitor/test/browser_net_charts-04.js
@@ -1,70 +1,73 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Makes sure Pie Charts have the right internal structure when
  * initialized with empty data.
  */
 
-function test() {
-  initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [, , monitor] = yield initNetMonitor(SIMPLE_URL);
+  info("Starting test... ");
+
+  let { document, L10N, Chart } = monitor.panelWin;
 
-    let { document, L10N, Chart } = aMonitor.panelWin;
-    let container = document.createElement("box");
+  let table = Chart.Table(document, {
+    title: "Table title",
+    data: null,
+    totals: {
+      label1: value => "Hello " + L10N.numberWithDecimals(value, 2),
+      label2: value => "World " + L10N.numberWithDecimals(value, 2)
+    }
+  });
 
-    let table = Chart.Table(document, {
-      title: "Table title",
-      data: null,
-      totals: {
-        label1: value => "Hello " + L10N.numberWithDecimals(value, 2),
-        label2: value => "World " + L10N.numberWithDecimals(value, 2)
-      }
-    });
+  let node = table.node;
+  let title = node.querySelector(".table-chart-title");
+  let grid = node.querySelector(".table-chart-grid");
+  let totals = node.querySelector(".table-chart-totals");
+  let rows = grid.querySelectorAll(".table-chart-row");
+  let sums = node.querySelectorAll(".table-chart-summary-label");
 
-    let node = table.node;
-    let title = node.querySelector(".table-chart-title");
-    let grid = node.querySelector(".table-chart-grid");
-    let totals = node.querySelector(".table-chart-totals");
-    let rows = grid.querySelectorAll(".table-chart-row");
-    let sums = node.querySelectorAll(".table-chart-summary-label");
+  ok(node.classList.contains("table-chart-container") &&
+     node.classList.contains("generic-chart-container"),
+    "A table chart container was created successfully.");
 
-    ok(node.classList.contains("table-chart-container") &&
-       node.classList.contains("generic-chart-container"),
-      "A table chart container was created successfully.");
+  ok(title, "A title node was created successfully.");
+  is(title.getAttribute("value"), "Table title",
+    "The title node displays the correct text.");
+
+  is(rows.length, 1, "There should be 1 table chart row created.");
 
-    ok(title,
-      "A title node was created successfully.");
-    is(title.getAttribute("value"), "Table title",
-      "The title node displays the correct text.");
+  ok(rows[0].querySelector(".table-chart-row-box.chart-colored-blob"),
+    "A colored blob exists for the firt row.");
+  is(rows[0].querySelectorAll("label")[0].getAttribute("name"), "size",
+    "The first column of the first row exists.");
+  is(rows[0].querySelectorAll("label")[1].getAttribute("name"), "label",
+    "The second column of the first row exists.");
+  is(rows[0].querySelectorAll("label")[0].getAttribute("value"), "",
+    "The first column of the first row displays the correct text.");
+  is(rows[0].querySelectorAll("label")[1].getAttribute("value"),
+    L10N.getStr("tableChart.loading"),
+    "The second column of the first row displays the correct text.");
 
-    is(rows.length, 1,
-      "There should be 1 table chart row created.");
+  is(sums.length, 2,
+    "There should be 2 total summaries created.");
 
-    ok(rows[0].querySelector(".table-chart-row-box.chart-colored-blob"),
-      "A colored blob exists for the firt row.");
-    is(rows[0].querySelectorAll("label")[0].getAttribute("name"), "size",
-      "The first column of the first row exists.");
-    is(rows[0].querySelectorAll("label")[1].getAttribute("name"), "label",
-      "The second column of the first row exists.");
-    is(rows[0].querySelectorAll("label")[0].getAttribute("value"), "",
-      "The first column of the first row displays the correct text.");
-    is(rows[0].querySelectorAll("label")[1].getAttribute("value"), L10N.getStr("tableChart.loading"),
-      "The second column of the first row displays the correct text.");
-
-    is(sums.length, 2,
-      "There should be 2 total summaries created.");
+  is(totals.querySelectorAll(".table-chart-summary-label")[0].getAttribute("name"),
+    "label1",
+    "The first sum's type is correct.");
+  is(totals.querySelectorAll(".table-chart-summary-label")[0].getAttribute("value"),
+    "Hello 0",
+    "The first sum's value is correct.");
 
-    is(totals.querySelectorAll(".table-chart-summary-label")[0].getAttribute("name"), "label1",
-      "The first sum's type is correct.");
-    is(totals.querySelectorAll(".table-chart-summary-label")[0].getAttribute("value"), "Hello 0",
-      "The first sum's value is correct.");
+  is(totals.querySelectorAll(".table-chart-summary-label")[1].getAttribute("name"),
+    "label2",
+    "The second sum's type is correct.");
+  is(totals.querySelectorAll(".table-chart-summary-label")[1].getAttribute("value"),
+    "World 0",
+    "The second sum's value is correct.");
 
-    is(totals.querySelectorAll(".table-chart-summary-label")[1].getAttribute("name"), "label2",
-      "The second sum's type is correct.");
-    is(totals.querySelectorAll(".table-chart-summary-label")[1].getAttribute("value"), "World 0",
-      "The second sum's value is correct.");
-
-    teardown(aMonitor).then(finish);
-  });
-}
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/browser_net_charts-05.js
+++ b/devtools/client/netmonitor/test/browser_net_charts-05.js
@@ -1,63 +1,59 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Makes sure Pie+Table Charts have the right internal structure.
  */
 
-function test() {
-  initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
-
-    let { document, L10N, Chart } = aMonitor.panelWin;
-    let container = document.createElement("box");
+add_task(function* () {
+  let [, , monitor] = yield initNetMonitor(SIMPLE_URL);
+  info("Starting test... ");
 
-    let chart = Chart.PieTable(document, {
-      title: "Table title",
-      data: [{
-        size: 1,
-        label: 11.1
-      }, {
-        size: 2,
-        label: 12.2
-      }, {
-        size: 3,
-        label: 13.3
-      }],
-      strings: {
-        label2: (value, index) => value + ["foo", "bar", "baz"][index]
-      },
-      totals: {
-        size: value => "Hello " + L10N.numberWithDecimals(value, 2),
-        label: value => "World " + L10N.numberWithDecimals(value, 2)
-      }
-    });
+  let { document, L10N, Chart } = monitor.panelWin;
 
-    ok(chart.pie, "The pie chart proxy is accessible.");
-    ok(chart.table, "The table chart proxy is accessible.");
-
-    let node = chart.node;
-    let slices = node.querySelectorAll(".pie-chart-slice");
-    let rows = node.querySelectorAll(".table-chart-row");
-    let sums = node.querySelectorAll(".table-chart-summary-label");
-
-    ok(node.classList.contains("pie-table-chart-container"),
-      "A pie+table chart container was created successfully.");
+  let chart = Chart.PieTable(document, {
+    title: "Table title",
+    data: [{
+      size: 1,
+      label: 11.1
+    }, {
+      size: 2,
+      label: 12.2
+    }, {
+      size: 3,
+      label: 13.3
+    }],
+    strings: {
+      label2: (value, index) => value + ["foo", "bar", "baz"][index]
+    },
+    totals: {
+      size: value => "Hello " + L10N.numberWithDecimals(value, 2),
+      label: value => "World " + L10N.numberWithDecimals(value, 2)
+    }
+  });
 
-    ok(node.querySelector(".table-chart-title"),
-      "A title node was created successfully.");
-    ok(node.querySelector(".pie-chart-container"),
-      "A pie chart was created successfully.");
-    ok(node.querySelector(".table-chart-container"),
-      "A table chart was created successfully.");
+  ok(chart.pie, "The pie chart proxy is accessible.");
+  ok(chart.table, "The table chart proxy is accessible.");
+
+  let node = chart.node;
+  let rows = node.querySelectorAll(".table-chart-row");
+  let sums = node.querySelectorAll(".table-chart-summary-label");
+
+  ok(node.classList.contains("pie-table-chart-container"),
+    "A pie+table chart container was created successfully.");
 
-    is(rows.length, 3,
-      "There should be 3 pie chart slices created.");
-    is(rows.length, 3,
-      "There should be 3 table chart rows created.");
-    is(sums.length, 2,
-      "There should be 2 total summaries created.");
+  ok(node.querySelector(".table-chart-title"),
+    "A title node was created successfully.");
+  ok(node.querySelector(".pie-chart-container"),
+    "A pie chart was created successfully.");
+  ok(node.querySelector(".table-chart-container"),
+    "A table chart was created successfully.");
 
-    teardown(aMonitor).then(finish);
-  });
-}
+  is(rows.length, 3, "There should be 3 pie chart slices created.");
+  is(rows.length, 3, "There should be 3 table chart rows created.");
+  is(sums.length, 2, "There should be 2 total summaries created.");
+
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/browser_net_charts-06.js
+++ b/devtools/client/netmonitor/test/browser_net_charts-06.js
@@ -1,44 +1,45 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Makes sure Pie Charts correctly handle empty source data.
  */
 
-function test() {
-  initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [, , monitor] = yield initNetMonitor(SIMPLE_URL);
+  info("Starting test... ");
 
-    let { document, L10N, Chart } = aMonitor.panelWin;
-    let container = document.createElement("box");
+  let { document, L10N, Chart } = monitor.panelWin;
 
-    let pie = Chart.Pie(document, {
-      data: [],
-      width: 100,
-      height: 100
-    });
+  let pie = Chart.Pie(document, {
+    data: [],
+    width: 100,
+    height: 100
+  });
 
-    let node = pie.node;
-    let slices = node.querySelectorAll(".pie-chart-slice.chart-colored-blob");
-    let labels = node.querySelectorAll(".pie-chart-label");
+  let node = pie.node;
+  let slices = node.querySelectorAll(".pie-chart-slice.chart-colored-blob");
+  let labels = node.querySelectorAll(".pie-chart-label");
 
-    is(slices.length, 1,
-      "There should be 1 pie chart slice created.");
-    ok(slices[0].getAttribute("d").match(/\s*M 50,50 L 50\.\d+,2\.5\d* A 47\.5,47\.5 0 1 1 49\.\d+,2\.5\d* Z/),
-      "The slice has the correct data.");
+  is(slices.length, 1,
+    "There should be 1 pie chart slice created.");
+  ok(slices[0].getAttribute("d").match(
+    /\s*M 50,50 L 50\.\d+,2\.5\d* A 47\.5,47\.5 0 1 1 49\.\d+,2\.5\d* Z/),
+    "The slice has the correct data.");
 
-    ok(slices[0].hasAttribute("largest"),
-      "The slice should be the largest one.");
-    ok(slices[0].hasAttribute("smallest"),
-      "The slice should also be the smallest one.");
-    ok(slices[0].getAttribute("name"), L10N.getStr("pieChart.unavailable"),
-      "The slice's name is correct.");
+  ok(slices[0].hasAttribute("largest"),
+    "The slice should be the largest one.");
+  ok(slices[0].hasAttribute("smallest"),
+    "The slice should also be the smallest one.");
+  ok(slices[0].getAttribute("name"), L10N.getStr("pieChart.unavailable"),
+    "The slice's name is correct.");
 
-    is(labels.length, 1,
-      "There should be 1 pie chart label created.");
-    is(labels[0].textContent, "Empty",
-      "The label's text is correct.");
+  is(labels.length, 1,
+    "There should be 1 pie chart label created.");
+  is(labels[0].textContent, "Empty",
+    "The label's text is correct.");
 
-    teardown(aMonitor).then(finish);
-  });
-}
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/browser_net_charts-07.js
+++ b/devtools/client/netmonitor/test/browser_net_charts-07.js
@@ -1,58 +1,61 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Makes sure Table Charts correctly handle empty source data.
  */
 
-function test() {
-  initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [, , monitor] = yield initNetMonitor(SIMPLE_URL);
+  info("Starting test... ");
 
-    let { document, L10N, Chart } = aMonitor.panelWin;
-    let container = document.createElement("box");
+  let { document, L10N, Chart } = monitor.panelWin;
 
-    let table = Chart.Table(document, {
-      data: [],
-      totals: {
-        label1: value => "Hello " + L10N.numberWithDecimals(value, 2),
-        label2: value => "World " + L10N.numberWithDecimals(value, 2)
-      }
-    });
+  let table = Chart.Table(document, {
+    data: [],
+    totals: {
+      label1: value => "Hello " + L10N.numberWithDecimals(value, 2),
+      label2: value => "World " + L10N.numberWithDecimals(value, 2)
+    }
+  });
 
-    let node = table.node;
-    let grid = node.querySelector(".table-chart-grid");
-    let totals = node.querySelector(".table-chart-totals");
-    let rows = grid.querySelectorAll(".table-chart-row");
-    let sums = node.querySelectorAll(".table-chart-summary-label");
+  let node = table.node;
+  let grid = node.querySelector(".table-chart-grid");
+  let totals = node.querySelector(".table-chart-totals");
+  let rows = grid.querySelectorAll(".table-chart-row");
+  let sums = node.querySelectorAll(".table-chart-summary-label");
 
-    is(rows.length, 1,
-      "There should be 1 table chart row created.");
+  is(rows.length, 1, "There should be 1 table chart row created.");
 
-    ok(rows[0].querySelector(".table-chart-row-box.chart-colored-blob"),
-      "A colored blob exists for the firt row.");
-    is(rows[0].querySelectorAll("label")[0].getAttribute("name"), "size",
-      "The first column of the first row exists.");
-    is(rows[0].querySelectorAll("label")[1].getAttribute("name"), "label",
-      "The second column of the first row exists.");
-    is(rows[0].querySelectorAll("label")[0].getAttribute("value"), "",
-      "The first column of the first row displays the correct text.");
-    is(rows[0].querySelectorAll("label")[1].getAttribute("value"), L10N.getStr("tableChart.unavailable"),
-      "The second column of the first row displays the correct text.");
+  ok(rows[0].querySelector(".table-chart-row-box.chart-colored-blob"),
+    "A colored blob exists for the firt row.");
+  is(rows[0].querySelectorAll("label")[0].getAttribute("name"), "size",
+    "The first column of the first row exists.");
+  is(rows[0].querySelectorAll("label")[1].getAttribute("name"), "label",
+    "The second column of the first row exists.");
+  is(rows[0].querySelectorAll("label")[0].getAttribute("value"), "",
+    "The first column of the first row displays the correct text.");
+  is(rows[0].querySelectorAll("label")[1].getAttribute("value"),
+    L10N.getStr("tableChart.unavailable"),
+    "The second column of the first row displays the correct text.");
 
-    is(sums.length, 2,
-      "There should be 2 total summaries created.");
+  is(sums.length, 2, "There should be 2 total summaries created.");
 
-    is(totals.querySelectorAll(".table-chart-summary-label")[0].getAttribute("name"), "label1",
-      "The first sum's type is correct.");
-    is(totals.querySelectorAll(".table-chart-summary-label")[0].getAttribute("value"), "Hello 0",
-      "The first sum's value is correct.");
+  is(totals.querySelectorAll(".table-chart-summary-label")[0].getAttribute("name"),
+    "label1",
+    "The first sum's type is correct.");
+  is(totals.querySelectorAll(".table-chart-summary-label")[0].getAttribute("value"),
+    "Hello 0",
+    "The first sum's value is correct.");
 
-    is(totals.querySelectorAll(".table-chart-summary-label")[1].getAttribute("name"), "label2",
-      "The second sum's type is correct.");
-    is(totals.querySelectorAll(".table-chart-summary-label")[1].getAttribute("value"), "World 0",
-      "The second sum's value is correct.");
+  is(totals.querySelectorAll(".table-chart-summary-label")[1].getAttribute("name"),
+    "label2",
+    "The second sum's type is correct.");
+  is(totals.querySelectorAll(".table-chart-summary-label")[1].getAttribute("value"),
+    "World 0",
+    "The second sum's value is correct.");
 
-    teardown(aMonitor).then(finish);
-  });
-}
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/browser_net_clear.js
+++ b/devtools/client/netmonitor/test/browser_net_clear.js
@@ -1,76 +1,77 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Tests if the clear button empties the request menu.
  */
 
-function test() {
-  initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [tab, , monitor] = yield initNetMonitor(SIMPLE_URL);
+  info("Starting test... ");
 
-    let { document, $, NetMonitorView } = aMonitor.panelWin;
-    let { RequestsMenu } = NetMonitorView;
-    let detailsPane = $("#details-pane");
-    let detailsPaneToggleButton = $("#details-pane-toggle");
-    let clearButton = $("#requests-menu-clear-button");
+  let { $, NetMonitorView } = monitor.panelWin;
+  let { RequestsMenu } = NetMonitorView;
+  let detailsPane = $("#details-pane");
+  let detailsPaneToggleButton = $("#details-pane-toggle");
+  let clearButton = $("#requests-menu-clear-button");
 
-    RequestsMenu.lazyUpdate = false;
+  RequestsMenu.lazyUpdate = false;
 
-    // Make sure we start in a sane state
-    assertNoRequestState(RequestsMenu, detailsPaneToggleButton);
+  // Make sure we start in a sane state
+  assertNoRequestState(RequestsMenu, detailsPaneToggleButton);
 
-    // Load one request and assert it shows up in the lis
-    aMonitor.panelWin.once(aMonitor.panelWin.EVENTS.NETWORK_EVENT, () => {
-      assertSingleRequestState(RequestsMenu, detailsPaneToggleButton);
+  // Load one request and assert it shows up in the list
+  let networkEvent = monitor.panelWin.once(monitor.panelWin.EVENTS.NETWORK_EVENT);
+  tab.linkedBrowser.reload();
+  yield networkEvent;
 
-      // Click clear and make sure the requests are gone
-      EventUtils.sendMouseEvent({ type: "click" }, clearButton);
-      assertNoRequestState(RequestsMenu, detailsPaneToggleButton);
+  assertSingleRequestState();
 
-      // Load a second request and make sure they still show up
-      aMonitor.panelWin.once(aMonitor.panelWin.EVENTS.NETWORK_EVENT, () => {
-        assertSingleRequestState(RequestsMenu, detailsPaneToggleButton);
+  // Click clear and make sure the requests are gone
+  EventUtils.sendMouseEvent({ type: "click" }, clearButton);
+  assertNoRequestState();
 
-        // Make sure we can now open the details pane
-        NetMonitorView.toggleDetailsPane({ visible: true, animated: false });
-        ok(!detailsPane.classList.contains("pane-collapsed") &&
-          !detailsPaneToggleButton.classList.contains("pane-collapsed"),
-          "The details pane should be visible after clicking the toggle button.");
+  // Load a second request and make sure they still show up
+  networkEvent = monitor.panelWin.once(monitor.panelWin.EVENTS.NETWORK_EVENT);
+  tab.linkedBrowser.reload();
+  yield networkEvent;
+
+  assertSingleRequestState();
 
-        // Click clear and make sure the details pane closes
-        EventUtils.sendMouseEvent({ type: "click" }, clearButton);
-        assertNoRequestState(RequestsMenu, detailsPaneToggleButton);
-        ok(detailsPane.classList.contains("pane-collapsed") &&
-          detailsPaneToggleButton.classList.contains("pane-collapsed"),
-          "The details pane should not be visible clicking 'clear'.");
+  // Make sure we can now open the details pane
+  NetMonitorView.toggleDetailsPane({ visible: true, animated: false });
+  ok(!detailsPane.classList.contains("pane-collapsed") &&
+    !detailsPaneToggleButton.classList.contains("pane-collapsed"),
+    "The details pane should be visible after clicking the toggle button.");
 
-        teardown(aMonitor).then(finish);
-      });
+  // Click clear and make sure the details pane closes
+  EventUtils.sendMouseEvent({ type: "click" }, clearButton);
+  assertNoRequestState();
+  ok(detailsPane.classList.contains("pane-collapsed") &&
+    detailsPaneToggleButton.classList.contains("pane-collapsed"),
+    "The details pane should not be visible clicking 'clear'.");
 
-      aDebuggee.location.reload();
-    });
-
-    aDebuggee.location.reload();
-  });
+  return teardown(monitor);
 
   /**
    * Asserts the state of the network monitor when one request has loaded
    */
-  function assertSingleRequestState(RequestsMenu, detailsPaneToggleButton) {
+  function assertSingleRequestState() {
     is(RequestsMenu.itemCount, 1,
       "The request menu should have one item at this point.");
     is(detailsPaneToggleButton.hasAttribute("disabled"), false,
       "The pane toggle button should be enabled after a request is made.");
   }
 
   /**
    * Asserts the state of the network monitor when no requests have loaded
    */
-  function assertNoRequestState(RequestsMenu, detailsPaneToggleButton) {
+  function assertNoRequestState() {
     is(RequestsMenu.itemCount, 0,
       "The request menu should be empty at this point.");
     is(detailsPaneToggleButton.hasAttribute("disabled"), true,
       "The pane toggle button should be disabled when the request menu is cleared.");
   }
-}
+});
--- a/devtools/client/netmonitor/test/browser_net_complex-params.js
+++ b/devtools/client/netmonitor/test/browser_net_complex-params.js
@@ -1,182 +1,193 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Tests whether complex request params and payload sent via POST are
  * displayed correctly.
  */
 
-function test() {
-  initNetMonitor(PARAMS_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [tab, , monitor] = yield initNetMonitor(PARAMS_URL);
+  info("Starting test... ");
 
-    let { document, L10N, EVENTS, Editor, NetMonitorView } = aMonitor.panelWin;
-    let { RequestsMenu, NetworkDetails } = NetMonitorView;
+  let { document, L10N, EVENTS, Editor, NetMonitorView } = monitor.panelWin;
+  let { RequestsMenu, NetworkDetails } = NetMonitorView;
 
-    RequestsMenu.lazyUpdate = false;
-    NetworkDetails._params.lazyEmpty = false;
+  RequestsMenu.lazyUpdate = false;
+  NetworkDetails._params.lazyEmpty = false;
 
-    Task.spawn(function* () {
-      yield waitForNetworkEvents(aMonitor, 1, 6);
-
-      EventUtils.sendMouseEvent({ type: "mousedown" },
-        document.getElementById("details-pane-toggle"));
-      EventUtils.sendMouseEvent({ type: "mousedown" },
-        document.querySelectorAll("#details-pane tab")[2]);
+  let wait = waitForNetworkEvents(monitor, 1, 6);
+  yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
+    content.wrappedJSObject.performRequests();
+  });
+  yield wait;
 
-      yield waitFor(aMonitor.panelWin, EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
-      yield testParamsTab1("a", '""', '{ "foo": "bar" }', '""');
-
-      RequestsMenu.selectedIndex = 1;
-      yield waitFor(aMonitor.panelWin, EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
-      yield testParamsTab1("a", '"b"', '{ "foo": "bar" }', '""');
-
-      RequestsMenu.selectedIndex = 2;
-      yield waitFor(aMonitor.panelWin, EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
-      yield testParamsTab1("a", '"b"', "foo", '"bar"');
+  let onEvent = monitor.panelWin.once(EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
+  EventUtils.sendMouseEvent({ type: "mousedown" },
+    document.getElementById("details-pane-toggle"));
+  EventUtils.sendMouseEvent({ type: "mousedown" },
+    document.querySelectorAll("#details-pane tab")[2]);
+  yield onEvent;
+  yield testParamsTab1("a", '""', '{ "foo": "bar" }', '""');
 
-      RequestsMenu.selectedIndex = 3;
-      yield waitFor(aMonitor.panelWin, EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
-      yield testParamsTab2("a", '""', '{ "foo": "bar" }', "js");
+  onEvent = monitor.panelWin.once(EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
+  RequestsMenu.selectedIndex = 1;
+  yield onEvent;
+  yield testParamsTab1("a", '"b"', '{ "foo": "bar" }', '""');
 
-      RequestsMenu.selectedIndex = 4;
-      yield waitFor(aMonitor.panelWin, EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
-      yield testParamsTab2("a", '"b"', '{ "foo": "bar" }', "js");
+  onEvent = monitor.panelWin.once(EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
+  RequestsMenu.selectedIndex = 2;
+  yield onEvent;
+  yield testParamsTab1("a", '"b"', "foo", '"bar"');
 
-      RequestsMenu.selectedIndex = 5;
-      yield waitFor(aMonitor.panelWin, EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
-      yield testParamsTab2("a", '"b"', "?foo=bar", "text");
+  onEvent = monitor.panelWin.once(EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
+  RequestsMenu.selectedIndex = 3;
+  yield onEvent;
+  yield testParamsTab2("a", '""', '{ "foo": "bar" }', "js");
 
-      RequestsMenu.selectedIndex = 6;
-      yield waitFor(aMonitor.panelWin, EVENTS.SIDEBAR_POPULATED);
-      yield testParamsTab3("a", '"b"');
+  onEvent = monitor.panelWin.once(EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
+  RequestsMenu.selectedIndex = 4;
+  yield onEvent;
+  yield testParamsTab2("a", '"b"', '{ "foo": "bar" }', "js");
 
-      yield teardown(aMonitor);
-      finish();
-    });
+  onEvent = monitor.panelWin.once(EVENTS.REQUEST_POST_PARAMS_DISPLAYED);
+  RequestsMenu.selectedIndex = 5;
+  yield onEvent;
+  yield testParamsTab2("a", '"b"', "?foo=bar", "text");
 
-    function testParamsTab1(
-      aQueryStringParamName, aQueryStringParamValue, aFormDataParamName, aFormDataParamValue)
-    {
-      let tab = document.querySelectorAll("#details-pane tab")[2];
-      let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2];
+  onEvent = monitor.panelWin.once(EVENTS.SIDEBAR_POPULATED);
+  RequestsMenu.selectedIndex = 6;
+  yield onEvent;
+  yield testParamsTab3("a", '"b"');
 
-      is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
-        "The number of param scopes displayed in this tabpanel is incorrect.");
-      is(tabpanel.querySelectorAll(".variable-or-property").length, 2,
-        "The number of param values displayed in this tabpanel is incorrect.");
-      is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
-        "The empty notice should not be displayed in this tabpanel.");
+  yield teardown(monitor);
+
+  function testParamsTab1(queryStringParamName, queryStringParamValue,
+                          formDataParamName, formDataParamValue) {
+    let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2];
 
-      is(tabpanel.querySelector("#request-params-box")
-        .hasAttribute("hidden"), false,
-        "The request params box should not be hidden.");
-      is(tabpanel.querySelector("#request-post-data-textarea-box")
-        .hasAttribute("hidden"), true,
-        "The request post data textarea box should be hidden.");
-
-      let paramsScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
-      let formDataScope = tabpanel.querySelectorAll(".variables-view-scope")[1];
+    is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
+      "The number of param scopes displayed in this tabpanel is incorrect.");
+    is(tabpanel.querySelectorAll(".variable-or-property").length, 2,
+      "The number of param values displayed in this tabpanel is incorrect.");
+    is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
+      "The empty notice should not be displayed in this tabpanel.");
 
-      is(paramsScope.querySelector(".name").getAttribute("value"),
-        L10N.getStr("paramsQueryString"),
-        "The params scope doesn't have the correct title.");
-      is(formDataScope.querySelector(".name").getAttribute("value"),
-        L10N.getStr("paramsFormData"),
-        "The form data scope doesn't have the correct title.");
+    is(tabpanel.querySelector("#request-params-box")
+      .hasAttribute("hidden"), false,
+      "The request params box should not be hidden.");
+    is(tabpanel.querySelector("#request-post-data-textarea-box")
+      .hasAttribute("hidden"), true,
+      "The request post data textarea box should be hidden.");
 
-      is(paramsScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
-        aQueryStringParamName,
-        "The first query string param name was incorrect.");
-      is(paramsScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
-        aQueryStringParamValue,
-        "The first query string param value was incorrect.");
+    let paramsScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
+    let formDataScope = tabpanel.querySelectorAll(".variables-view-scope")[1];
+
+    is(paramsScope.querySelector(".name").getAttribute("value"),
+      L10N.getStr("paramsQueryString"),
+      "The params scope doesn't have the correct title.");
+    is(formDataScope.querySelector(".name").getAttribute("value"),
+      L10N.getStr("paramsFormData"),
+      "The form data scope doesn't have the correct title.");
 
-      is(formDataScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
-        aFormDataParamName,
-        "The first form data param name was incorrect.");
-      is(formDataScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
-        aFormDataParamValue,
-        "The first form data param value was incorrect.");
-    }
+    is(paramsScope.querySelectorAll(".variables-view-variable .name")[0]
+      .getAttribute("value"),
+      queryStringParamName,
+      "The first query string param name was incorrect.");
+    is(paramsScope.querySelectorAll(".variables-view-variable .value")[0]
+      .getAttribute("value"),
+      queryStringParamValue,
+      "The first query string param value was incorrect.");
 
-    function testParamsTab2(
-      aQueryStringParamName, aQueryStringParamValue, aRequestPayload, aEditorMode)
-    {
-      let isJSON = aEditorMode == "js";
-      let tab = document.querySelectorAll("#details-pane tab")[2];
-      let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2];
+    is(formDataScope.querySelectorAll(".variables-view-variable .name")[0]
+      .getAttribute("value"),
+      formDataParamName,
+      "The first form data param name was incorrect.");
+    is(formDataScope.querySelectorAll(".variables-view-variable .value")[0]
+      .getAttribute("value"),
+      formDataParamValue,
+      "The first form data param value was incorrect.");
+  }
+
+  function* testParamsTab2(queryStringParamName, queryStringParamValue,
+                          requestPayload, editorMode) {
+    let isJSON = editorMode == "js";
+    let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2];
 
-      is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
-        "The number of param scopes displayed in this tabpanel is incorrect.");
-      is(tabpanel.querySelectorAll(".variable-or-property").length, isJSON ? 4 : 1,
-        "The number of param values displayed in this tabpanel is incorrect.");
-      is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
-        "The empty notice should not be displayed in this tabpanel.");
+    is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
+      "The number of param scopes displayed in this tabpanel is incorrect.");
+    is(tabpanel.querySelectorAll(".variable-or-property").length, isJSON ? 4 : 1,
+      "The number of param values displayed in this tabpanel is incorrect.");
+    is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
+      "The empty notice should not be displayed in this tabpanel.");
 
-      is(tabpanel.querySelector("#request-params-box")
-        .hasAttribute("hidden"), false,
-        "The request params box should not be hidden.");
-      is(tabpanel.querySelector("#request-post-data-textarea-box")
-        .hasAttribute("hidden"), isJSON,
-        "The request post data textarea box should be hidden.");
+    is(tabpanel.querySelector("#request-params-box")
+      .hasAttribute("hidden"), false,
+      "The request params box should not be hidden.");
+    is(tabpanel.querySelector("#request-post-data-textarea-box")
+      .hasAttribute("hidden"), isJSON,
+      "The request post data textarea box should be hidden.");
 
-      let paramsScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
-      let payloadScope = tabpanel.querySelectorAll(".variables-view-scope")[1];
+    let paramsScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
+    let payloadScope = tabpanel.querySelectorAll(".variables-view-scope")[1];
 
-      is(paramsScope.querySelector(".name").getAttribute("value"),
-        L10N.getStr("paramsQueryString"),
-        "The params scope doesn't have the correct title.");
-      is(payloadScope.querySelector(".name").getAttribute("value"),
-        isJSON ? L10N.getStr("jsonScopeName") : L10N.getStr("paramsPostPayload"),
-        "The request payload scope doesn't have the correct title.");
+    is(paramsScope.querySelector(".name").getAttribute("value"),
+      L10N.getStr("paramsQueryString"),
+      "The params scope doesn't have the correct title.");
+    is(payloadScope.querySelector(".name").getAttribute("value"),
+      isJSON ? L10N.getStr("jsonScopeName") : L10N.getStr("paramsPostPayload"),
+      "The request payload scope doesn't have the correct title.");
 
-      is(paramsScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
-        aQueryStringParamName,
-        "The first query string param name was incorrect.");
-      is(paramsScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
-        aQueryStringParamValue,
-        "The first query string param value was incorrect.");
+    is(paramsScope.querySelectorAll(".variables-view-variable .name")[0]
+      .getAttribute("value"),
+      queryStringParamName,
+      "The first query string param name was incorrect.");
+    is(paramsScope.querySelectorAll(".variables-view-variable .value")[0]
+      .getAttribute("value"),
+      queryStringParamValue,
+      "The first query string param value was incorrect.");
 
-      if (isJSON) {
-        let requestPayloadObject = JSON.parse(aRequestPayload);
-        let requestPairs = Object.keys(requestPayloadObject).map(k => [k, requestPayloadObject[k]]);
-        let displayedNames = payloadScope.querySelectorAll(".variables-view-property.variable-or-property .name");
-        let displayedValues = payloadScope.querySelectorAll(".variables-view-property.variable-or-property .value");
-        for (let i = 0; i < requestPairs.length; i++) {
-          let [requestPayloadName, requestPayloadValue] = requestPairs[i];
-          is(requestPayloadName, displayedNames[i].getAttribute("value"), "JSON property name " + i + " should be displayed correctly");
-          is('"' + requestPayloadValue + '"', displayedValues[i].getAttribute("value"), "JSON property value " + i + " should be displayed correctly");
-        }
-      } else {
-        return NetMonitorView.editor("#request-post-data-textarea").then((aEditor) => {
-          is(aEditor.getText(), aRequestPayload,
-            "The text shown in the source editor is incorrect.");
-          is(aEditor.getMode(), Editor.modes[aEditorMode],
-            "The mode active in the source editor is incorrect.");
-        });
+    if (isJSON) {
+      let requestPayloadObject = JSON.parse(requestPayload);
+      let requestPairs = Object.keys(requestPayloadObject)
+        .map(k => [k, requestPayloadObject[k]]);
+      let displayedNames = payloadScope.querySelectorAll(
+        ".variables-view-property.variable-or-property .name");
+      let displayedValues = payloadScope.querySelectorAll(
+        ".variables-view-property.variable-or-property .value");
+      for (let i = 0; i < requestPairs.length; i++) {
+        let [requestPayloadName, requestPayloadValue] = requestPairs[i];
+        is(requestPayloadName, displayedNames[i].getAttribute("value"),
+          "JSON property name " + i + " should be displayed correctly");
+        is('"' + requestPayloadValue + '"', displayedValues[i].getAttribute("value"),
+          "JSON property value " + i + " should be displayed correctly");
       }
+    } else {
+      let editor = yield NetMonitorView.editor("#request-post-data-textarea");
+      is(editor.getText(), requestPayload,
+        "The text shown in the source editor is incorrect.");
+      is(editor.getMode(), Editor.modes[editorMode],
+        "The mode active in the source editor is incorrect.");
     }
+  }
 
-    function testParamsTab3(aQueryStringParamName, aQueryStringParamValue) {
-      let tab = document.querySelectorAll("#details-pane tab")[2];
-      let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2];
+  function testParamsTab3(queryStringParamName, queryStringParamValue) {
+    let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2];
 
-      is(tabpanel.querySelectorAll(".variables-view-scope").length, 0,
-        "The number of param scopes displayed in this tabpanel is incorrect.");
-      is(tabpanel.querySelectorAll(".variable-or-property").length, 0,
-        "The number of param values displayed in this tabpanel is incorrect.");
-      is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 1,
-        "The empty notice should be displayed in this tabpanel.");
+    is(tabpanel.querySelectorAll(".variables-view-scope").length, 0,
+      "The number of param scopes displayed in this tabpanel is incorrect.");
+    is(tabpanel.querySelectorAll(".variable-or-property").length, 0,
+      "The number of param values displayed in this tabpanel is incorrect.");
+    is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 1,
+      "The empty notice should be displayed in this tabpanel.");
 
-      is(tabpanel.querySelector("#request-params-box")
-        .hasAttribute("hidden"), false,
-        "The request params box should not be hidden.");
-      is(tabpanel.querySelector("#request-post-data-textarea-box")
-        .hasAttribute("hidden"), true,
-        "The request post data textarea box should be hidden.");
-    }
-
-    aDebuggee.performRequests();
-  });
-}
+    is(tabpanel.querySelector("#request-params-box")
+      .hasAttribute("hidden"), false,
+      "The request params box should not be hidden.");
+    is(tabpanel.querySelector("#request-post-data-textarea-box")
+      .hasAttribute("hidden"), true,
+      "The request post data textarea box should be hidden.");
+  }
+});
--- a/devtools/client/netmonitor/test/browser_net_content-type.js
+++ b/devtools/client/netmonitor/test/browser_net_content-type.js
@@ -1,255 +1,252 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Tests if different response content types are handled correctly.
  */
 
-function test() {
-  initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [tab, , monitor] = yield initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL);
+  info("Starting test... ");
 
-    let { document, L10N, Editor, NetMonitorView } = aMonitor.panelWin;
-    let { RequestsMenu } = NetMonitorView;
-
-    RequestsMenu.lazyUpdate = false;
+  let { document, L10N, Editor, NetMonitorView } = monitor.panelWin;
+  let { RequestsMenu } = NetMonitorView;
 
-    waitForNetworkEvents(aMonitor, 7).then(() => {
-      verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
-        "GET", CONTENT_TYPE_SJS + "?fmt=xml", {
-          status: 200,
-          statusText: "OK",
-          type: "xml",
-          fullMimeType: "text/xml; charset=utf-8",
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 42),
-          time: true
-        });
-      verifyRequestItemTarget(RequestsMenu.getItemAtIndex(1),
-        "GET", CONTENT_TYPE_SJS + "?fmt=css", {
-          status: 200,
-          statusText: "OK",
-          type: "css",
-          fullMimeType: "text/css; charset=utf-8",
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 34),
-          time: true
-        });
-      verifyRequestItemTarget(RequestsMenu.getItemAtIndex(2),
-        "GET", CONTENT_TYPE_SJS + "?fmt=js", {
-          status: 200,
-          statusText: "OK",
-          type: "js",
-          fullMimeType: "application/javascript; charset=utf-8",
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 34),
-          time: true
-        });
-      verifyRequestItemTarget(RequestsMenu.getItemAtIndex(3),
-        "GET", CONTENT_TYPE_SJS + "?fmt=json", {
-          status: 200,
-          statusText: "OK",
-          type: "json",
-          fullMimeType: "application/json; charset=utf-8",
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 29),
-          time: true
-        });
-      verifyRequestItemTarget(RequestsMenu.getItemAtIndex(4),
-        "GET", CONTENT_TYPE_SJS + "?fmt=bogus", {
-          status: 404,
-          statusText: "Not Found",
-          type: "html",
-          fullMimeType: "text/html; charset=utf-8",
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 24),
-          time: true
-        });
-      verifyRequestItemTarget(RequestsMenu.getItemAtIndex(5),
-        "GET", TEST_IMAGE, {
-          fuzzyUrl: true,
-          status: 200,
-          statusText: "OK",
-          type: "png",
-          fullMimeType: "image/png",
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 580),
-          time: true
-        });
-      verifyRequestItemTarget(RequestsMenu.getItemAtIndex(6),
-        "GET", CONTENT_TYPE_SJS + "?fmt=gzip", {
-          status: 200,
-          statusText: "OK",
-          type: "plain",
-          fullMimeType: "text/plain",
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 10.73),
-          time: true
-        });
+  RequestsMenu.lazyUpdate = false;
 
-      EventUtils.sendMouseEvent({ type: "mousedown" },
-        document.getElementById("details-pane-toggle"));
-      EventUtils.sendMouseEvent({ type: "mousedown" },
-        document.querySelectorAll("#details-pane tab")[3]);
-
-      Task.spawn(function* () {
-        yield waitForResponseBodyDisplayed();
-        yield testResponseTab("xml");
-        RequestsMenu.selectedIndex = 1;
-        yield waitForTabUpdated();
-        yield testResponseTab("css");
-        RequestsMenu.selectedIndex = 2;
-        yield waitForTabUpdated();
-        yield testResponseTab("js");
-        RequestsMenu.selectedIndex = 3;
-        yield waitForTabUpdated();
-        yield testResponseTab("json");
-        RequestsMenu.selectedIndex = 4;
-        yield waitForTabUpdated();
-        yield testResponseTab("html");
-        RequestsMenu.selectedIndex = 5;
-        yield waitForTabUpdated();
-        yield testResponseTab("png");
-        RequestsMenu.selectedIndex = 6;
-        yield waitForTabUpdated();
-        yield testResponseTab("gzip");
-        yield teardown(aMonitor);
-        finish();
-      });
-
-      function testResponseTab(aType) {
-        let tab = document.querySelectorAll("#details-pane tab")[3];
-        let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3];
-
-        is(tab.getAttribute("selected"), "true",
-          "The response tab in the network details pane should be selected.");
+  let wait = waitForNetworkEvents(monitor, 7);
+  yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
+    content.wrappedJSObject.performRequests();
+  });
+  yield wait;
 
-        function checkVisibility(aBox) {
-          is(tabpanel.querySelector("#response-content-info-header")
-            .hasAttribute("hidden"), true,
-            "The response info header doesn't have the intended visibility.");
-          is(tabpanel.querySelector("#response-content-json-box")
-            .hasAttribute("hidden"), aBox != "json",
-            "The response content json box doesn't have the intended visibility.");
-          is(tabpanel.querySelector("#response-content-textarea-box")
-            .hasAttribute("hidden"), aBox != "textarea",
-            "The response content textarea box doesn't have the intended visibility.");
-          is(tabpanel.querySelector("#response-content-image-box")
-            .hasAttribute("hidden"), aBox != "image",
-            "The response content image box doesn't have the intended visibility.");
-        }
-
-        switch (aType) {
-          case "xml": {
-            checkVisibility("textarea");
-
-            return NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
-              is(aEditor.getText(), "<label value='greeting'>Hello XML!</label>",
-                "The text shown in the source editor is incorrect for the xml request.");
-              is(aEditor.getMode(), Editor.modes.html,
-                "The mode active in the source editor is incorrect for the xml request.");
-            });
-          }
-          case "css": {
-            checkVisibility("textarea");
-
-            return NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
-              is(aEditor.getText(), "body:pre { content: 'Hello CSS!' }",
-                "The text shown in the source editor is incorrect for the xml request.");
-              is(aEditor.getMode(), Editor.modes.css,
-                "The mode active in the source editor is incorrect for the xml request.");
-            });
-          }
-          case "js": {
-            checkVisibility("textarea");
-
-            return NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
-              is(aEditor.getText(), "function() { return 'Hello JS!'; }",
-                "The text shown in the source editor is incorrect for the xml request.");
-              is(aEditor.getMode(), Editor.modes.js,
-                "The mode active in the source editor is incorrect for the xml request.");
-            });
-          }
-          case "json": {
-            checkVisibility("json");
-
-            is(tabpanel.querySelectorAll(".variables-view-scope").length, 1,
-              "There should be 1 json scope displayed in this tabpanel.");
-            is(tabpanel.querySelectorAll(".variables-view-property").length, 2,
-              "There should be 2 json properties displayed in this tabpanel.");
-            is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
-              "The empty notice should not be displayed in this tabpanel.");
-
-            let jsonScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
-
-            is(jsonScope.querySelector(".name").getAttribute("value"),
-              L10N.getStr("jsonScopeName"),
-              "The json scope doesn't have the correct title.");
-
-            is(jsonScope.querySelectorAll(".variables-view-property .name")[0].getAttribute("value"),
-              "greeting", "The first json property name was incorrect.");
-            is(jsonScope.querySelectorAll(".variables-view-property .value")[0].getAttribute("value"),
-              "\"Hello JSON!\"", "The first json property value was incorrect.");
-
-            is(jsonScope.querySelectorAll(".variables-view-property .name")[1].getAttribute("value"),
-              "__proto__", "The second json property name was incorrect.");
-            is(jsonScope.querySelectorAll(".variables-view-property .value")[1].getAttribute("value"),
-              "Object", "The second json property value was incorrect.");
-
-            return promise.resolve();
-          }
-          case "html": {
-            checkVisibility("textarea");
-
-            return NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
-              is(aEditor.getText(), "<blink>Not Found</blink>",
-                "The text shown in the source editor is incorrect for the xml request.");
-              is(aEditor.getMode(), Editor.modes.html,
-                "The mode active in the source editor is incorrect for the xml request.");
-            });
-          }
-          case "png": {
-            checkVisibility("image");
-
-            let imageNode = tabpanel.querySelector("#response-content-image");
-            let deferred = promise.defer();
-
-            imageNode.addEventListener("load", function onLoad() {
-              imageNode.removeEventListener("load", onLoad);
-
-              is(tabpanel.querySelector("#response-content-image-name-value")
-                .getAttribute("value"), "test-image.png",
-                "The image name info isn't correct.");
-              is(tabpanel.querySelector("#response-content-image-mime-value")
-                .getAttribute("value"), "image/png",
-                "The image mime info isn't correct.");
-              is(tabpanel.querySelector("#response-content-image-dimensions-value")
-                .getAttribute("value"), "16" + " \u00D7 " + "16",
-                "The image dimensions info isn't correct.");
-
-              deferred.resolve();
-            });
-
-            return deferred.promise;
-          }
-
-          case "gzip": {
-            checkVisibility("textarea");
-
-            let expected = new Array(1000).join("Hello gzip!");
-            return NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
-              is(aEditor.getText(), expected,
-                "The text shown in the source editor is incorrect for the gzip request.");
-              is(aEditor.getMode(), Editor.modes.text,
-                "The mode active in the source editor is incorrect for the gzip request.");
-            });
-          }
-
-        }
-      }
-
-      function waitForTabUpdated() {
-        return waitFor(aMonitor.panelWin, aMonitor.panelWin.EVENTS.TAB_UPDATED);
-      }
-
-      function waitForResponseBodyDisplayed() {
-        return waitFor(aMonitor.panelWin, aMonitor.panelWin.EVENTS.RESPONSE_BODY_DISPLAYED);
-      }
+  verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
+    "GET", CONTENT_TYPE_SJS + "?fmt=xml", {
+      status: 200,
+      statusText: "OK",
+      type: "xml",
+      fullMimeType: "text/xml; charset=utf-8",
+      size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 42),
+      time: true
+    });
+  verifyRequestItemTarget(RequestsMenu.getItemAtIndex(1),
+    "GET", CONTENT_TYPE_SJS + "?fmt=css", {
+      status: 200,
+      statusText: "OK",
+      type: "css",
+      fullMimeType: "text/css; charset=utf-8",
+      size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 34),
+      time: true
+    });
+  verifyRequestItemTarget(RequestsMenu.getItemAtIndex(2),
+    "GET", CONTENT_TYPE_SJS + "?fmt=js", {
+      status: 200,
+      statusText: "OK",
+      type: "js",
+      fullMimeType: "application/javascript; charset=utf-8",
+      size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 34),
+      time: true
+    });
+  verifyRequestItemTarget(RequestsMenu.getItemAtIndex(3),
+    "GET", CONTENT_TYPE_SJS + "?fmt=json", {
+      status: 200,
+      statusText: "OK",
+      type: "json",
+      fullMimeType: "application/json; charset=utf-8",
+      size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 29),
+      time: true
+    });
+  verifyRequestItemTarget(RequestsMenu.getItemAtIndex(4),
+    "GET", CONTENT_TYPE_SJS + "?fmt=bogus", {
+      status: 404,
+      statusText: "Not Found",
+      type: "html",
+      fullMimeType: "text/html; charset=utf-8",
+      size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 24),
+      time: true
+    });
+  verifyRequestItemTarget(RequestsMenu.getItemAtIndex(5),
+    "GET", TEST_IMAGE, {
+      fuzzyUrl: true,
+      status: 200,
+      statusText: "OK",
+      type: "png",
+      fullMimeType: "image/png",
+      size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 580),
+      time: true
+    });
+  verifyRequestItemTarget(RequestsMenu.getItemAtIndex(6),
+    "GET", CONTENT_TYPE_SJS + "?fmt=gzip", {
+      status: 200,
+      statusText: "OK",
+      type: "plain",
+      fullMimeType: "text/plain",
+      size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 10.73),
+      time: true
     });
 
-    aDebuggee.performRequests();
-  });
-}
+  let onEvent = waitForResponseBodyDisplayed();
+  EventUtils.sendMouseEvent({ type: "mousedown" },
+    document.getElementById("details-pane-toggle"));
+  EventUtils.sendMouseEvent({ type: "mousedown" },
+    document.querySelectorAll("#details-pane tab")[3]);
+  yield onEvent;
+  yield testResponseTab("xml");
+
+  yield selectIndexAndWaitForTabUpdated(1);
+  yield testResponseTab("css");
+
+  yield selectIndexAndWaitForTabUpdated(2);
+  yield testResponseTab("js");
+
+  yield selectIndexAndWaitForTabUpdated(3);
+  yield testResponseTab("json");
+
+  yield selectIndexAndWaitForTabUpdated(4);
+  yield testResponseTab("html");
+
+  yield selectIndexAndWaitForTabUpdated(5);
+  yield testResponseTab("png");
+
+  yield selectIndexAndWaitForTabUpdated(6);
+  yield testResponseTab("gzip");
+
+  yield teardown(monitor);
+
+  function* testResponseTab(type) {
+    let tabEl = document.querySelectorAll("#details-pane tab")[3];
+    let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3];
+
+    is(tabEl.getAttribute("selected"), "true",
+      "The response tab in the network details pane should be selected.");
+
+    function checkVisibility(box) {
+      is(tabpanel.querySelector("#response-content-info-header")
+        .hasAttribute("hidden"), true,
+        "The response info header doesn't have the intended visibility.");
+      is(tabpanel.querySelector("#response-content-json-box")
+        .hasAttribute("hidden"), box != "json",
+        "The response content json box doesn't have the intended visibility.");
+      is(tabpanel.querySelector("#response-content-textarea-box")
+        .hasAttribute("hidden"), box != "textarea",
+        "The response content textarea box doesn't have the intended visibility.");
+      is(tabpanel.querySelector("#response-content-image-box")
+        .hasAttribute("hidden"), box != "image",
+        "The response content image box doesn't have the intended visibility.");
+    }
+
+    switch (type) {
+      case "xml": {
+        checkVisibility("textarea");
+
+        let editor = yield NetMonitorView.editor("#response-content-textarea");
+        is(editor.getText(), "<label value='greeting'>Hello XML!</label>",
+          "The text shown in the source editor is incorrect for the xml request.");
+        is(editor.getMode(), Editor.modes.html,
+          "The mode active in the source editor is incorrect for the xml request.");
+        break;
+      }
+      case "css": {
+        checkVisibility("textarea");
+
+        let editor = yield NetMonitorView.editor("#response-content-textarea");
+        is(editor.getText(), "body:pre { content: 'Hello CSS!' }",
+          "The text shown in the source editor is incorrect for the xml request.");
+        is(editor.getMode(), Editor.modes.css,
+          "The mode active in the source editor is incorrect for the xml request.");
+        break;
+      }
+      case "js": {
+        checkVisibility("textarea");
+
+        let editor = yield NetMonitorView.editor("#response-content-textarea");
+        is(editor.getText(), "function() { return 'Hello JS!'; }",
+          "The text shown in the source editor is incorrect for the xml request.");
+        is(editor.getMode(), Editor.modes.js,
+          "The mode active in the source editor is incorrect for the xml request.");
+        break;
+      }
+      case "json": {
+        checkVisibility("json");
+
+        is(tabpanel.querySelectorAll(".variables-view-scope").length, 1,
+          "There should be 1 json scope displayed in this tabpanel.");
+        is(tabpanel.querySelectorAll(".variables-view-property").length, 2,
+          "There should be 2 json properties displayed in this tabpanel.");
+        is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
+          "The empty notice should not be displayed in this tabpanel.");
+
+        let jsonScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
+
+        is(jsonScope.querySelector(".name").getAttribute("value"),
+          L10N.getStr("jsonScopeName"),
+          "The json scope doesn't have the correct title.");
+
+        is(jsonScope.querySelectorAll(".variables-view-property .name")[0]
+          .getAttribute("value"),
+          "greeting", "The first json property name was incorrect.");
+        is(jsonScope.querySelectorAll(".variables-view-property .value")[0]
+          .getAttribute("value"),
+          "\"Hello JSON!\"", "The first json property value was incorrect.");
+
+        is(jsonScope.querySelectorAll(".variables-view-property .name")[1]
+          .getAttribute("value"),
+          "__proto__", "The second json property name was incorrect.");
+        is(jsonScope.querySelectorAll(".variables-view-property .value")[1]
+          .getAttribute("value"),
+          "Object", "The second json property value was incorrect.");
+        break;
+      }
+      case "html": {
+        checkVisibility("textarea");
+
+        let editor = yield NetMonitorView.editor("#response-content-textarea");
+        is(editor.getText(), "<blink>Not Found</blink>",
+          "The text shown in the source editor is incorrect for the xml request.");
+        is(editor.getMode(), Editor.modes.html,
+          "The mode active in the source editor is incorrect for the xml request.");
+        break;
+      }
+      case "png": {
+        checkVisibility("image");
+
+        let imageNode = tabpanel.querySelector("#response-content-image");
+        yield once(imageNode, "load");
+
+        is(tabpanel.querySelector("#response-content-image-name-value")
+          .getAttribute("value"), "test-image.png",
+          "The image name info isn't correct.");
+        is(tabpanel.querySelector("#response-content-image-mime-value")
+          .getAttribute("value"), "image/png",
+          "The image mime info isn't correct.");
+        is(tabpanel.querySelector("#response-content-image-dimensions-value")
+          .getAttribute("value"), "16" + " \u00D7 " + "16",
+          "The image dimensions info isn't correct.");
+        break;
+      }
+      case "gzip": {
+        checkVisibility("textarea");
+
+        let expected = new Array(1000).join("Hello gzip!");
+        let editor = yield NetMonitorView.editor("#response-content-textarea");
+        is(editor.getText(), expected,
+          "The text shown in the source editor is incorrect for the gzip request.");
+        is(editor.getMode(), Editor.modes.text,
+          "The mode active in the source editor is incorrect for the gzip request.");
+        break;
+      }
+    }
+  }
+
+  function selectIndexAndWaitForTabUpdated(index) {
+    let onTabUpdated = monitor.panelWin.once(monitor.panelWin.EVENTS.TAB_UPDATED);
+    RequestsMenu.selectedIndex = index;
+    return onTabUpdated;
+  }
+
+  function waitForResponseBodyDisplayed() {
+    return monitor.panelWin.once(monitor.panelWin.EVENTS.RESPONSE_BODY_DISPLAYED);
+  }
+});
--- a/devtools/client/netmonitor/test/browser_net_copy_headers.js
+++ b/devtools/client/netmonitor/test/browser_net_copy_headers.js
@@ -1,64 +1,72 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Tests if copying a request's request/response headers works.
  */
 
 add_task(function* () {
-
-  let [ aTab, aDebuggee, aMonitor ] = yield initNetMonitor(SIMPLE_URL);
+  let [tab, , monitor ] = yield initNetMonitor(SIMPLE_URL);
   info("Starting test... ");
 
-  let { NetMonitorView } = aMonitor.panelWin;
+  let { NetMonitorView } = monitor.panelWin;
   let { RequestsMenu } = NetMonitorView;
 
   RequestsMenu.lazyUpdate = false;
 
-  aDebuggee.location.reload();
-  yield waitForNetworkEvents(aMonitor, 1);
+  let wait = waitForNetworkEvents(monitor, 1);
+  tab.linkedBrowser.reload();
+  yield wait;
 
   let requestItem = RequestsMenu.getItemAtIndex(0);
   RequestsMenu.selectedItem = requestItem;
 
-  let clipboard = null;
+  let { method, httpVersion, status, statusText } = requestItem.attachment;
 
   const EXPECTED_REQUEST_HEADERS = [
-    requestItem.attachment.method + " " + SIMPLE_URL + " " + requestItem.attachment.httpVersion,
+    `${method} ${SIMPLE_URL} ${httpVersion}`,
     "Host: example.com",
     "User-Agent: " + navigator.userAgent + "",
     "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
     "Accept-Language: " + navigator.languages.join(",") + ";q=0.5",
     "Accept-Encoding: gzip, deflate",
     "Connection: keep-alive",
     "Upgrade-Insecure-Requests: 1",
     "Pragma: no-cache",
     "Cache-Control: no-cache"
   ].join("\n");
 
-  RequestsMenu.copyRequestHeaders();
-  clipboard = SpecialPowers.getClipboardData("text/unicode");
-  // Sometimes, a "Cookie" header is left over from other tests. Remove it:
-  clipboard = clipboard.replace(/Cookie: [^\n]+\n/, "");
-  is(clipboard, EXPECTED_REQUEST_HEADERS, "Clipboard contains the currently selected item's request headers.");
+  yield waitForClipboardPromise(function setup() {
+    RequestsMenu.copyRequestHeaders();
+  }, function validate(result) {
+    // Sometimes, a "Cookie" header is left over from other tests. Remove it:
+    result = String(result).replace(/Cookie: [^\n]+\n/, "");
+    return result === EXPECTED_REQUEST_HEADERS;
+  });
+  info("Clipboard contains the currently selected item's request headers.");
 
   const EXPECTED_RESPONSE_HEADERS = [
-    requestItem.attachment.httpVersion + " " + requestItem.attachment.status + " " + requestItem.attachment.statusText,
+    `${httpVersion} ${status} ${statusText}`,
     "Last-Modified: Sun, 3 May 2015 11:11:11 GMT",
     "Content-Type: text/html",
     "Content-Length: 465",
     "Connection: close",
     "Server: httpd.js",
     "Date: Sun, 3 May 2015 11:11:11 GMT"
   ].join("\n");
 
-  RequestsMenu.copyResponseHeaders();
-  clipboard = SpecialPowers.getClipboardData("text/unicode");
-  // Fake the "Last-Modified" and "Date" headers because they will vary:
-  clipboard = clipboard
-    .replace(/Last-Modified: [^\n]+ GMT/, "Last-Modified: Sun, 3 May 2015 11:11:11 GMT")
-    .replace(/Date: [^\n]+ GMT/, "Date: Sun, 3 May 2015 11:11:11 GMT");
-  is(clipboard, EXPECTED_RESPONSE_HEADERS, "Clipboard contains the currently selected item's response headers.");
+  yield waitForClipboardPromise(function setup() {
+    RequestsMenu.copyResponseHeaders();
+  }, function validate(result) {
+    // Fake the "Last-Modified" and "Date" headers because they will vary:
+    result = String(result)
+      .replace(/Last-Modified: [^\n]+ GMT/, "Last-Modified: Sun, 3 May 2015 11:11:11 GMT")
+      .replace(/Date: [^\n]+ GMT/, "Date: Sun, 3 May 2015 11:11:11 GMT");
+    return result === EXPECTED_RESPONSE_HEADERS;
+  });
+  info("Clipboard contains the currently selected item's response headers.");
 
-  teardown(aMonitor).then(finish);
+  yield teardown(monitor);
 });
--- a/devtools/client/netmonitor/test/browser_net_copy_image_as_data_uri.js
+++ b/devtools/client/netmonitor/test/browser_net_copy_image_as_data_uri.js
@@ -1,38 +1,35 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Tests if copying an image as data uri works.
  */
 
-function test() {
-  initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [tab, , monitor] = yield initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL);
+  info("Starting test... ");
 
-    let { NetMonitorView } = aMonitor.panelWin;
-    let { RequestsMenu } = NetMonitorView;
+  let { NetMonitorView } = monitor.panelWin;
+  let { RequestsMenu } = NetMonitorView;
 
-    RequestsMenu.lazyUpdate = false;
-
-    waitForNetworkEvents(aMonitor, 7).then(() => {
-      let requestItem = RequestsMenu.getItemAtIndex(5);
-      RequestsMenu.selectedItem = requestItem;
+  RequestsMenu.lazyUpdate = false;
 
-      waitForClipboard(TEST_IMAGE_DATA_URI, function setup() {
-        RequestsMenu.copyImageAsDataUri();
-      }, function onSuccess() {
-        ok(true, "Clipboard contains the currently selected image as data uri.");
-        cleanUp();
-      }, function onFailure() {
-        ok(false, "Copying the currently selected image as data uri was unsuccessful.");
-        cleanUp();
-      });
-    });
+  let wait = waitForNetworkEvents(monitor, 7);
+  yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
+    content.wrappedJSObject.performRequests();
+  });
+  yield wait;
+
+  let requestItem = RequestsMenu.getItemAtIndex(5);
+  RequestsMenu.selectedItem = requestItem;
 
-    aDebuggee.performRequests();
+  yield waitForClipboardPromise(function setup() {
+    RequestsMenu.copyImageAsDataUri();
+  }, TEST_IMAGE_DATA_URI);
 
-    function cleanUp() {
-      teardown(aMonitor).then(finish);
-    }
-  });
-}
+  ok(true, "Clipboard contains the currently selected image as data uri.");
+
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/browser_net_copy_params.js
+++ b/devtools/client/netmonitor/test/browser_net_copy_params.js
@@ -1,92 +1,94 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Tests whether copying a request item's parameters works.
  */
 
-function test() {
-  initNetMonitor(PARAMS_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [tab, , monitor] = yield initNetMonitor(PARAMS_URL);
+  info("Starting test... ");
 
-    let { document, L10N, EVENTS, Editor, NetMonitorView } = aMonitor.panelWin;
-    let { RequestsMenu, NetworkDetails } = NetMonitorView;
-
-    RequestsMenu.lazyUpdate = false;
+  let { document, NetMonitorView } = monitor.panelWin;
+  let { RequestsMenu } = NetMonitorView;
 
-    Task.spawn(function* () {
-      yield waitForNetworkEvents(aMonitor, 1, 6);
+  RequestsMenu.lazyUpdate = false;
 
-      RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(0);
-      yield testCopyUrlParamsHidden(false);
-      yield testCopyUrlParams("a");
-      yield testCopyPostDataHidden(false);
-      yield testCopyPostData("{ \"foo\": \"bar\" }");
+  let wait = waitForNetworkEvents(monitor, 1, 6);
+  yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
+    content.wrappedJSObject.performRequests();
+  });
+  yield wait;
 
-      RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(1);
-      yield testCopyUrlParamsHidden(false);
-      yield testCopyUrlParams("a=b");
-      yield testCopyPostDataHidden(false);
-      yield testCopyPostData("{ \"foo\": \"bar\" }");
+  RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(0);
+  yield testCopyUrlParamsHidden(false);
+  yield testCopyUrlParams("a");
+  yield testCopyPostDataHidden(false);
+  yield testCopyPostData("{ \"foo\": \"bar\" }");
 
-      RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(2);
-      yield testCopyUrlParamsHidden(false);
-      yield testCopyUrlParams("a=b");
-      yield testCopyPostDataHidden(false);
-      yield testCopyPostData("foo=bar");
+  RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(1);
+  yield testCopyUrlParamsHidden(false);
+  yield testCopyUrlParams("a=b");
+  yield testCopyPostDataHidden(false);
+  yield testCopyPostData("{ \"foo\": \"bar\" }");
 
-      RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(3);
-      yield testCopyUrlParamsHidden(false);
-      yield testCopyUrlParams("a");
-      yield testCopyPostDataHidden(false);
-      yield testCopyPostData("{ \"foo\": \"bar\" }");
+  RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(2);
+  yield testCopyUrlParamsHidden(false);
+  yield testCopyUrlParams("a=b");
+  yield testCopyPostDataHidden(false);
+  yield testCopyPostData("foo=bar");
 
-      RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(4);
-      yield testCopyUrlParamsHidden(false);
-      yield testCopyUrlParams("a=b");
-      yield testCopyPostDataHidden(false);
-      yield testCopyPostData("{ \"foo\": \"bar\" }");
+  RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(3);
+  yield testCopyUrlParamsHidden(false);
+  yield testCopyUrlParams("a");
+  yield testCopyPostDataHidden(false);
+  yield testCopyPostData("{ \"foo\": \"bar\" }");
 
-      RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(5);
-      yield testCopyUrlParamsHidden(false);
-      yield testCopyUrlParams("a=b");
-      yield testCopyPostDataHidden(false);
-      yield testCopyPostData("?foo=bar");
+  RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(4);
+  yield testCopyUrlParamsHidden(false);
+  yield testCopyUrlParams("a=b");
+  yield testCopyPostDataHidden(false);
+  yield testCopyPostData("{ \"foo\": \"bar\" }");
 
-      RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(6);
-      yield testCopyUrlParamsHidden(true);
-      yield testCopyPostDataHidden(true);
+  RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(5);
+  yield testCopyUrlParamsHidden(false);
+  yield testCopyUrlParams("a=b");
+  yield testCopyPostDataHidden(false);
+  yield testCopyPostData("?foo=bar");
 
-      yield teardown(aMonitor);
-      finish();
-    });
+  RequestsMenu.selectedItem = RequestsMenu.getItemAtIndex(6);
+  yield testCopyUrlParamsHidden(true);
+  yield testCopyPostDataHidden(true);
+
+  return teardown(monitor);
 
-    function testCopyUrlParamsHidden(aHidden) {
-      RequestsMenu._onContextShowing();
-      is(document.querySelector("#request-menu-context-copy-url-params").hidden,
-        aHidden, "The \"Copy URL Parameters\" context menu item should" + (aHidden ? " " : " not ") + "be hidden.");
-    }
+  function testCopyUrlParamsHidden(hidden) {
+    RequestsMenu._onContextShowing();
+    is(document.querySelector("#request-menu-context-copy-url-params").hidden, hidden,
+      "The \"Copy URL Parameters\" context menu item should" + (hidden ? " " : " not ") +
+        "be hidden.");
+  }
 
-    function testCopyUrlParams(aQueryString) {
+  function* testCopyUrlParams(queryString) {
+    yield waitForClipboardPromise(function setup() {
       RequestsMenu.copyUrlParams();
-      is(SpecialPowers.getClipboardData("text/unicode"),
-        aQueryString, "The url query string copied from the selected item is correct.");
-    }
-
-    function testCopyPostDataHidden(aHidden) {
-      RequestsMenu._onContextShowing();
-      is(document.querySelector("#request-menu-context-copy-post-data").hidden,
-        aHidden, "The \"Copy POST Data\" context menu item should" + (aHidden ? " " : " not ") + "be hidden.");
-    }
+    }, queryString);
+    ok(true, "The url query string copied from the selected item is correct.");
+  }
 
-    function testCopyPostData(aPostData) {
-      return RequestsMenu.copyPostData().then(() => {
-        is(SpecialPowers.getClipboardData("text/unicode"),
-          aPostData, "The post data string copied from the selected item is correct.");
-      });
-    }
+  function testCopyPostDataHidden(hidden) {
+    RequestsMenu._onContextShowing();
+    is(document.querySelector("#request-menu-context-copy-post-data").hidden, hidden,
+      "The \"Copy POST Data\" context menu item should" + (hidden ? " " : " not ") +
+        "be hidden.");
+  }
 
-    aDebuggee.performRequests();
-  });
-}
-
+  function* testCopyPostData(postData) {
+    yield waitForClipboardPromise(function setup() {
+      RequestsMenu.copyPostData();
+    }, postData);
+    ok(true, "The post data string copied from the selected item is correct.");
+  }
+});
--- a/devtools/client/netmonitor/test/browser_net_copy_response.js
+++ b/devtools/client/netmonitor/test/browser_net_copy_response.js
@@ -1,40 +1,35 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Tests if copying a request's response works.
  */
 
-function test() {
-  initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
-
-    const EXPECTED_RESULT = '{ "greeting": "Hello JSON!" }';
+add_task(function* () {
+  let [tab, , monitor] = yield initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL);
+  info("Starting test... ");
 
-    let { NetMonitorView } = aMonitor.panelWin;
-    let { RequestsMenu } = NetMonitorView;
+  const EXPECTED_RESULT = '{ "greeting": "Hello JSON!" }';
 
-    RequestsMenu.lazyUpdate = false;
+  let { NetMonitorView } = monitor.panelWin;
+  let { RequestsMenu } = NetMonitorView;
 
-    waitForNetworkEvents(aMonitor, 7).then(() => {
-      let requestItem = RequestsMenu.getItemAtIndex(3);
-      RequestsMenu.selectedItem = requestItem;
+  RequestsMenu.lazyUpdate = false;
 
-      waitForClipboard(EXPECTED_RESULT, function setup() {
-        RequestsMenu.copyResponse();
-      }, function onSuccess() {
-        ok(true, "Clipboard contains the currently selected item's response.");
-        cleanUp();
-      }, function onFailure() {
-        ok(false, "Copying the currently selected item's response was unsuccessful.");
-        cleanUp();
-      });
-    });
+  let wait = waitForNetworkEvents(monitor, 7);
+  yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
+    content.wrappedJSObject.performRequests();
+  });
+  yield wait;
 
-    aDebuggee.performRequests();
+  let requestItem = RequestsMenu.getItemAtIndex(3);
+  RequestsMenu.selectedItem = requestItem;
 
-    function cleanUp() {
-      teardown(aMonitor).then(finish);
-    }
-  });
-}
+  yield waitForClipboardPromise(function setup() {
+    RequestsMenu.copyResponse();
+  }, EXPECTED_RESULT);
+
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/browser_net_copy_svg_image_as_data_uri.js
+++ b/devtools/client/netmonitor/test/browser_net_copy_svg_image_as_data_uri.js
@@ -1,41 +1,37 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Tests if copying an image as data uri works.
  */
 
-function test() {
-  const SVG_URL = EXAMPLE_URL + "dropmarker.svg";
-  initNetMonitor(CURL_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+const SVG_URL = EXAMPLE_URL + "dropmarker.svg";
 
-    let { NetMonitorView } = aMonitor.panelWin;
-    let { RequestsMenu } = NetMonitorView;
+add_task(function* () {
+  let [tab, , monitor] = yield initNetMonitor(CURL_URL);
+  info("Starting test... ");
 
-    RequestsMenu.lazyUpdate = false;
+  let { NetMonitorView } = monitor.panelWin;
+  let { RequestsMenu } = NetMonitorView;
 
-    waitForNetworkEvents(aMonitor, 1).then(() => {
-      let requestItem = RequestsMenu.getItemAtIndex(0);
-      RequestsMenu.selectedItem = requestItem;
+  RequestsMenu.lazyUpdate = false;
 
-      waitForClipboard(function check(text) {
-        return text.startsWith("data:") && !/undefined/.test(text);
-      }, function setup() {
-        RequestsMenu.copyImageAsDataUri();
-      }, function onSuccess() {
-        ok(true, "Clipboard contains a valid data: URI");
-        cleanUp();
-      }, function onFailure() {
-        ok(false, "Clipboard contains an invalid data: URI");
-        cleanUp();
-      });
-    });
+  let wait = waitForNetworkEvents(monitor, 1);
+  yield ContentTask.spawn(tab.linkedBrowser, SVG_URL, function* (url) {
+    content.wrappedJSObject.performRequest(url);
+  });
+  yield wait;
+
+  let requestItem = RequestsMenu.getItemAtIndex(0);
+  RequestsMenu.selectedItem = requestItem;
 
-    aDebuggee.performRequest(SVG_URL);
+  yield waitForClipboardPromise(function setup() {
+    RequestsMenu.copyImageAsDataUri();
+  }, function check(text) {
+    return text.startsWith("data:") && !/undefined/.test(text);
+  });
 
-    function cleanUp() {
-      teardown(aMonitor).then(finish);
-    }
-  });
-}
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/browser_net_copy_url.js
+++ b/devtools/client/netmonitor/test/browser_net_copy_url.js
@@ -1,36 +1,31 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Tests if copying a request's url works.
  */
 
-function test() {
-  initNetMonitor(CUSTOM_GET_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [tab, , monitor] = yield initNetMonitor(CUSTOM_GET_URL);
+  info("Starting test... ");
 
-    let { NetMonitorView } = aMonitor.panelWin;
-    let { RequestsMenu } = NetMonitorView;
-
-    waitForNetworkEvents(aMonitor, 1).then(() => {
-      let requestItem = RequestsMenu.getItemAtIndex(0);
-      RequestsMenu.selectedItem = requestItem;
+  let { NetMonitorView } = monitor.panelWin;
+  let { RequestsMenu } = NetMonitorView;
 
-      waitForClipboard(requestItem.attachment.url, function setup() {
-        RequestsMenu.copyUrl();
-      }, function onSuccess() {
-        ok(true, "Clipboard contains the currently selected item's url.");
-        cleanUp();
-      }, function onFailure() {
-        ok(false, "Copying the currently selected item's url was unsuccessful.");
-        cleanUp();
-      });
-    });
+  let wait = waitForNetworkEvents(monitor, 1);
+  yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
+    content.wrappedJSObject.performRequests(1);
+  });
+  yield wait;
 
-    aDebuggee.performRequests(1);
+  let requestItem = RequestsMenu.getItemAtIndex(0);
+  RequestsMenu.selectedItem = requestItem;
 
-    function cleanUp() {
-      teardown(aMonitor).then(finish);
-    }
-  });
-}
+  yield waitForClipboardPromise(function setup() {
+    RequestsMenu.copyUrl();
+  }, requestItem.attachment.url);
+
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/browser_net_cors_requests.js
+++ b/devtools/client/netmonitor/test/browser_net_cors_requests.js
@@ -1,29 +1,33 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
+
 "use strict";
 
 /**
  * Test that CORS preflight requests are displayed by network monitor
  */
 
 add_task(function* () {
-  let [, debuggee, monitor] = yield initNetMonitor(CORS_URL);
+  let [tab, , monitor] = yield initNetMonitor(CORS_URL);
   let { RequestsMenu } = monitor.panelWin.NetMonitorView;
   RequestsMenu.lazyUpdate = false;
 
+  let wait = waitForNetworkEvents(monitor, 1, 1);
+
   info("Performing a CORS request");
-  let url = "http://test1.example.com" + CORS_SJS_PATH;
-  debuggee.performRequests(url, "triggering/preflight", "post-data");
+  let requestUrl = "http://test1.example.com" + CORS_SJS_PATH;
+  yield ContentTask.spawn(tab.linkedBrowser, requestUrl, function* (url) {
+    content.wrappedJSObject.performRequests(url, "triggering/preflight", "post-data");
+  });
 
   info("Waiting until the requests appear in netmonitor");
-  yield waitForNetworkEvents(monitor, 1, 1);
+  yield wait;
 
   info("Checking the preflight and flight methods");
   ["OPTIONS", "POST"].forEach((method, i) => {
-    verifyRequestItemTarget(RequestsMenu.getItemAtIndex(i), method, url);
+    verifyRequestItemTarget(RequestsMenu.getItemAtIndex(i), method, requestUrl);
   });
 
   yield teardown(monitor);
-  finish();
 });
--- a/devtools/client/netmonitor/test/browser_net_curl-utils.js
+++ b/devtools/client/netmonitor/test/browser_net_curl-utils.js
@@ -4,106 +4,101 @@
 "use strict";
 
 /**
  * Tests Curl Utils functionality.
  */
 
 const { CurlUtils } = require("devtools/client/shared/curl");
 
-function test() {
-  initNetMonitor(CURL_UTILS_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
+add_task(function* () {
+  let [tab, , monitor] = yield initNetMonitor(CURL_UTILS_URL);
+  info("Starting test... ");
 
-    let { NetMonitorView, gNetwork } = aMonitor.panelWin;
-    let { RequestsMenu } = NetMonitorView;
+  let { NetMonitorView, gNetwork } = monitor.panelWin;
+  let { RequestsMenu } = NetMonitorView;
 
-    RequestsMenu.lazyUpdate = false;
+  RequestsMenu.lazyUpdate = false;
 
-    waitForNetworkEvents(aMonitor, 1, 3).then(() => {
-      let requests = {
-        get: RequestsMenu.getItemAtIndex(0),
-        post: RequestsMenu.getItemAtIndex(1),
-        multipart: RequestsMenu.getItemAtIndex(2),
-        multipartForm: RequestsMenu.getItemAtIndex(3)
-      };
+  let wait = waitForNetworkEvents(monitor, 1, 3);
+  yield ContentTask.spawn(tab.linkedBrowser, SIMPLE_SJS, function* (url) {
+    content.wrappedJSObject.performRequests(url);
+  });
+  yield wait;
 
-      Task.spawn(function* () {
-        yield createCurlData(requests.get.attachment, gNetwork).then((aData) => {
-          test_findHeader(aData);
-        });
-
-        yield createCurlData(requests.post.attachment, gNetwork).then((aData) => {
-          test_isUrlEncodedRequest(aData);
-          test_writePostDataTextParams(aData);
-        });
+  let requests = {
+    get: RequestsMenu.getItemAtIndex(0),
+    post: RequestsMenu.getItemAtIndex(1),
+    multipart: RequestsMenu.getItemAtIndex(2),
+    multipartForm: RequestsMenu.getItemAtIndex(3)
+  };
 
-        yield createCurlData(requests.multipart.attachment, gNetwork).then((aData) => {
-          test_isMultipartRequest(aData);
-          test_getMultipartBoundary(aData);
-          test_removeBinaryDataFromMultipartText(aData);
-        });
+  let data = yield createCurlData(requests.get.attachment, gNetwork);
+  testFindHeader(data);
 
-        yield createCurlData(requests.multipartForm.attachment, gNetwork).then((aData) => {
-          test_getHeadersFromMultipartText(aData);
-        });
+  data = yield createCurlData(requests.post.attachment, gNetwork);
+  testIsUrlEncodedRequest(data);
+  testWritePostDataTextParams(data);
+
+  data = yield createCurlData(requests.multipart.attachment, gNetwork);
+  testIsMultipartRequest(data);
+  testGetMultipartBoundary(data);
+  testRemoveBinaryDataFromMultipartText(data);
 
-        if (Services.appinfo.OS != "WINNT") {
-          test_escapeStringPosix();
-        } else {
-          test_escapeStringWin();
-        }
+  data = yield createCurlData(requests.multipartForm.attachment, gNetwork);
+  testGetHeadersFromMultipartText(data);
 
-        teardown(aMonitor).then(finish);
-      });
-    });
+  if (Services.appinfo.OS != "WINNT") {
+    testEscapeStringPosix();
+  } else {
+    testEscapeStringWin();
+  }
 
-    aDebuggee.performRequests(SIMPLE_SJS);
-  });
-}
+  yield teardown(monitor);
+});
 
-function test_isUrlEncodedRequest(aData) {
-  let isUrlEncoded = CurlUtils.isUrlEncodedRequest(aData);
+function testIsUrlEncodedRequest(data) {
+  let isUrlEncoded = CurlUtils.isUrlEncodedRequest(data);
   ok(isUrlEncoded, "Should return true for url encoded requests.");
 }
 
-function test_isMultipartRequest(aData) {
-  let isMultipart = CurlUtils.isMultipartRequest(aData);
+function testIsMultipartRequest(data) {
+  let isMultipart = CurlUtils.isMultipartRequest(data);
   ok(isMultipart, "Should return true for multipart/form-data requests.");
 }
 
-function test_findHeader(aData) {
-  let headers = aData.headers;
+function testFindHeader(data) {
+  let headers = data.headers;
   let hostName = CurlUtils.findHeader(headers, "Host");
   let requestedWithLowerCased = CurlUtils.findHeader(headers, "x-requested-with");
   let doesNotExist = CurlUtils.findHeader(headers, "X-Does-Not-Exist");
 
   is(hostName, "example.com",
     "Header with name 'Host' should be found in the request array.");
   is(requestedWithLowerCased, "XMLHttpRequest",
     "The search should be case insensitive.");
   is(doesNotExist, null,
     "Should return null when a header is not found.");
 }
 
-function test_writePostDataTextParams(aData) {
-  let params = CurlUtils.writePostDataTextParams(aData.postDataText);
+function testWritePostDataTextParams(data) {
+  let params = CurlUtils.writePostDataTextParams(data.postDataText);
   is(params, "param1=value1&param2=value2&param3=value3",
     "Should return a serialized representation of the request parameters");
 }
 
-function test_getMultipartBoundary(aData) {
-  let boundary = CurlUtils.getMultipartBoundary(aData);
+function testGetMultipartBoundary(data) {
+  let boundary = CurlUtils.getMultipartBoundary(data);
   ok(/-{3,}\w+/.test(boundary),
     "A boundary string should be found in a multipart request.");
 }
 
-function test_removeBinaryDataFromMultipartText(aData) {
-  let generatedBoundary = CurlUtils.getMultipartBoundary(aData);
-  let text = aData.postDataText;
+function testRemoveBinaryDataFromMultipartText(data) {
+  let generatedBoundary = CurlUtils.getMultipartBoundary(data);
+  let text = data.postDataText;
   let binaryRemoved =
     CurlUtils.removeBinaryDataFromMultipartText(text, generatedBoundary);
   let boundary = "--" + generatedBoundary;
 
   const EXPECTED_POSIX_RESULT = [
     "$'",
     boundary,
     "\\r\\n\\r\\n",
@@ -144,28 +139,25 @@ function test_removeBinaryDataFromMultip
     is(CurlUtils.escapeStringPosix(binaryRemoved), EXPECTED_POSIX_RESULT,
       "The mulitpart request payload should not contain binary data.");
   } else {
     is(CurlUtils.escapeStringWin(binaryRemoved), EXPECTED_WIN_RESULT,
       "WinNT: The mulitpart request payload should not contain binary data.");
   }
 }
 
-function test_getHeadersFromMultipartText(aData) {
-  let headers = CurlUtils.getHeadersFromMultipartText(aData.postDataText);
+function testGetHeadersFromMultipartText(data) {
+  let headers = CurlUtils.getHeadersFromMultipartText(data.postDataText);
 
-  ok(Array.isArray(headers),
-    "Should return an array.");
-  ok(headers.length > 0,
-    "There should exist at least one request header.");
-  is(headers[0].name, "Content-Type",
-    "The first header name should be 'Content-Type'.");
+  ok(Array.isArray(headers), "Should return an array.");
+  ok(headers.length > 0, "There should exist at least one request header.");
+  is(headers[0].name, "Content-Type", "The first header name should be 'Content-Type'.");
 }
 
-function test_escapeStringPosix() {
+function testEscapeStringPosix() {
   let surroundedWithQuotes = "A simple string";
   is(CurlUtils.escapeStringPosix(surroundedWithQuotes), "'A simple string'",
     "The string should be surrounded with single quotes.");
 
   let singleQuotes = "It's unusual to put crickets in your coffee.";
   is(CurlUtils.escapeStringPosix(singleQuotes),
     "$'It\\'s unusual to put crickets in your coffee.'",
     "Single quotes should be escaped.");
@@ -179,17 +171,17 @@ function test_escapeStringPosix() {
     "Control characters should be escaped.");
 
   let extendedAsciiChars = "æ ø ü ß ö é";
   is(CurlUtils.escapeStringPosix(extendedAsciiChars),
     "$'\\xc3\\xa6 \\xc3\\xb8 \\xc3\\xbc \\xc3\\x9f \\xc3\\xb6 \\xc3\\xa9'",
     "Character codes outside of the decimal range 32 - 126 should be escaped.");
 }
 
-function test_escapeStringWin() {
+function testEscapeStringWin() {
   let surroundedWithDoubleQuotes = "A simple string";
   is(CurlUtils.escapeStringWin(surroundedWithDoubleQuotes), '"A simple string"',
     "The string should be surrounded with double quotes.");
 
   let doubleQuotes = "Quote: \"Time is an illusion. Lunchtime doubly so.\"";
   is(CurlUtils.escapeStringWin(doubleQuotes),
     '"Quote: ""Time is an illusion. Lunchtime doubly so."""',
     "Double quotes should be escaped.");
@@ -203,34 +195,34 @@ function test_escapeStringWin() {
     "Backslashes should be escaped.");
 
   let newLines = "line1\r\nline2\r\nline3";
   is(CurlUtils.escapeStringWin(newLines),
     '"line1"^\u000d\u000A"line2"^\u000d\u000A"line3"',
     "Newlines should be escaped.");
 }
 
-function createCurlData(aSelected, aNetwork) {
-  return Task.spawn(function* () {
-    // Create a sanitized object for the Curl command generator.
-    let data = {
-      url: aSelected.url,
-      method: aSelected.method,
-      headers: [],
-      httpVersion: aSelected.httpVersion,
-      postDataText: null
-    };
+function* createCurlData(selected, network, controller) {
+  let { url, method, httpVersion } = selected;
+
+  // Create a sanitized object for the Curl command generator.
+  let data = {
+    url,
+    method,
+    headers: [],
+    httpVersion,
+    postDataText: null
+  };
 
-    // Fetch header values.
-    for (let { name, value } of aSelected.requestHeaders.headers) {
-      let text = yield aNetwork.getString(value);
-      data.headers.push({ name: name, value: text });
-    }
+  // Fetch header values.
+  for (let { name, value } of selected.requestHeaders.headers) {
+    let text = yield network.getString(value);
+    data.headers.push({ name: name, value: text });
+  }
 
-    // Fetch the request payload.
-    if (aSelected.requestPostData) {
-      let postData = aSelected.requestPostData.postData.text;
-      data.postDataText = yield aNetwork.getString(postData);
-    }
+  // Fetch the request payload.
+  if (selected.requestPostData) {
+    let postData = selected.requestPostData.postData.text;
+    data.postDataText = yield network.getString(postData);
+  }
 
-    return data;
-  });
+  return data;
 }
--- a/devtools/client/netmonitor/test/browser_net_cyrillic-01.js
+++ b/devtools/client/netmonitor/test/browser_net_cyrillic-01.js
@@ -1,44 +1,45 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Tests if cyrillic text is rendered correctly in the source editor.
  */
 
-function test() {
-  initNetMonitor(CYRILLIC_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
-
-    let { document, Editor, NetMonitorView } = aMonitor.panelWin;
-    let { RequestsMenu } = NetMonitorView;
+add_task(function* () {
+  let [tab, , monitor] = yield initNetMonitor(CYRILLIC_URL);
+  info("Starting test... ");
 
-    RequestsMenu.lazyUpdate = false;
+  let { document, EVENTS, Editor, NetMonitorView } = monitor.panelWin;
+  let { RequestsMenu } = NetMonitorView;
 
-    waitForNetworkEvents(aMonitor, 1).then(() => {
-      verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
-        "GET", CONTENT_TYPE_SJS + "?fmt=txt", {
-          status: 200,
-          statusText: "DA DA DA"
-        });
+  RequestsMenu.lazyUpdate = false;
 
-      EventUtils.sendMouseEvent({ type: "mousedown" },
-        document.getElementById("details-pane-toggle"));
-      EventUtils.sendMouseEvent({ type: "mousedown" },
-        document.querySelectorAll("#details-pane tab")[3]);
+  let wait = waitForNetworkEvents(monitor, 1);
+  yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
+    content.wrappedJSObject.performRequests();
+  });
+  yield wait;
 
-      let RESPONSE_BODY_DISPLAYED = aMonitor.panelWin.EVENTS.RESPONSE_BODY_DISPLAYED;
-      waitFor(aMonitor.panelWin, RESPONSE_BODY_DISPLAYED).then(() =>
-        NetMonitorView.editor("#response-content-textarea")
-      ).then((aEditor) => {
-        is(aEditor.getText().indexOf("\u044F"), 26, // я
-          "The text shown in the source editor is incorrect.");
-        is(aEditor.getMode(), Editor.modes.text,
-          "The mode active in the source editor is incorrect.");
-
-        teardown(aMonitor).then(finish);
-      });
+  verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
+    "GET", CONTENT_TYPE_SJS + "?fmt=txt", {
+      status: 200,
+      statusText: "DA DA DA"
     });
 
-    aDebuggee.performRequests();
-  });
-}
+  EventUtils.sendMouseEvent({ type: "mousedown" },
+    document.getElementById("details-pane-toggle"));
+  EventUtils.sendMouseEvent({ type: "mousedown" },
+    document.querySelectorAll("#details-pane tab")[3]);
+
+  yield monitor.panelWin.once(EVENTS.RESPONSE_BODY_DISPLAYED);
+  let editor = yield NetMonitorView.editor("#response-content-textarea");
+  // u044F = я
+  is(editor.getText().indexOf("\u044F"), 26,
+    "The text shown in the source editor is correct.");
+  is(editor.getMode(), Editor.modes.text,
+    "The mode active in the source editor is correct.");
+
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/browser_net_cyrillic-02.js
+++ b/devtools/client/netmonitor/test/browser_net_cyrillic-02.js
@@ -1,45 +1,44 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /**
  * Tests if cyrillic text is rendered correctly in the source editor
  * when loaded directly from an HTML page.
  */
 
-function test() {
-  initNetMonitor(CYRILLIC_URL).then(([aTab, aDebuggee, aMonitor]) => {
-    info("Starting test... ");
-
-    let { document, Editor, NetMonitorView } = aMonitor.panelWin;
-    let { RequestsMenu } = NetMonitorView;
+add_task(function* () {
+  let [tab, , monitor] = yield initNetMonitor(CYRILLIC_URL);
+  info("Starting test... ");
 
-    RequestsMenu.lazyUpdate = false;
+  let { document, EVENTS, Editor, NetMonitorView } = monitor.panelWin;
+  let { RequestsMenu } = NetMonitorView;
 
-    waitForNetworkEvents(aMonitor, 1).then(() => {
-      verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
-        "GET", CYRILLIC_URL, {
-          status: 200,
-          statusText: "OK"
-        });
+  RequestsMenu.lazyUpdate = false;
 
-      EventUtils.sendMouseEvent({ type: "mousedown" },
-        document.getElementById("details-pane-toggle"));
-      EventUtils.sendMouseEvent({ type: "mousedown" },
-        document.querySelectorAll("#details-pane tab")[3]);
+  let wait = waitForNetworkEvents(monitor, 1);
+  tab.linkedBrowser.reload();
+  yield wait;
 
-      let RESPONSE_BODY_DISPLAYED = aMonitor.panelWin.EVENTS.RESPONSE_BODY_DISPLAYED;
-      waitFor(aMonitor.panelWin, RESPONSE_BODY_DISPLAYED).then(() =>
-        NetMonitorView.editor("#response-content-textarea")
-      ).then((aEditor) => {
-        is(aEditor.getText().indexOf("\u044F"), 486, // я
-          "The text shown in the source editor is incorrect.");
-        is(aEditor.getMode(), Editor.modes.html,
-          "The mode active in the source editor is incorrect.");
-
-        teardown(aMonitor).then(finish);
-      });
+  verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
+    "GET", CYRILLIC_URL, {
+      status: 200,
+      statusText: "OK"
     });
 
-    aDebuggee.location.reload();
-  });
-}
+  EventUtils.sendMouseEvent({ type: "mousedown" },
+    document.getElementById("details-pane-toggle"));
+  EventUtils.sendMouseEvent({ type: "mousedown" },
+    document.querySelectorAll("#details-pane tab")[3]);
+
+  yield monitor.panelWin.once(EVENTS.RESPONSE_BODY_DISPLAYED);
+  let editor = yield NetMonitorView.editor("#response-content-textarea");
+  // u044F = я
+  is(editor.getText().indexOf("\u044F"), 486,
+    "The text shown in the source editor is correct.");
+  is(editor.getMode(), Editor.modes.html,
+    "The mode active in the source editor is correct.");
+
+  return teardown(monitor);
+});