зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1228382 - Keep service worker alive when attaching to them. r=janx,ejpbruel
This commit is contained in:
Родитель
da5ef790fb
Коммит
aff2effa69
|
@ -41,7 +41,10 @@ exports.TargetComponent = React.createClass({
|
|||
let workerActor = this.props.target.actorID;
|
||||
client.attachWorker(workerActor, (response, workerClient) => {
|
||||
gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
|
||||
"jsdebugger", Toolbox.HostType.WINDOW);
|
||||
"jsdebugger", Toolbox.HostType.WINDOW)
|
||||
.then(toolbox => {
|
||||
toolbox.once("destroy", () => workerClient.detach());
|
||||
});
|
||||
});
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -10,3 +10,4 @@ support-files =
|
|||
|
||||
[browser_addons_install.js]
|
||||
[browser_service_workers.js]
|
||||
[browser_service_workers_timeout.js]
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Service workers can't be loaded from chrome://,
|
||||
// but http:// is ok with dom.serviceWorkers.testing.enabled turned on.
|
||||
const HTTP_ROOT = CHROME_ROOT.replace("chrome://mochitests/content/",
|
||||
"http://mochi.test:8888/");
|
||||
const SERVICE_WORKER = HTTP_ROOT + "service-workers/empty-sw.js";
|
||||
const TAB_URL = HTTP_ROOT + "service-workers/empty-sw.html";
|
||||
|
||||
const SW_TIMEOUT = 1000;
|
||||
|
||||
function waitForWorkersUpdate(document) {
|
||||
return new Promise(done => {
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
observer.disconnect();
|
||||
done();
|
||||
});
|
||||
var target = document.getElementById("service-workers");
|
||||
observer.observe(target, { childList: true });
|
||||
});
|
||||
}
|
||||
|
||||
function assertHasWorker(expected, document, type, name) {
|
||||
let names = [...document.querySelectorAll("#" + type + " .target-name")];
|
||||
names = names.map(element => element.textContent);
|
||||
is(names.includes(name), expected, "The " + type + " url appears in the list: " + names);
|
||||
}
|
||||
|
||||
add_task(function *() {
|
||||
yield new Promise(done => {
|
||||
let options = {"set": [
|
||||
// Accept workers from mochitest's http
|
||||
["dom.serviceWorkers.testing.enabled", true],
|
||||
// Reduce the timeout to expose issues when service worker
|
||||
// freezing is broken
|
||||
["dom.serviceWorkers.idle_timeout", SW_TIMEOUT],
|
||||
["dom.serviceWorkers.idle_extended_timeout", SW_TIMEOUT],
|
||||
]};
|
||||
SpecialPowers.pushPrefEnv(options, done);
|
||||
});
|
||||
|
||||
let { tab, document } = yield openAboutDebugging("workers");
|
||||
|
||||
let swTab = yield addTab(TAB_URL);
|
||||
|
||||
yield waitForWorkersUpdate(document);
|
||||
|
||||
assertHasWorker(true, document, "service-workers", SERVICE_WORKER);
|
||||
|
||||
// XXX: race, the WorkerDebugger is ready whereas ServiceWorkerInfo
|
||||
// doesn't has the worker registered yet on its side
|
||||
yield new Promise(done => {
|
||||
require("sdk/timers").setTimeout(done, 250);
|
||||
});
|
||||
|
||||
// Retrieve the DEBUG button for the worker
|
||||
let names = [...document.querySelectorAll("#service-workers .target-name")];
|
||||
let name = names.filter(element => element.textContent === SERVICE_WORKER)[0];
|
||||
ok(name, "Found the service worker in the list");
|
||||
let debugBtn = name.parentNode.parentNode.querySelector("button");
|
||||
ok(debugBtn, "Found its debug button");
|
||||
|
||||
// Click on it and wait for the toolbox to be ready
|
||||
let onToolboxReady = new Promise(done => {
|
||||
gDevTools.once("toolbox-ready", function (e, toolbox) {
|
||||
done(toolbox);
|
||||
});
|
||||
});
|
||||
debugBtn.click();
|
||||
|
||||
let toolbox = yield onToolboxReady;
|
||||
|
||||
// Wait for more than the regular timeout,
|
||||
// so that if the worker freezing doesn't work,
|
||||
// it will be destroyed and removed from the list
|
||||
yield new Promise(done => {
|
||||
setTimeout(done, SW_TIMEOUT * 2);
|
||||
});
|
||||
|
||||
assertHasWorker(true, document, "service-workers", SERVICE_WORKER);
|
||||
|
||||
yield toolbox.destroy();
|
||||
toolbox = null;
|
||||
|
||||
// Now ensure that the worker is correctly destroyed
|
||||
// after we destroy the toolbox.
|
||||
// The list should update once it get destroyed.
|
||||
yield waitForWorkersUpdate(document);
|
||||
|
||||
assertHasWorker(false, document, "service-workers", SERVICE_WORKER);
|
||||
|
||||
// Finally, unregister the service worker itself
|
||||
// Use message manager to work with e10s
|
||||
let frameScript = function () {
|
||||
// Retrieve the `sw` promise created in the html page
|
||||
let { sw } = content.wrappedJSObject;
|
||||
sw.then(function (registration) {
|
||||
registration.unregister().then(function (success) {
|
||||
dump("SW unregistered: " + success + "\n");
|
||||
},
|
||||
function (e) {
|
||||
dump("SW not unregistered; " + e + "\n");
|
||||
});
|
||||
});
|
||||
};
|
||||
swTab.linkedBrowser.messageManager.loadFrameScript("data:,(" + encodeURIComponent(frameScript) + ")()", true);
|
||||
|
||||
yield removeTab(swTab);
|
||||
yield closeAboutDebugging(tab);
|
||||
});
|
|
@ -11,6 +11,12 @@ XPCOMUtils.defineLazyServiceGetter(
|
|||
"nsIWorkerDebuggerManager"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
this, "swm",
|
||||
"@mozilla.org/serviceworkers/manager;1",
|
||||
"nsIServiceWorkerManager"
|
||||
);
|
||||
|
||||
function matchWorkerDebugger(dbg, options) {
|
||||
if ("type" in options && dbg.type !== options.type) {
|
||||
return false;
|
||||
|
@ -54,6 +60,14 @@ WorkerActor.prototype = {
|
|||
}
|
||||
|
||||
if (!this._isAttached) {
|
||||
// Automatically disable their internal timeout that shut them down
|
||||
// Should be refactored by having actors specific to service workers
|
||||
if (this._dbg.type == Ci.nsIWorkerDebugger.TYPE_SERVICE) {
|
||||
let worker = this._getServiceWorkerInfo();
|
||||
if (worker) {
|
||||
worker.attachDebugger();
|
||||
}
|
||||
}
|
||||
this._dbg.addListener(this);
|
||||
this._isAttached = true;
|
||||
}
|
||||
|
@ -115,6 +129,11 @@ WorkerActor.prototype = {
|
|||
reportError("ERROR:" + filename + ":" + lineno + ":" + message + "\n");
|
||||
},
|
||||
|
||||
_getServiceWorkerInfo: function () {
|
||||
let info = swm.getRegistrationByPrincipal(this._dbg.principal, this._dbg.url);
|
||||
return info.getWorkerByID(this._dbg.serviceWorkerID);
|
||||
},
|
||||
|
||||
_detach: function () {
|
||||
if (this._threadActor !== null) {
|
||||
this._transport.close();
|
||||
|
@ -122,6 +141,20 @@ WorkerActor.prototype = {
|
|||
this._threadActor = null;
|
||||
}
|
||||
|
||||
// If the worker is already destroyed, nsIWorkerDebugger.type throws
|
||||
// (_dbg.closed appears to be false when it throws)
|
||||
let type;
|
||||
try {
|
||||
type = this._dbg.type;
|
||||
} catch(e) {}
|
||||
|
||||
if (type == Ci.nsIWorkerDebugger.TYPE_SERVICE) {
|
||||
let worker = this._getServiceWorkerInfo();
|
||||
if (worker) {
|
||||
worker.detachDebugger();
|
||||
}
|
||||
}
|
||||
|
||||
this._dbg.removeListener(this);
|
||||
this._isAttached = false;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче