Bug 840292: Change debugging server xpcshell tests to use a "listTabs" request, rather than a "listContexts" request. r=dcamp
authorJim Blandy <jimb@mozilla.com>
Tue, 07 May 2013 10:20:34 -0700
changeset 142095 f0653eab4d95719c829b118174382cfa679a296e
parent 142094 aa6a74a92890c873e81a3fd201d49292aa46d672
child 142096 c39614efd2637b174d3a5272c1633762a2d1259e
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdcamp
bugs840292
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 840292: Change debugging server xpcshell tests to use a "listTabs" request, rather than a "listContexts" request. r=dcamp The original protocol specification had a "listContexts" request, but that was only ever implemented in the test harness. The real server has always used a browser-appropriate "listTabs" request. The latter is now documented, and the former has been removed from the spec. This is preparation for using a common root actor implementation for all servers: the xpcshell tests now actually use the protocol such a common root actor would speak.
toolkit/devtools/debugger/tests/unit/head_dbg.js
toolkit/devtools/debugger/tests/unit/test_attach.js
toolkit/devtools/debugger/tests/unit/test_breakpoint-01.js
toolkit/devtools/debugger/tests/unit/test_breakpoint-02.js
toolkit/devtools/debugger/tests/unit/test_breakpoint-03.js
toolkit/devtools/debugger/tests/unit/test_breakpoint-04.js
toolkit/devtools/debugger/tests/unit/test_breakpoint-05.js
toolkit/devtools/debugger/tests/unit/test_breakpoint-06.js
toolkit/devtools/debugger/tests/unit/test_breakpoint-07.js
toolkit/devtools/debugger/tests/unit/test_breakpoint-08.js
toolkit/devtools/debugger/tests/unit/test_breakpoint-09.js
toolkit/devtools/debugger/tests/unit/test_breakpoint-10.js
toolkit/devtools/debugger/tests/unit/test_breakpoint-11.js
toolkit/devtools/debugger/tests/unit/test_breakpoint-12.js
toolkit/devtools/debugger/tests/unit/test_dbgactor.js
toolkit/devtools/debugger/tests/unit/test_dbgclient_debuggerstatement.js
toolkit/devtools/debugger/tests/unit/test_dbgsocket.js
toolkit/devtools/debugger/tests/unit/test_eval-01.js
toolkit/devtools/debugger/tests/unit/test_eval-02.js
toolkit/devtools/debugger/tests/unit/test_eval-03.js
toolkit/devtools/debugger/tests/unit/test_eval-04.js
toolkit/devtools/debugger/tests/unit/test_eval-05.js
toolkit/devtools/debugger/tests/unit/test_frameactor-01.js
toolkit/devtools/debugger/tests/unit/test_frameactor-02.js
toolkit/devtools/debugger/tests/unit/test_frameactor-03.js
toolkit/devtools/debugger/tests/unit/test_frameactor-04.js
toolkit/devtools/debugger/tests/unit/test_frameactor-05.js
toolkit/devtools/debugger/tests/unit/test_framearguments-01.js
toolkit/devtools/debugger/tests/unit/test_framebindings-01.js
toolkit/devtools/debugger/tests/unit/test_framebindings-02.js
toolkit/devtools/debugger/tests/unit/test_framebindings-03.js
toolkit/devtools/debugger/tests/unit/test_framebindings-04.js
toolkit/devtools/debugger/tests/unit/test_framebindings-05.js
toolkit/devtools/debugger/tests/unit/test_framebindings-06.js
toolkit/devtools/debugger/tests/unit/test_frameclient-01.js
toolkit/devtools/debugger/tests/unit/test_frameclient-02.js
toolkit/devtools/debugger/tests/unit/test_functiongrips-01.js
toolkit/devtools/debugger/tests/unit/test_interrupt.js
toolkit/devtools/debugger/tests/unit/test_listsources-01.js
toolkit/devtools/debugger/tests/unit/test_listsources-02.js
toolkit/devtools/debugger/tests/unit/test_listsources-03.js
toolkit/devtools/debugger/tests/unit/test_longstringgrips-01.js
toolkit/devtools/debugger/tests/unit/test_longstringgrips-02.js
toolkit/devtools/debugger/tests/unit/test_new_source-01.js
toolkit/devtools/debugger/tests/unit/test_objectgrips-01.js
toolkit/devtools/debugger/tests/unit/test_objectgrips-02.js
toolkit/devtools/debugger/tests/unit/test_objectgrips-03.js
toolkit/devtools/debugger/tests/unit/test_objectgrips-04.js
toolkit/devtools/debugger/tests/unit/test_pause_exceptions-01.js
toolkit/devtools/debugger/tests/unit/test_pause_exceptions-02.js
toolkit/devtools/debugger/tests/unit/test_pauselifetime-01.js
toolkit/devtools/debugger/tests/unit/test_pauselifetime-02.js
toolkit/devtools/debugger/tests/unit/test_pauselifetime-03.js
toolkit/devtools/debugger/tests/unit/test_pauselifetime-04.js
toolkit/devtools/debugger/tests/unit/test_source-01.js
toolkit/devtools/debugger/tests/unit/test_sourcemaps-01.js
toolkit/devtools/debugger/tests/unit/test_sourcemaps-02.js
toolkit/devtools/debugger/tests/unit/test_sourcemaps-03.js
toolkit/devtools/debugger/tests/unit/test_sourcemaps-04.js
toolkit/devtools/debugger/tests/unit/test_sourcemaps-05.js
toolkit/devtools/debugger/tests/unit/test_stepping-01.js
toolkit/devtools/debugger/tests/unit/test_stepping-02.js
toolkit/devtools/debugger/tests/unit/test_stepping-03.js
toolkit/devtools/debugger/tests/unit/test_stepping-04.js
toolkit/devtools/debugger/tests/unit/test_stepping-05.js
toolkit/devtools/debugger/tests/unit/test_threadlifetime-01.js
toolkit/devtools/debugger/tests/unit/test_threadlifetime-02.js
toolkit/devtools/debugger/tests/unit/test_threadlifetime-03.js
toolkit/devtools/debugger/tests/unit/test_threadlifetime-04.js
toolkit/devtools/debugger/tests/unit/test_threadlifetime-05.js
toolkit/devtools/debugger/tests/unit/test_threadlifetime-06.js
toolkit/devtools/debugger/tests/unit/testactors.js
--- a/toolkit/devtools/debugger/tests/unit/head_dbg.js
+++ b/toolkit/devtools/debugger/tests/unit/head_dbg.js
@@ -92,70 +92,62 @@ function testGlobal(aName) {
 
 function addTestGlobal(aName)
 {
   let global = testGlobal(aName);
   DebuggerServer.addTestGlobal(global);
   return global;
 }
 
-function getTestGlobalContext(aClient, aName, aCallback) {
-  aClient.request({ "to": "root", "type": "listContexts" }, function(aResponse) {
-    for each (let context in aResponse.contexts) {
-      if (context.global == aName) {
-        aCallback(context);
-        return false;
-      }
-    }
-    aCallback(null);
-  });
-}
-
-function attachTestGlobalClient(aClient, aName, aCallback) {
-  getTestGlobalContext(aClient, aName, function(aContext) {
-    aClient.attachThread(aContext.actor, aCallback, { useSourceMaps: true });
-  });
-}
-
-function attachTestGlobalClientAndResume(aClient, aName, aCallback) {
-  attachTestGlobalClient(aClient, aName, function(aResponse, aThreadClient) {
-    aThreadClient.resume(function(aResponse) {
-      aCallback(aResponse, aThreadClient);
-    });
-  })
-}
-
-function getTestTab(aClient, aName, aCallback) {
-  gClient.listTabs(function (aResponse) {
+// List the DebuggerClient |aClient|'s tabs, look for one whose title is
+// |aTitle|, and apply |aCallback| to the packet's entry for that tab.
+function getTestTab(aClient, aTitle, aCallback) {
+  aClient.listTabs(function (aResponse) {
     for (let tab of aResponse.tabs) {
-      if (tab.title === aName) {
+      if (tab.title === aTitle) {
         aCallback(tab);
         return;
       }
     }
     aCallback(null);
   });
 }
 
-function attachTestTab(aClient, aName, aCallback) {
-  getTestTab(aClient, aName, function (aTab) {
-    gClient.attachTab(aTab.actor, aCallback);
+// Attach to |aClient|'s tab whose title is |aTitle|; pass |aCallback| the
+// response packet and a TabClient instance referring to that tab.
+function attachTestTab(aClient, aTitle, aCallback) {
+  getTestTab(aClient, aTitle, function (aTab) {
+    aClient.attachTab(aTab.actor, aCallback);
   });
 }
 
-function attachTestTabAndResume(aClient, aName, aCallback) {
-  attachTestTab(aClient, aName, function (aResponse, aTabClient) {
+// Attach to |aClient|'s tab whose title is |aTitle|, and then attach to
+// that tab's thread. Pass |aCallback| the thread attach response packet, a
+// TabClient referring to the tab, and a ThreadClient referring to the
+// thread.
+function attachTestThread(aClient, aTitle, aCallback) {
+  attachTestTab(aClient, aTitle, function (aResponse, aTabClient) {
     aClient.attachThread(aResponse.threadActor, function (aResponse, aThreadClient) {
-      aThreadClient.resume(function (aResponse) {
-        aCallback(aResponse, aTabClient, aThreadClient);
-      });
+      aCallback(aResponse, aTabClient, aThreadClient);
     }, { useSourceMaps: true });
   });
 }
 
+// Attach to |aClient|'s tab whose title is |aTitle|, attach to the tab's
+// thread, and then resume it. Pass |aCallback| the thread's response to
+// the 'resume' packet, a TabClient for the tab, and a ThreadClient for the
+// thread.
+function attachTestTabAndResume(aClient, aTitle, aCallback) {
+  attachTestThread(aClient, aTitle, function(aResponse, aTabClient, aThreadClient) {
+    aThreadClient.resume(function (aResponse) {
+      aCallback(aResponse, aTabClient, aThreadClient);
+    });
+  });
+}
+
 /**
  * Initialize the testing debugger server.
  */
 function initTestDebuggerServer()
 {
   DebuggerServer.addActors("resource://test/testactors.js");
   // Allow incoming connections.
   DebuggerServer.init(function () { return true; });
--- a/toolkit/devtools/debugger/tests/unit/test_attach.js
+++ b/toolkit/devtools/debugger/tests/unit/test_attach.js
@@ -1,43 +1,37 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 var gClient;
 var gDebuggee;
 
 function run_test()
 {
-  DebuggerServer.addActors("resource://test/testactors.js");
-
-  // Allow incoming connections.
-  DebuggerServer.init(function () { return true; });
+  initTestDebuggerServer();
   gDebuggee = testGlobal("test-1");
   DebuggerServer.addTestGlobal(gDebuggee);
 
   let transport = DebuggerServer.connectPipe();
   gClient = new DebuggerClient(transport);
   gClient.connect(function(aType, aTraits) {
-    getTestGlobalContext(gClient, "test-1", function(aContext) {
-      test_attach(aContext);
+    attachTestTab(gClient, "test-1", function(aReply, aTabClient) {
+      test_attach(aReply.threadActor);
     });
   });
   do_test_pending();
 }
 
-function test_attach(aContext)
+function test_attach(aThreadActorID)
 {
-  gClient.attachThread(aContext.actor, function(aResponse, aThreadClient) {
+  gClient.attachThread(aThreadActorID, function(aResponse, aThreadClient) {
     do_check_eq(aThreadClient.state, "paused");
-    aThreadClient.resume(function() {
-      cleanup();
-    });
+    aThreadClient.resume(cleanup);
   });
 }
 
 function cleanup()
 {
   gClient.addListener("closed", function(aEvent) {
     do_test_finished();
   });
   gClient.close();
 }
-
--- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-01.js
@@ -10,19 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_simple_breakpoint();
     });
   });
   do_test_pending();
 }
 
 function test_simple_breakpoint()
--- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-02.js
@@ -10,19 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_breakpoint_running();
     });
   });
   do_test_pending();
 }
 
 function test_breakpoint_running()
--- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-03.js
+++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-03.js
@@ -10,22 +10,22 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
-      gThreadClient = aThreadClient;
-      test_skip_breakpoint();
-    });
+    attachTestTabAndResume(gClient,
+                           "test-stack",
+                           function (aResponse, aTabClient, aThreadClient) {
+                             gThreadClient = aThreadClient;
+                             test_skip_breakpoint();
+                           });
   });
   do_test_pending();
 }
 
 function test_skip_breakpoint()
 {
   gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
     let path = getFilePath('test_breakpoint-03.js');
--- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-04.js
+++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-04.js
@@ -10,19 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_child_breakpoint();
     });
   });
   do_test_pending();
 }
 
 function test_child_breakpoint()
--- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-05.js
+++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-05.js
@@ -11,19 +11,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_child_skip_breakpoint();
     });
   });
   do_test_pending();
 }
 
 function test_child_skip_breakpoint()
--- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-06.js
+++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-06.js
@@ -11,19 +11,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_nested_breakpoint();
     });
   });
   do_test_pending();
 }
 
 function test_nested_breakpoint()
--- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-07.js
+++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-07.js
@@ -11,19 +11,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_second_child_skip_breakpoint();
     });
   });
   do_test_pending();
 }
 
 function test_second_child_skip_breakpoint()
--- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-08.js
+++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-08.js
@@ -11,19 +11,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_child_skip_breakpoint();
     });
   });
   do_test_pending();
 }
 
 function test_child_skip_breakpoint()
--- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-09.js
+++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-09.js
@@ -10,19 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_remove_breakpoint();
     });
   });
   do_test_pending();
 }
 
 function test_remove_breakpoint()
--- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-10.js
+++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-10.js
@@ -11,19 +11,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_child_breakpoint();
     });
   });
   do_test_pending();
 }
 
 function test_child_breakpoint()
--- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-11.js
+++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-11.js
@@ -11,19 +11,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_child_breakpoint();
     });
   });
   do_test_pending();
 }
 
 function test_child_breakpoint()
--- a/toolkit/devtools/debugger/tests/unit/test_breakpoint-12.js
+++ b/toolkit/devtools/debugger/tests/unit/test_breakpoint-12.js
@@ -15,19 +15,17 @@ var gBpActor;
 var gCount = 1;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_child_skip_breakpoint();
     });
   });
   do_test_pending();
 }
 
 function test_child_skip_breakpoint()
--- a/toolkit/devtools/debugger/tests/unit/test_dbgactor.js
+++ b/toolkit/devtools/debugger/tests/unit/test_dbgactor.js
@@ -2,76 +2,108 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
 Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
 
 var gClient;
 var gDebuggee;
 
+const xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
+
 function run_test()
 {
-  DebuggerServer.addActors("resource://test/testactors.js");
-
-  // Allow incoming connections.
-  DebuggerServer.init(function () { return true; });
+  initTestDebuggerServer();
   gDebuggee = testGlobal("test-1");
   DebuggerServer.addTestGlobal(gDebuggee);
 
   let transport = DebuggerServer.connectPipe();
   gClient = new DebuggerClient(transport);
   gClient.addListener("connected", function(aEvent, aType, aTraits) {
-    gClient.request({ to: "root", type: "listContexts" }, function(aResponse) {
-      do_check_true('contexts' in aResponse);
-      for each (let context in aResponse.contexts) {
-        if (context.global == "test-1") {
-          test_attach(context);
+    gClient.listTabs((aResponse) => {
+      do_check_true('tabs' in aResponse);
+      for (let tab of aResponse.tabs) {
+        if (tab.title == "test-1") {
+          test_attach_tab(tab.actor);
           return false;
         }
       }
-      do_check_true(false);
+      do_check_true(false); // We should have found our tab in the list.
     });
   });
+
   gClient.connect();
 
   do_test_pending();
 }
 
-function test_attach(aContext)
+// Attach to |aTabActor|, and check the response.
+function test_attach_tab(aTabActor)
 {
-  gClient.request({ to: aContext.actor, type: "attach" }, function(aResponse) {
-    do_check_true(!aResponse.error);
+  gClient.request({ to: aTabActor, type: "attach" }, function(aResponse) {
+    do_check_false("error" in aResponse);
+    do_check_eq(aResponse.from, aTabActor);
+    do_check_eq(aResponse.type, "tabAttached");
+    do_check_true(typeof aResponse.threadActor === "string");
+
+    test_attach_thread(aResponse.threadActor);
+  });
+}
+
+// Attach to |aThreadActor|, check the response, and resume it.
+function test_attach_thread(aThreadActor)
+{
+  gClient.request({ to: aThreadActor, type: "attach" }, function(aResponse) {
+    do_check_false("error" in aResponse);
+    do_check_eq(aResponse.from, aThreadActor);
     do_check_eq(aResponse.type, "paused");
+    do_check_true("why" in aResponse);
+    do_check_eq(aResponse.why.type, "attached");
 
-    // Resume the thread and test the debugger statement.
-    gClient.request({ to: aContext.actor, type: "resume" }, function() {
-      test_debugger_statement(aContext);
-    });
+    test_resume_thread(aThreadActor);
   });
 }
 
-function test_debugger_statement(aContext)
+// Resume |aThreadActor|, and see that it stops at the 'debugger'
+// statement.
+function test_resume_thread(aThreadActor)
 {
+  // Allow the client to resume execution.
+  gClient.request({ to: aThreadActor, type: "resume" }, function (aResponse) {
+    do_check_false("error" in aResponse);
+    do_check_eq(aResponse.from, aThreadActor);
+    do_check_eq(aResponse.type, "resumed");
+
+    do_check_eq(xpcInspector.eventLoopNestLevel, 0);
+
+    // Now that we know we're resumed, we can make the debuggee do something.
+    Cu.evalInSandbox("var a = true; var b = false; debugger; var b = true;", gDebuggee);
+    // Now make sure that we've run the code after the debugger statement...
+    do_check_true(gDebuggee.b);
+  });
+
   gClient.addListener("paused", function(aName, aPacket) {
+    do_check_eq(aName, "paused");
+    do_check_false("error" in aPacket);
+    do_check_eq(aPacket.from, aThreadActor);
+    do_check_eq(aPacket.type, "paused");
+    do_check_true("actor" in aPacket);
+    do_check_true("why" in aPacket)
+    do_check_eq(aPacket.why.type, "debuggerStatement");
+
     // Reach around the protocol to check that the debuggee is in the state
     // we expect.
     do_check_true(gDebuggee.a);
     do_check_false(gDebuggee.b);
 
-    let xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
     do_check_eq(xpcInspector.eventLoopNestLevel, 1);
 
-    gClient.request({ to: aContext.actor, type: "resume" }, function() {
-      cleanup();
-    });
+    // Let the debuggee continue execution.
+    gClient.request({ to: aThreadActor, type: "resume" }, cleanup);
   });
-
-  Cu.evalInSandbox("var a = true; var b = false; debugger; var b = true;", gDebuggee);
-  // Now make sure that we've run the code after the debugger statement...
-  do_check_true(gDebuggee.b);
 }
 
 function cleanup()
 {
   gClient.addListener("closed", function(aEvent, aResult) {
     do_test_finished();
   });
 
--- a/toolkit/devtools/debugger/tests/unit/test_dbgclient_debuggerstatement.js
+++ b/toolkit/devtools/debugger/tests/unit/test_dbgclient_debuggerstatement.js
@@ -4,38 +4,36 @@
 Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
 Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
 
 var gClient;
 var gDebuggee;
 
 function run_test()
 {
-  DebuggerServer.addActors("resource://test/testactors.js");
-
-  // Allow incoming connections.
-  DebuggerServer.init(function () { return true; });
+  initTestDebuggerServer();
   gDebuggee = testGlobal("test-1");
   DebuggerServer.addTestGlobal(gDebuggee);
 
   let transport = DebuggerServer.connectPipe();
   gClient = new DebuggerClient(transport);
   gClient.connect(function(aType, aTraits) {
-    getTestGlobalContext(gClient, "test-1", function(aContext) {
-      test_attach(aContext);
+    attachTestTab(gClient, "test-1", function(aReply, aTabClient) {
+      test_threadAttach(aReply.threadActor);
     });
   });
   do_test_pending();
 }
 
-function test_attach(aContext)
+function test_threadAttach(aThreadActorID)
 {
-  gClient.attachThread(aContext.actor, function(aResponse, aThreadClient) {
+  do_print("Trying to attach to thread " + aThreadActorID);
+  gClient.attachThread(aThreadActorID, function(aResponse, aThreadClient) {
     do_check_eq(aThreadClient.state, "paused");
-    do_check_eq(aThreadClient.actor, aContext.actor);
+    do_check_eq(aThreadClient.actor, aThreadActorID);
     aThreadClient.resume(function() {
       do_check_eq(aThreadClient.state, "attached");
       test_debugger_statement(aThreadClient);
     });
   });
 }
 
 function test_debugger_statement(aThreadClient)
@@ -45,19 +43,17 @@ function test_debugger_statement(aThread
     // Reach around the protocol to check that the debuggee is in the state
     // we expect.
     do_check_true(gDebuggee.a);
     do_check_false(gDebuggee.b);
 
     let xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
     do_check_eq(xpcInspector.eventLoopNestLevel, 1);
 
-    aThreadClient.resume(function() {
-      cleanup();
-    });
+    aThreadClient.resume(cleanup);
   });
 
   Cu.evalInSandbox("var a = true; var b = false; debugger; var b = true;", gDebuggee);
 
   // Now make sure that we've run the code after the debugger statement...
   do_check_true(gDebuggee.b);
 }
 
--- a/toolkit/devtools/debugger/tests/unit/test_dbgsocket.js
+++ b/toolkit/devtools/debugger/tests/unit/test_dbgsocket.js
@@ -4,19 +4,17 @@
 Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
 Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
 
 let port = 2929;
 
 function run_test()
 {
   do_print("Starting test at " + new Date().toTimeString());
-  // Allow incoming connections.
-  DebuggerServer.init(function () true);
-  DebuggerServer.addActors("resource://test/testactors.js");
+  initTestDebuggerServer();
 
   add_test(test_socket_conn);
   add_test(test_socket_shutdown);
   add_test(test_pipe_conn);
 
   run_next_test();
 }
 
--- a/toolkit/devtools/debugger/tests/unit/test_eval-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_eval-01.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_simple_eval();
     });
   });
   do_test_pending();
 }
 
 function test_simple_eval()
--- a/toolkit/devtools/debugger/tests/unit/test_eval-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_eval-02.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_throw_eval();
     });
   });
   do_test_pending();
 }
 
 function test_throw_eval()
--- a/toolkit/devtools/debugger/tests/unit/test_eval-03.js
+++ b/toolkit/devtools/debugger/tests/unit/test_eval-03.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_syntax_error_eval();
     });
   });
   do_test_pending();
 }
 
 function test_syntax_error_eval()
--- a/toolkit/devtools/debugger/tests/unit/test_eval-04.js
+++ b/toolkit/devtools/debugger/tests/unit/test_eval-04.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_syntax_error_eval();
     });
   });
   do_test_pending();
 }
 
 function test_syntax_error_eval()
--- a/toolkit/devtools/debugger/tests/unit/test_eval-05.js
+++ b/toolkit/devtools/debugger/tests/unit/test_eval-05.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_syntax_error_eval();
     });
   });
   do_test_pending();
 }
 
 function test_syntax_error_eval()
--- a/toolkit/devtools/debugger/tests/unit/test_frameactor-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_frameactor-01.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_frameactor-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_frameactor-02.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_frameactor-03.js
+++ b/toolkit/devtools/debugger/tests/unit/test_frameactor-03.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_frameactor-04.js
+++ b/toolkit/devtools/debugger/tests/unit/test_frameactor-04.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 var gFrames = [
--- a/toolkit/devtools/debugger/tests/unit/test_frameactor-05.js
+++ b/toolkit/devtools/debugger/tests/unit/test_frameactor-05.js
@@ -11,17 +11,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_frame_slice() {
--- a/toolkit/devtools/debugger/tests/unit/test_framearguments-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_framearguments-01.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_framebindings-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_framebindings-01.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_framebindings-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_framebindings-02.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_framebindings-03.js
+++ b/toolkit/devtools/debugger/tests/unit/test_framebindings-03.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_framebindings-04.js
+++ b/toolkit/devtools/debugger/tests/unit/test_framebindings-04.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_framebindings-05.js
+++ b/toolkit/devtools/debugger/tests/unit/test_framebindings-05.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_framebindings-06.js
+++ b/toolkit/devtools/debugger/tests/unit/test_framebindings-06.js
@@ -7,17 +7,17 @@ var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
 
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_banana_environment();
     });
   });
   do_test_pending();
 }
 
 function test_banana_environment()
--- a/toolkit/devtools/debugger/tests/unit/test_frameclient-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_frameclient-01.js
@@ -6,17 +6,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_frameclient-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_frameclient-02.js
@@ -6,17 +6,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_functiongrips-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_functiongrips-01.js
@@ -10,17 +10,17 @@ function run_test()
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gDebuggee.eval(function stopMe(arg1) {
     debugger;
   }.toString());
 
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_named_function();
     });
   });
   do_test_pending();
 }
 
 function test_named_function()
--- a/toolkit/devtools/debugger/tests/unit/test_interrupt.js
+++ b/toolkit/devtools/debugger/tests/unit/test_interrupt.js
@@ -1,36 +1,31 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 var gClient;
 var gDebuggee;
 
 function run_test()
 {
-  DebuggerServer.addActors("resource://test/testactors.js");
-
-  // Allow incoming connections.
-  DebuggerServer.init(function () { return true; });
+  initTestDebuggerServer();
   gDebuggee = testGlobal("test-1");
   DebuggerServer.addTestGlobal(gDebuggee);
 
   let transport = DebuggerServer.connectPipe();
   gClient = new DebuggerClient(transport);
   gClient.connect(function(aType, aTraits) {
-    getTestGlobalContext(gClient, "test-1", function(aContext) {
-      test_attach(aContext);
-    });
+    attachTestTab(gClient, "test-1", test_attach);
   });
   do_test_pending();
 }
 
-function test_attach(aContext)
+function test_attach(aResponse, aTabClient)
 {
-  gClient.attachThread(aContext.actor, function(aResponse, aThreadClient) {
+  gClient.attachThread(aResponse.threadActor, function(aResponse, aThreadClient) {
     do_check_eq(aThreadClient.paused, true);
     aThreadClient.resume(function() {
       test_interrupt();
     });
   });
 }
 
 function test_interrupt()
--- a/toolkit/devtools/debugger/tests/unit/test_listsources-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_listsources-01.js
@@ -20,17 +20,17 @@ function run_test()
     return function (aRequest, aOnResponse) {
       if (aRequest.type === "sources") {
         ++gNumTimesSourcesSent;
       }
       return request.call(this, aRequest, aOnResponse);
     };
   }(gClient.request));
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_simple_listsources();
     });
   });
   do_test_pending();
 }
 
 function test_simple_listsources()
--- a/toolkit/devtools/debugger/tests/unit/test_listsources-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_listsources-02.js
@@ -23,17 +23,17 @@ function run_test()
       }
       return request.call(this, aRequest, aOnResponse);
     };
   }(gClient.request));
   // Make sure that the eval script from addTestGlobal() won't interfere with
   // the test.
   gc();
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_listing_zero_sources();
     });
   });
   do_test_pending();
 }
 
 function test_listing_zero_sources()
--- a/toolkit/devtools/debugger/tests/unit/test_listsources-03.js
+++ b/toolkit/devtools/debugger/tests/unit/test_listsources-03.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-sources");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient, "test-sources", function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-sources", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_simple_listsources();
     });
   });
   do_test_pending();
 }
 
 function test_simple_listsources()
--- a/toolkit/devtools/debugger/tests/unit/test_longstringgrips-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_longstringgrips-01.js
@@ -10,17 +10,17 @@ function run_test()
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gDebuggee.eval(function stopMe(arg1) {
     debugger;
   }.toString());
 
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_longstring_grip();
     });
   });
   do_test_pending();
 }
 
 function test_longstring_grip()
--- a/toolkit/devtools/debugger/tests/unit/test_longstringgrips-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_longstringgrips-02.js
@@ -10,18 +10,18 @@ function run_test()
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gDebuggee.eval(function stopMe(arg1) {
     debugger;
   }.toString());
 
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(
-      gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(
+      gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
         gThreadClient = aThreadClient;
         test_longstring_grip();
       });
   });
   do_test_pending();
 }
 
 function test_longstring_grip()
--- a/toolkit/devtools/debugger/tests/unit/test_new_source-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_new_source-01.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_simple_new_source();
     });
   });
   do_test_pending();
 }
 
 function test_simple_new_source()
--- a/toolkit/devtools/debugger/tests/unit/test_objectgrips-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_objectgrips-01.js
@@ -10,17 +10,17 @@ function run_test()
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gDebuggee.eval(function stopMe(arg1) {
     debugger;
   }.toString());
 
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_object_grip();
     });
   });
   do_test_pending();
 }
 
 function test_object_grip()
--- a/toolkit/devtools/debugger/tests/unit/test_objectgrips-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_objectgrips-02.js
@@ -10,17 +10,17 @@ function run_test()
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gDebuggee.eval(function stopMe(arg1) {
     debugger;
   }.toString());
 
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_object_grip();
     });
   });
   do_test_pending();
 }
 
 function test_object_grip()
--- a/toolkit/devtools/debugger/tests/unit/test_objectgrips-03.js
+++ b/toolkit/devtools/debugger/tests/unit/test_objectgrips-03.js
@@ -10,17 +10,17 @@ function run_test()
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gDebuggee.eval(function stopMe(arg1) {
     debugger;
   }.toString());
 
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_object_grip();
     });
   });
   do_test_pending();
 }
 
 function test_object_grip()
--- a/toolkit/devtools/debugger/tests/unit/test_objectgrips-04.js
+++ b/toolkit/devtools/debugger/tests/unit/test_objectgrips-04.js
@@ -10,17 +10,17 @@ function run_test()
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gDebuggee.eval(function stopMe(arg1) {
     debugger;
   }.toString());
 
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_object_grip();
     });
   });
   do_test_pending();
 }
 
 function test_object_grip()
--- a/toolkit/devtools/debugger/tests/unit/test_pause_exceptions-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_pause_exceptions-01.js
@@ -11,17 +11,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_pause_exceptions-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_pause_exceptions-02.js
@@ -11,17 +11,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_pauselifetime-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_pauselifetime-01.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_pauselifetime-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_pauselifetime-02.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_pauselifetime-03.js
+++ b/toolkit/devtools/debugger/tests/unit/test_pauselifetime-03.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_pauselifetime-04.js
+++ b/toolkit/devtools/debugger/tests/unit/test_pauselifetime-04.js
@@ -11,17 +11,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_pause_frame();
     });
   });
   do_test_pending();
 }
 
 function test_pause_frame()
