зеркало из 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;
|
let workerActor = this.props.target.actorID;
|
||||||
client.attachWorker(workerActor, (response, workerClient) => {
|
client.attachWorker(workerActor, (response, workerClient) => {
|
||||||
gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
|
gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
|
||||||
"jsdebugger", Toolbox.HostType.WINDOW);
|
"jsdebugger", Toolbox.HostType.WINDOW)
|
||||||
|
.then(toolbox => {
|
||||||
|
toolbox.once("destroy", () => workerClient.detach());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -10,3 +10,4 @@ support-files =
|
||||||
|
|
||||||
[browser_addons_install.js]
|
[browser_addons_install.js]
|
||||||
[browser_service_workers.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"
|
"nsIWorkerDebuggerManager"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyServiceGetter(
|
||||||
|
this, "swm",
|
||||||
|
"@mozilla.org/serviceworkers/manager;1",
|
||||||
|
"nsIServiceWorkerManager"
|
||||||
|
);
|
||||||
|
|
||||||
function matchWorkerDebugger(dbg, options) {
|
function matchWorkerDebugger(dbg, options) {
|
||||||
if ("type" in options && dbg.type !== options.type) {
|
if ("type" in options && dbg.type !== options.type) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -54,6 +60,14 @@ WorkerActor.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._isAttached) {
|
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._dbg.addListener(this);
|
||||||
this._isAttached = true;
|
this._isAttached = true;
|
||||||
}
|
}
|
||||||
|
@ -115,6 +129,11 @@ WorkerActor.prototype = {
|
||||||
reportError("ERROR:" + filename + ":" + lineno + ":" + message + "\n");
|
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 () {
|
_detach: function () {
|
||||||
if (this._threadActor !== null) {
|
if (this._threadActor !== null) {
|
||||||
this._transport.close();
|
this._transport.close();
|
||||||
|
@ -122,6 +141,20 @@ WorkerActor.prototype = {
|
||||||
this._threadActor = null;
|
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._dbg.removeListener(this);
|
||||||
this._isAttached = false;
|
this._isAttached = false;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче