Bug 966991 - Ensure cleaning up child processes tab actors when disconnecting. r=jryans

This commit is contained in:
Alexandre Poirot 2014-04-02 15:29:40 -04:00
Родитель 81be981df4
Коммит 052c4e3e3d
4 изменённых файлов: 163 добавлений и 1 удалений

Просмотреть файл

@ -24,12 +24,14 @@ let chromeGlobal = this;
// time we load child.js
DebuggerServer.addChildActors();
let conn;
let onConnect = DevToolsUtils.makeInfallible(function (msg) {
removeMessageListener("debug:connect", onConnect);
let mm = msg.target;
let conn = DebuggerServer.connectToParent(msg.data.prefix, mm);
conn = DebuggerServer.connectToParent(msg.data.prefix, mm);
let actor = new DebuggerServer.ContentActor(conn, chromeGlobal);
let actorPool = new ActorPool(conn);
@ -40,4 +42,15 @@ let chromeGlobal = this;
});
addMessageListener("debug:connect", onConnect);
let onDisconnect = DevToolsUtils.makeInfallible(function (msg) {
removeMessageListener("debug:disconnect", onDisconnect);
// Call DebuggerServerConnection.close to destroy all child actors
// (It should end up calling DebuggerServerConnection.onClosed
// that would actually cleanup all actor pools)
conn.close();
conn = null;
});
addMessageListener("debug:disconnect", onDisconnect);
})();

Просмотреть файл

@ -59,6 +59,7 @@ function loadSubScript(aURL)
}
}
let events = require("sdk/event/core");
let {defer, resolve, reject, promised, all} = require("sdk/core/promise");
this.defer = defer;
this.resolve = resolve;
@ -571,6 +572,7 @@ var DebuggerServer = {
// If we have a child transport, the actor has already
// been created. We need to stop using this message manager.
childTransport.close();
childTransport = null;
aConnection.cancelForwarding(prefix);
} else {
// Otherwise, the app has been closed before the actor
@ -594,6 +596,20 @@ var DebuggerServer = {
Services.obs.addObserver(onMessageManagerDisconnect,
"message-manager-disconnect", false);
events.once(aConnection, "closed", () => {
if (childTransport) {
// When the client disconnects, we have to unplug the dedicated
// ChildDebuggerTransport...
childTransport.close();
childTransport = null;
aConnection.cancelForwarding(prefix);
// ... and notify the child process to clean the tab actors.
mm.sendAsyncMessage("debug:disconnect");
}
Services.obs.removeObserver(onMessageManagerDisconnect, "message-manager-disconnect");
});
mm.sendAsyncMessage("debug:connect", { prefix: prefix });
return deferred.promise;
@ -1156,6 +1172,11 @@ DebuggerServerConnection.prototype = {
*/
onClosed: function DSC_onClosed(aStatus) {
dumpn("Cleaning up connection.");
if (!this._actorPool) {
// Ignore this call if the connection is already closed.
return;
}
events.emit(this, "closed", aStatus);
this._actorPool.cleanup();
this._actorPool = null;

Просмотреть файл

@ -43,3 +43,4 @@ support-files =
[test_inspector_getImageData.html]
[test_memory.html]
[test_preference.html]
[test_connectToChild.html]

Просмотреть файл

@ -0,0 +1,127 @@
<SDOCTYPv HTM.>
<html>
<!--
Bug 966991 - Test DebuggerServer.connectToChild
-->
<head>
<meta charset="utf-8">
<title>Mozilla Bug</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script type="application/javascript;version=1.8">
let Cu = Components.utils;
let Cc = Components.classes;
let Ci = Components.interfaces;
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
window.onload = function() {
SimpleTest.waitForExplicitFinish();
// Always log packets when running tests.
SpecialPowers.pushPrefEnv({
"set": [
["devtools.debugger.log", true]
]
}, runTests);
}
function runTests() {
// Create a minimal iframe with a message manager
let iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
document.body.appendChild(iframe);
let mm = iframe.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
// Register a test actor in the child process so that we can know if and when
// this fake actor is disconnected.
mm.loadFrameScript("data:text/javascript,new " + function FrameScriptScope() {
const {DebuggerServer} = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
if (!DebuggerServer.initialized) {
DebuggerServer.init();
}
function TestActor() {dump("instanciate test actor");}
TestActor.prototype = {
actorPrefix: "test",
disconnect: function () {
sendAsyncMessage("test-actor-disconnected", null);
},
hello: function () {
return {msg:"world"};
}
};
TestActor.prototype.requestTypes = {
"hello": TestActor.prototype.hello
};
DebuggerServer.addTabActor(TestActor, "testActor");
}, false);
// Instantiate a minimal server
DebuggerServer.init(function () { return true; });
DebuggerServer.addBrowserActors();
function firstClient() {
// Fake a first connection to an iframe
let transport = DebuggerServer.connectPipe();
let conn = transport._serverConnection;
let client = new DebuggerClient(transport);
DebuggerServer.connectToChild(conn, mm).then(actor => {
ok(actor.testActor, "Got the test actor");
// Ensure sending at least one request to our actor,
// otherwise it won't be instanciated, nor be disconnected...
client.request({
to: actor.testActor,
type: "hello",
}, function (response) {
// Then close the client. That should end up cleaning our test actor
client.close();
// Ensure that our test actor got cleaned up;
// its disconnect method should be called
mm.addMessageListener("test-actor-disconnected", function listener() {
mm.removeMessageListener("test-actor-disconnected", listener);
ok(true, "Actor is cleaned up");
secondClient(actor.testActor);
});
});
});
}
function secondClient(firstActor) {
// Then fake a second one, that should spawn a new set of tab actors
let transport = DebuggerServer.connectPipe();
let conn = transport._serverConnection;
let client = new DebuggerClient(transport);
DebuggerServer.connectToChild(conn, mm).then(actor => {
ok(actor.testActor, "Got a test actor for the second connection");
isnot(actor.testActor, firstActor, "We get different actor instances between two connections");
client.close(cleanup);
});
}
function cleanup() {
DebuggerServer.destroy();
iframe.remove();
SimpleTest.finish()
}
firstClient();
}
</script>
</pre>
</body>
</html>