--- a/toolkit/devtools/debugger/tests/unit/test_source-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_source-01.js
@@ -15,17 +15,17 @@ function run_test()
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gDebuggee.eval(function stopMe(arg1) {
     debugger;
   }.toString());
 
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       gThreadClient.addListener("unsolicitedPause", unsolicitedPauseListener);
       test_source();
     });
   });
   do_test_pending();
 }
 
--- a/toolkit/devtools/debugger/tests/unit/test_sourcemaps-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_sourcemaps-01.js
@@ -12,17 +12,17 @@ var gThreadClient;
 Components.utils.import('resource:///modules/devtools/SourceMap.jsm');
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-source-map");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-source-map", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-source-map", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_simple_source_map();
     });
   });
   do_test_pending();
 }
 
 function test_simple_source_map()
--- a/toolkit/devtools/debugger/tests/unit/test_sourcemaps-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_sourcemaps-02.js
@@ -12,17 +12,17 @@ var gThreadClient;
 Components.utils.import("resource:///modules/devtools/SourceMap.jsm");
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-source-map");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-source-map", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-source-map", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_simple_source_map();
     });
   });
   do_test_pending();
 }
 
 function test_simple_source_map()
--- a/toolkit/devtools/debugger/tests/unit/test_sourcemaps-03.js
+++ b/toolkit/devtools/debugger/tests/unit/test_sourcemaps-03.js
@@ -12,17 +12,17 @@ var gThreadClient;
 Components.utils.import('resource:///modules/devtools/SourceMap.jsm');
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-source-map");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-source-map", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-source-map", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_simple_source_map();
     });
   });
   do_test_pending();
 }
 
 function testBreakpointMapping(aName, aCallback)
--- a/toolkit/devtools/debugger/tests/unit/test_sourcemaps-04.js
+++ b/toolkit/devtools/debugger/tests/unit/test_sourcemaps-04.js
@@ -12,17 +12,17 @@ var gThreadClient;
 Components.utils.import('resource:///modules/devtools/SourceMap.jsm');
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-source-map");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-source-map", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-source-map", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_absolute_source_map();
     });
   });
   do_test_pending();
 }
 
 function test_absolute_source_map()
--- a/toolkit/devtools/debugger/tests/unit/test_sourcemaps-05.js
+++ b/toolkit/devtools/debugger/tests/unit/test_sourcemaps-05.js
@@ -12,17 +12,17 @@ var gThreadClient;
 Components.utils.import('resource:///modules/devtools/SourceMap.jsm');
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-source-map");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-source-map", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-source-map", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_relative_source_map();
     });
   });
   do_test_pending();
 }
 
 function test_relative_source_map()
--- a/toolkit/devtools/debugger/tests/unit/test_stepping-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_stepping-01.js
@@ -10,19 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_simple_stepping();
     });
   });
   do_test_pending();
 }
 
 function test_simple_stepping()
--- a/toolkit/devtools/debugger/tests/unit/test_stepping-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_stepping-02.js
@@ -10,19 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_simple_stepping();
     });
   });
   do_test_pending();
 }
 
 function test_simple_stepping()
--- a/toolkit/devtools/debugger/tests/unit/test_stepping-03.js
+++ b/toolkit/devtools/debugger/tests/unit/test_stepping-03.js
@@ -10,19 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_simple_stepping();
     });
   });
   do_test_pending();
 }
 
 function test_simple_stepping()
--- a/toolkit/devtools/debugger/tests/unit/test_stepping-04.js
+++ b/toolkit/devtools/debugger/tests/unit/test_stepping-04.js
@@ -10,19 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_simple_stepping();
     });
   });
   do_test_pending();
 }
 
 function test_simple_stepping()
--- a/toolkit/devtools/debugger/tests/unit/test_stepping-05.js
+++ b/toolkit/devtools/debugger/tests/unit/test_stepping-05.js
@@ -12,19 +12,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-stack");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function () {
-    attachTestGlobalClientAndResume(gClient,
-                                    "test-stack",
-                                    function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_stepping_last();
     });
   });
   do_test_pending();
 }
 
 function test_stepping_last()
--- a/toolkit/devtools/debugger/tests/unit/test_threadlifetime-01.js
+++ b/toolkit/devtools/debugger/tests/unit/test_threadlifetime-01.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_thread_lifetime();
     });
   });
   do_test_pending();
 }
 
 function test_thread_lifetime()
--- a/toolkit/devtools/debugger/tests/unit/test_threadlifetime-02.js
+++ b/toolkit/devtools/debugger/tests/unit/test_threadlifetime-02.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_thread_lifetime();
     });
   });
   do_test_pending();
 }
 
 function test_thread_lifetime()
--- a/toolkit/devtools/debugger/tests/unit/test_threadlifetime-03.js
+++ b/toolkit/devtools/debugger/tests/unit/test_threadlifetime-03.js
@@ -10,17 +10,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_thread_lifetime();
     });
   });
   do_test_pending();
 }
 
 function test_thread_lifetime()
--- a/toolkit/devtools/debugger/tests/unit/test_threadlifetime-04.js
+++ b/toolkit/devtools/debugger/tests/unit/test_threadlifetime-04.js
@@ -11,17 +11,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function (aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_thread_lifetime();
     });
   });
   do_test_pending();
 }
 
 function test_thread_lifetime()
