Bug 1202486 - [webext] Add test for browser.runtime.connect, fix a few bugs (r=gabor)

This commit is contained in:
Bill McCloskey 2015-09-01 12:20:07 -07:00
parent 42aee3f8d4
commit 7ab0636be2
5 changed files with 193 additions and 4 deletions

View File

@ -51,6 +51,10 @@ function isWhenBeforeOrSame(when1, when2)
var api = context => { return {
runtime: {
connect: function(extensionId, connectInfo) {
if (!connectInfo) {
connectInfo = extensionId;
extensionId = null;
}
let name = connectInfo && connectInfo.name || "";
let recipient = extensionId ? {extensionId} : {extensionId: context.extensionId};
return context.messenger.connect(context.messageManager, name, recipient);

View File

@ -370,6 +370,9 @@ function Port(context, messageManager, name, id, sender)
this.disconnectName = `Extension:Disconnect-${this.id}`;
this.sender = sender;
this.disconnected = false;
this.messageManager.addMessageListener(this.disconnectName, this, true);
this.disconnectListeners = new Set();
}
Port.prototype = {
@ -397,9 +400,9 @@ Port.prototype = {
}
};
this.messageManager.addMessageListener(this.disconnectName, listener, true);
this.disconnectListeners.add(listener);
return () => {
this.messageManager.removeMessageListener(this.disconnectName, listener);
this.disconnectListeners.delete(listener);
};
}).api(),
onMessage: new EventManager(this.context, "Port.onMessage", fire => {
@ -424,9 +427,31 @@ Port.prototype = {
return portObj;
},
disconnect() {
handleDisconnection() {
this.messageManager.removeMessageListener(this.disconnectName, this);
this.context.forgetOnClose(this);
this.disconnect = true;
this.disconnected = true;
},
receiveMessage(msg) {
if (msg.name == this.disconnectName) {
if (this.disconnected) {
return;
}
for (let listener of this.disconnectListeners) {
listener();
}
this.handleDisconnection();
}
},
disconnect() {
if (this.disconnected) {
throw "Attempt to disconnect() a disconnected port";
}
this.handleDisconnection();
this.messageManager.sendAsyncMessage(this.disconnectName);
},

View File

@ -21,5 +21,7 @@ support-files =
[test_ext_contentscript.html]
[test_ext_webrequest.html]
[test_ext_generate.html]
[test_ext_runtime_connect.html]
[test_ext_runtime_disconnect.html]
[test_ext_sandbox_var.html]
[test_ext_storage.html]

View File

@ -0,0 +1,83 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebExtension test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.8">
"use strict";
function backgroundScript() {
browser.runtime.onConnect.addListener(port => {
browser.test.assertEq(port.name, "ernie", "port name correct");
browser.test.assertTrue(port.sender.url.endsWith("file_sample.html"), "URL correct");
browser.test.assertTrue(port.sender.tab.url.endsWith("file_sample.html"), "tab URL correct");
var expected = "message 1";
port.onMessage.addListener(msg => {
browser.test.assertEq(msg, expected, "message is expected");
if (expected == "message 1") {
port.postMessage("message 2");
expected = "message 3";
} else if (expected == "message 3") {
expected = "disconnect";
browser.test.notifyPass("runtime.connect");
}
});
port.onDisconnect.addListener(() => {
browser.test.assertEq(expected, "disconnect", "got disconnection at right time");
});
});
}
function contentScript() {
var port = browser.runtime.connect({name: "ernie"});
port.postMessage("message 1");
port.onMessage.addListener(msg => {
if (msg == "message 2") {
port.postMessage("message 3");
port.disconnect();
}
});
}
let extensionData = {
background: "(" + backgroundScript.toString() + ")()",
manifest: {
"permissions": ["tabs"],
"content_scripts": [{
"matches": ["http://mochi.test/*/file_sample.html"],
"js": ["content_script.js"],
"run_at": "document_start"
}]
},
files: {
"content_script.js": "(" + contentScript.toString() + ")()",
},
};
add_task(function* test_contentscript() {
let extension = ExtensionTestUtils.loadExtension(extensionData);
yield extension.startup();
info("extension loaded");
let win = window.open("file_sample.html");
yield Promise.all([waitForLoad(win), extension.awaitFinish("runtime.connect")]);
win.close();
yield extension.unload();
info("extension unloaded");
});
</script>
</body>
</html>

View File

@ -0,0 +1,75 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebExtension test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.8">
"use strict";
function backgroundScript() {
browser.runtime.onConnect.addListener(port => {
browser.test.assertEq(port.name, "ernie", "port name correct");
port.onDisconnect.addListener(() => {
browser.test.sendMessage("disconnected");
});
browser.test.sendMessage("connected");
});
}
function contentScript() {
browser.runtime.connect({name: "ernie"});
}
let extensionData = {
background: "(" + backgroundScript.toString() + ")()",
manifest: {
"permissions": ["tabs"],
"content_scripts": [{
"matches": ["http://mochi.test/*/file_sample.html"],
"js": ["content_script.js"],
"run_at": "document_start"
}]
},
files: {
"content_script.js": "(" + contentScript.toString() + ")()",
},
};
add_task(function* test_contentscript() {
let extension = ExtensionTestUtils.loadExtension(extensionData);
yield extension.startup();
info("extension loaded");
let win = window.open("file_sample.html");
yield Promise.all([waitForLoad(win), extension.awaitMessage("connected")]);
win.close();
yield extension.awaitMessage("disconnected");
info("win.close() succeeded");
win = window.open("file_sample.html");
yield Promise.all([waitForLoad(win), extension.awaitMessage("connected")]);
// Add an "unload" listener so that we don't put the window in the
// bfcache. This way it gets destroyed immediately upon navigation.
win.addEventListener("unload", function() {});
win.location = "http://example.com";
yield extension.awaitMessage("disconnected");
win.close();
yield extension.unload();
info("extension unloaded");
});
</script>
</body>
</html>