Bug 785920 - reload for workers. r=gavin.sharp

This commit is contained in:
Shane Caraveo 2012-10-12 16:58:50 -07:00
parent 31d9b62d0d
commit ccbe60c88d
4 changed files with 91 additions and 26 deletions

View File

@ -71,24 +71,39 @@ function FrameWorker(url, name) {
this.loaded = false;
this.frame = makeHiddenFrame();
var self = this;
Services.obs.addObserver(function injectController(doc, topic, data) {
if (!doc.defaultView || doc.defaultView != self.frame.contentWindow) {
return;
}
Services.obs.removeObserver(injectController, "document-element-inserted", false);
try {
self.createSandbox();
} catch (e) {
Cu.reportError("FrameWorker: failed to create sandbox for " + url + ". " + e);
}
}, "document-element-inserted", false);
this.frame.setAttribute("src", url);
this.load();
}
FrameWorker.prototype = {
load: function FrameWorker_loadWorker() {
var self = this;
Services.obs.addObserver(function injectController(doc, topic, data) {
if (!doc.defaultView || doc.defaultView != self.frame.contentWindow) {
return;
}
Services.obs.removeObserver(injectController, "document-element-inserted", false);
try {
self.createSandbox();
} catch (e) {
Cu.reportError("FrameWorker: failed to create sandbox for " + url + ". " + e);
}
}, "document-element-inserted", false);
this.frame.setAttribute("src", this.url);
},
reload: function FrameWorker_reloadWorker() {
// push all the ports into pending ports, they will be re-entangled
// during the call to createSandbox after the document is reloaded
for (let [portid, port] in Iterator(this.ports)) {
port._window = null;
this.pendingPorts.push(port);
}
this.ports = {};
this.loaded = false;
this.load();
},
createSandbox: function createSandbox() {
let workerWindow = this.frame.contentWindow;
let sandbox = new Cu.Sandbox(workerWindow);
@ -139,10 +154,10 @@ FrameWorker.prototype = {
// and we delegate ononline and onoffline events to the worker.
// See http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#workerglobalscope
this.frame.addEventListener('offline', function fw_onoffline(event) {
workerWindow.addEventListener('offline', function fw_onoffline(event) {
Cu.evalInSandbox("onoffline();", sandbox);
}, false);
this.frame.addEventListener('online', function fw_ononline(event) {
workerWindow.addEventListener('online', function fw_ononline(event) {
Cu.evalInSandbox("ononline();", sandbox);
}, false);
@ -248,15 +263,12 @@ function makeHiddenFrame() {
return iframe;
}
// public methods on WorkerHandle should conform to the SharedWorker api
function WorkerHandle(port, worker) {
this.port = port;
this._worker = worker;
}
WorkerHandle.prototype = {
get document() {
return this._worker.frame.contentDocument;
},
// XXX - workers have no .close() method, but *do* have a .terminate()
// method which we should implement. However, the worker spec doesn't define
// a callback to be made in the worker when this happens - it all just dies.

View File

@ -27,9 +27,6 @@ function WorkerAPI(provider, port) {
// used for the api.
// later we might even include an API version - version 0 for now!
this._port.postMessage({topic: "social.initialize"});
// backwards compat, remove after Aug 1.
this._port.postMessage({topic: "social.cookie-changed"});
}
WorkerAPI.prototype = {
@ -52,6 +49,13 @@ WorkerAPI.prototype = {
},
handlers: {
"social.reload-worker": function(data) {
getFrameWorkerHandle(this._provider.workerURL, null)._worker.reload();
// the frameworker is going to be reloaded, send the initialization
// so it can have the same startup sequence as if it were loaded
// the first time. This will be queued until the frameworker is ready.
this._port.postMessage({topic: "social.initialize"});
},
"social.user-profile": function (data) {
this._provider.updateUserProfile(data);
},
@ -59,7 +63,8 @@ WorkerAPI.prototype = {
this._provider.setAmbientNotification(data);
},
"social.cookies-get": function(data) {
let document = getFrameWorkerHandle(this._provider.workerURL, null).document;
let document = getFrameWorkerHandle(this._provider.workerURL, null).
_worker.frame.contentDocument;
let cookies = document.cookie.split(";");
let results = [];
cookies.forEach(function(aCookie) {

View File

@ -102,6 +102,43 @@ let tests = {
Services.cookies.add('.example.com', '/', 'cheez', 'burger', false, false, true, MAX_EXPIRY);
port.postMessage({topic: "test-initialization"});
port.postMessage({topic: "test.cookies-get"});
}
},
testWorkerReload: function(next) {
let fw = {};
Cu.import("resource://gre/modules/FrameWorker.jsm", fw);
// get a real handle to the worker so we can watch the unload event
// we watch for the unload of the worker to know it is infact being
// unloaded, after that if we get worker.connected we know that
// the worker was loaded again and ports reconnected
let reloading = false;
let worker = fw.getFrameWorkerHandle(provider.workerURL, undefined, "testWorkerReload");
let win = worker._worker.frame.contentWindow;
win.addEventListener("unload", function workerUnload(e) {
win.removeEventListener("unload", workerUnload);
ok(true, "worker unload event has fired");
reloading = true;
});
let port = provider.getWorkerPort();
ok(port, "provider has a port");
port.onmessage = function (e) {
let topic = e.data.topic;
switch (topic) {
case "test-initialization-complete":
// tell the worker to send the reload msg
port.postMessage({topic: "test-reload-init"});
break;
case "worker.connected":
// we'll get this message from the worker on every load of the worker,
// so we need to ignore it unless we have requested the reload.
if (reloading) {
ok(true, "worker reloaded and testPort was reconnected");
next();
}
break;
}
}
port.postMessage({topic: "test-initialization"});
}
};

View File

@ -33,6 +33,17 @@ onconnect = function(e) {
break;
case "social.cookies-get-response":
testerPort.postMessage({topic: "test.cookies-get-response", data: data});
break;
case "test-reload-init":
// browser_social_sidebar.js started test, tell the sidebar to
// start
apiPort.postMessage({topic: 'social.reload-worker'});
break;
}
}
// used for "test-reload-worker"
if (apiPort && apiPort != port) {
port.postMessage({topic: "worker.connected"})
}
}