Bug 804910 - Part 1. Check for worker load failures and send a notification in case of errors. r=felipe

This commit is contained in:
Shane Caraveo 2012-10-29 21:57:07 -07:00
Родитель 55b72be75a
Коммит e9858c308c
3 изменённых файлов: 92 добавлений и 6 удалений

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

@ -183,8 +183,17 @@ FrameWorker.prototype = {
// removed - at which time we've explicitly killed it anyway.
let worker = this;
workerWindow.addEventListener("load", function loadListener() {
workerWindow.removeEventListener("load", loadListener);
workerWindow.addEventListener("DOMContentLoaded", function loadListener() {
workerWindow.removeEventListener("DOMContentLoaded", loadListener);
// no script, error out now rather than creating ports, etc
let scriptText = workerWindow.document.body.textContent.trim();
if (!scriptText) {
Cu.reportError("FrameWorker: Empty worker script received");
Services.obs.notifyObservers(null, "social:frameworker-error", worker.url);
return;
}
// the iframe has loaded the js file as text - first inject the magic
// port-handling code into the sandbox.
try {
@ -193,6 +202,8 @@ FrameWorker.prototype = {
}
catch (e) {
Cu.reportError("FrameWorker: Error injecting port code into content side of the worker: " + e + "\n" + e.stack);
Services.obs.notifyObservers(null, "social:frameworker-error", worker.url);
return;
}
// and wire up the client message handling.
@ -201,16 +212,18 @@ FrameWorker.prototype = {
}
catch (e) {
Cu.reportError("FrameWorker: Error setting up event listener for chrome side of the worker: " + e + "\n" + e.stack);
Services.obs.notifyObservers(null, "social:frameworker-error", worker.url);
return;
}
// Now get the worker js code and eval it into the sandbox
try {
let scriptText = workerWindow.document.body.textContent;
Cu.evalInSandbox(scriptText, sandbox, "1.8", workerWindow.location.href, 1);
} catch (e) {
Cu.reportError("FrameWorker: Error evaluating worker script for " + worker.name + ": " + e + "; " +
(e.lineNumber ? ("Line #" + e.lineNumber) : "") +
(e.stack ? ("\n" + e.stack) : ""));
Services.obs.notifyObservers(null, "social:frameworker-error", worker.url);
return;
}
@ -341,7 +354,11 @@ function initClientMessageHandler(worker, workerWindow) {
}
switch (data.portTopic) {
// No "port-create" here - client ports are created explicitly.
case "port-connection-error":
// onconnect failed, we cannot connect the port, the worker has
// become invalid
Services.obs.notifyObservers(null, "social:frameworker-error", worker.url);
break;
case "port-close":
// the worker side of the port was closed, so close this side too.
port = worker.ports[portid];

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

@ -65,7 +65,14 @@ function __initWorkerMessageHandler() {
port = new WorkerPort(portid);
ports[portid] = port;
// and call the "onconnect" handler.
onconnect({ports: [port]});
try {
onconnect({ports: [port]});
} catch(e) {
// we have a bad worker and cannot continue, we need to signal
// an error
port._postControlMessage("port-connection-error", JSON.stringify(e.toString()));
throw e;
}
break;
case "port-close":

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

@ -463,5 +463,67 @@ let tests = {
}
ioService.offline = true;
}
}
},
testMissingWorker: function(cbnext) {
Services.obs.addObserver(function handleError() {
Services.obs.removeObserver(handleError, "social:frameworker-error");
ok(true, "social:frameworker-error was handled");
cbnext();
}, 'social:frameworker-error', false);
// don't ever create this file! We want a 404.
let url = "https://example.com/browser/toolkit/components/social/test/browser/worker_is_missing.js";
let worker = getFrameWorkerHandle(url, undefined, "testMissingWorker");
worker.port.onmessage = function(e) {
ok(false, "social:frameworker-error was handled");
cbnext();
}
},
testNoConnectWorker: function(cbnext) {
Services.obs.addObserver(function handleError() {
Services.obs.removeObserver(handleError, "social:frameworker-error");
ok(true, "social:frameworker-error was handled");
cbnext();
}, 'social:frameworker-error', false);
let worker = getFrameWorkerHandle(makeWorkerUrl(function () {}),
undefined, "testNoConnectWorker");
worker.port.onmessage = function(e) {
ok(false, "social:frameworker-error was handled");
cbnext();
}
},
testEmptyWorker: function(cbnext) {
Services.obs.addObserver(function handleError() {
Services.obs.removeObserver(handleError, "social:frameworker-error");
ok(true, "social:frameworker-error was handled");
cbnext();
}, 'social:frameworker-error', false);
let worker = getFrameWorkerHandle("data:application/javascript;charset=utf-8,",
undefined, "testEmptyWorker");
worker.port.onmessage = function(e) {
ok(false, "social:frameworker-error was handled");
cbnext();
}
},
testWorkerConnectError: function(cbnext) {
Services.obs.addObserver(function handleError() {
Services.obs.removeObserver(handleError, "social:frameworker-error");
ok(true, "social:frameworker-error was handled");
cbnext();
}, 'social:frameworker-error', false);
let run = function () {
onconnect = function(e) {
throw new Error("worker failure");
}
}
let worker = getFrameWorkerHandle(makeWorkerUrl(run),
undefined, "testWorkerConnectError");
worker.port.onmessage = function(e) {
ok(false, "social:frameworker-error was handled");
cbnext();
}
},
}