--- a/toolkit/devtools/debugger/tests/unit/test_threadlifetime-05.js
+++ b/toolkit/devtools/debugger/tests/unit/test_threadlifetime-05.js
@@ -12,17 +12,17 @@ var gThreadClient;
 var gPauseGrip;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_thread_lifetime();
     });
   });
   do_test_pending();
 }
 
 function arg_grips(aFrameArgs, aOnResponse) {
--- a/toolkit/devtools/debugger/tests/unit/test_threadlifetime-06.js
+++ b/toolkit/devtools/debugger/tests/unit/test_threadlifetime-06.js
@@ -11,17 +11,17 @@ var gClient;
 var gThreadClient;
 
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-grips");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
-    attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
+    attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
       test_thread_lifetime();
     });
   });
   do_test_pending();
 }
 
 function test_thread_lifetime()
--- a/toolkit/devtools/debugger/tests/unit/testactors.js
+++ b/toolkit/devtools/debugger/tests/unit/testactors.js
@@ -1,62 +1,102 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 var gTestGlobals = [];
+DebuggerServer.addTestGlobal = function(aGlobal) {
+  gTestGlobals.push(aGlobal);
+};
 
-function createRootActor()
+function createRootActor(aConnection)
+{
+  return new TestRootActor(aConnection);
+}
+
+function TestRootActor(aConnection)
 {
-  let actor = {
-    sayHello: function() {
-      this._globalActors = [];
-      for each (let g in gTestGlobals) {
-        let addBreakpoint = function _addBreakpoint(aActor) {
-          this.conn.addActor(aActor);
-        }.bind(this);
-        let removeBreakpoint = function _removeBreakpoint(aActor) {
-          this.conn.removeActor(aActor);
-        }.bind(this);
-        let hooks = {
-          addToParentPool: addBreakpoint,
-          removeFromParentPool: removeBreakpoint
-        };
-        let actor = new ThreadActor(hooks);
-        actor.addDebuggee(g);
-        actor.global = g;
-        actor.json = function() {
-          return { actor: actor.actorID,
-                   threadActor: actor.actorID,
-                   global: actor.global.__name };
-        };
-        this.conn.addActor(actor);
-        this._globalActors.push(actor);
-      }
+  this.conn = aConnection;
+  this.actorID = "root";
+
+  // An array of actors for each global added with
+  // DebuggerServer.addTestGlobal.
+  this._tabActors = [];
 
-      return {
-        from: "root",
-        applicationType: "xpcshell-tests",
-        testConnectionPrefix: this.conn.prefix,
-        traits: {
-          sources: true
-        }
-      };
-    },
+  // A pool mapping those actors' names to the actors.
+  this._tabActorPool = new ActorPool(aConnection);
 
-    listGlobals: function(aRequest) {
-      return {
-        from: "root",
-        contexts: [ g.json() for each (g in this._globalActors) ]
-      };
-    },
-  };
+  for (let global of gTestGlobals) {
+    let actor = new TestTabActor(aConnection, global);
+    this._tabActors.push(actor);
+    this._tabActorPool.addActor(actor);
+  }
 
-  actor.requestTypes = {
-    "listContexts": actor.listGlobals,
-    "echo": function(aRequest) { return aRequest; },
-  };
-  return actor;
+  aConnection.addActorPool(this._tabActorPool);
 }
 
-DebuggerServer.addTestGlobal = function addTestGlobal(aGlobal)
+TestRootActor.prototype = {
+  constructor: TestRootActor,
+
+  sayHello: function () {
+    return { from: "root",
+             applicationType: "xpcshell-tests",
+             testConnectionPrefix: this.conn.prefix,
+             traits: {
+               sources: true
+             }
+           };
+  },
+
+  onListTabs: function(aRequest) {
+    return { tabs:[actor.grip() for (actor of this._tabActors)], selected:0 };
+  },
+
+  onEcho: function(aRequest) { return aRequest; },
+};
+
+TestRootActor.prototype.requestTypes = {
+  "listTabs": TestRootActor.prototype.onListTabs,
+  "echo": TestRootActor.prototype.onEcho
+};
+
+function TestTabActor(aConnection, aGlobal)
 {
-  gTestGlobals.push(aGlobal);
+  this.conn = aConnection;
+  this._global = aGlobal;
+  this._threadActor = new ThreadActor(this, this._global);
+  this.conn.addActor(this._threadActor);
+  this._attached = false;
 }
+
+TestTabActor.prototype = {
+  constructor: TestTabActor,
+  actorPrefix:"TestTabActor",
+
+  grip: function() {
+    return { actor: this.actorID, title: this._global.__name };
+  },
+
+  onAttach: function(aRequest) {
+    this._attached = true;
+    return { type: "tabAttached", threadActor: this._threadActor.actorID };
+  },
+
+  onDetach: function(aRequest) {
+    if (!this._attached) {
+      return { "error":"wrongState" };
+    }
+    return { type: "detached" };
+  },
+
+  // Hooks for use by TestTabActors.
+  addToParentPool: function(aActor) {
+    this.conn.addActor(aActor);
+  },
+
+  removeFromParentPool: function(aActor) {
+    this.conn.removeActor(aActor);
+  }
+};
+
+TestTabActor.prototype.requestTypes = {
+  "attach": TestTabActor.prototype.onAttach,
+  "detach": TestTabActor.prototype.onDetach
+};