Bug 1469036 - Stop using the ServiceWorkerManager in the child. r=asuth

With parent intercept enabled, the source of truth for ServiceWorker
registrations lives in the parent process. In order to avoid sync messages or
having to wait after every test, we count the number of active registrations
in the parent and inform the children when there is or isn't a registration.

In non-parent-intercept mode, the parent finds out about new service worker
registrations too late, so we have to keep the old code hanging around for the
time being.

Differential Revision: https://phabricator.services.mozilla.com/D12151

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Blake Kaplan 2018-11-26 19:39:13 +00:00
parent 4efd7c3f0e
commit 7c8c896ff5
4 changed files with 69 additions and 7 deletions

View File

@ -10,10 +10,9 @@ support-files = importtesting_chromescript.js
[test_sanityException2.html]
[test_sanityParams.html]
[test_sanityRegisteredServiceWorker.html]
skip-if = serviceworker_e10s
support-files = empty.js
[test_sanityRegisteredServiceWorker2.html]
skip-if = verify || serviceworker_e10s
skip-if = verify
support-files = empty.js
[test_sanityWindowSnapshot.html]
[test_SpecialPowersExtension.html]

View File

@ -27,6 +27,7 @@ Services.scriptloader.loadSubScript("resource://specialpowers/SpecialPowersObser
function SpecialPowersObserver() {
this._isFrameScriptLoaded = false;
this._messageManager = Services.mm;
this._serviceWorkerListener = null;
}
@ -78,6 +79,7 @@ SpecialPowersObserver.prototype._loadFrameScript = function() {
this._messageManager.addMessageListener("SPCleanUpSTSData", this);
this._messageManager.addMessageListener("SPRequestDumpCoverageCounters", this);
this._messageManager.addMessageListener("SPRequestResetCoverageCounters", this);
this._messageManager.addMessageListener("SPCheckServiceWorkers", this);
this._messageManager.loadFrameScript(CHILD_LOGGER_SCRIPT, true);
this._messageManager.loadFrameScript(CHILD_SCRIPT_API, true);
@ -109,6 +111,28 @@ SpecialPowersObserver.prototype.init = function() {
obs.addObserver(this, "http-on-modify-request");
// We would like to check that tests don't leave service workers around
// after they finish, but that information lives in the parent process.
// Ideally, we'd be able to tell the child processes whenever service
// workers are registered or unregistered so they would know at all times,
// but service worker lifetimes are complicated enough to make that
// difficult. For the time being, let the child process know when a test
// registers a service worker so it can ask, synchronously, at the end if
// the service worker had unregister called on it.
let swm = Cc["@mozilla.org/serviceworkers/manager;1"]
.getService(Ci.nsIServiceWorkerManager);
let self = this;
this._serviceWorkerListener = {
onRegister() {
self.onRegister();
},
onUnregister() {
// no-op
},
};
swm.addListener(this._serviceWorkerListener);
this._loadFrameScript();
};
@ -121,6 +145,10 @@ SpecialPowersObserver.prototype.uninit = function() {
});
this._removeProcessCrashObservers();
let swm = Cc["@mozilla.org/serviceworkers/manager;1"]
.getService(Ci.nsIServiceWorkerManager);
swm.removeListener(this._serviceWorkerListener);
if (this._isFrameScriptLoaded) {
this._messageManager.removeMessageListener("SPPrefService", this);
this._messageManager.removeMessageListener("SPProcessCrashManagerWait", this);
@ -144,6 +172,7 @@ SpecialPowersObserver.prototype.uninit = function() {
this._messageManager.removeMessageListener("SPCleanUpSTSData", this);
this._messageManager.removeMessageListener("SPRequestDumpCoverageCounters", this);
this._messageManager.removeMessageListener("SPRequestResetCoverageCounters", this);
this._messageManager.removeMessageListener("SPCheckServiceWorkers", this);
this._messageManager.removeDelayedFrameScript(CHILD_LOGGER_SCRIPT);
this._messageManager.removeDelayedFrameScript(CHILD_SCRIPT_API);
@ -282,3 +311,8 @@ SpecialPowersObserver.prototype.receiveMessage = function(aMessage) {
}
return undefined;
};
SpecialPowersObserver.prototype.onRegister = function() {
this._sendAsyncMessage("SPServiceWorkerRegistered",
{ registered: true });
};

View File

@ -558,6 +558,12 @@ SpecialPowersObserverAPI.prototype = {
return undefined; // See comment at the beginning of this function.
}
case "SPCheckServiceWorkers": {
let swm = Cc["@mozilla.org/serviceworkers/manager;1"]
.getService(Ci.nsIServiceWorkerManager);
return { hasWorkers: swm.getAllRegistrations().length != 0 };
}
case "SPLoadExtension": {
let id = aMessage.data.id;
let ext = aMessage.data.ext;
@ -640,7 +646,7 @@ SpecialPowersObserverAPI.prototype = {
}
default:
throw new SpecialPowersError("Unrecognized Special Powers API");
throw new SpecialPowersError(`Unrecognized Special Powers API: ${aMessage.name}`);
}
// We throw an exception before reaching this explicit return because

View File

@ -25,6 +25,7 @@ function SpecialPowers(window, mm) {
this._encounteredCrashDumpFiles = [];
this._unexpectedCrashDumpFiles = { };
this._crashDumpDir = null;
this._serviceWorkerRegistered = false;
this.DOMWindowUtils = bindDOMWindowUtils(window);
Object.defineProperty(this, "Components", {
configurable: true, enumerable: true, value: this.getFullComponents(),
@ -42,7 +43,8 @@ function SpecialPowers(window, mm) {
"SPPrefService",
"SPProcessCrashService",
"SPSetTestPluginEnabledState",
"SPCleanUpSTSData"];
"SPCleanUpSTSData",
"SPCheckServiceWorkers"];
this.SP_ASYNC_MESSAGES = ["SpecialPowers.Focus",
"SpecialPowers.Quit",
@ -57,6 +59,7 @@ function SpecialPowers(window, mm) {
"SPRequestDumpCoverageCounters",
"SPRequestResetCoverageCounters"];
mm.addMessageListener("SPPingService", this._messageListener);
mm.addMessageListener("SPServiceWorkerRegistered", this._messageListener);
mm.addMessageListener("SpecialPowers.FilesCreated", this._messageListener);
mm.addMessageListener("SpecialPowers.FilesError", this._messageListener);
let self = this;
@ -144,6 +147,10 @@ SpecialPowers.prototype._messageReceived = function(aMessage) {
}
break;
case "SPServiceWorkerRegistered":
this._serviceWorkerRegistered = aMessage.data.registered;
break;
case "SpecialPowers.FilesCreated":
var createdHandler = this._createFilesOnSuccess;
this._createFilesOnSuccess = null;
@ -234,9 +241,25 @@ SpecialPowers.prototype.nestedFrameSetup = function() {
};
SpecialPowers.prototype.isServiceWorkerRegistered = function() {
var swm = Cc["@mozilla.org/serviceworkers/manager;1"]
.getService(Ci.nsIServiceWorkerManager);
return swm.getAllRegistrations().length != 0;
// For the time being, if parent_intercept is false, we can assume that
// ServiceWorkers registered by the current test are all known to the SWM in
// this process.
if (!Services.prefs.getBoolPref("dom.serviceWorkers.parent_intercept", false)) {
let swm = Cc["@mozilla.org/serviceworkers/manager;1"]
.getService(Ci.nsIServiceWorkerManager);
return swm.getAllRegistrations().length != 0;
}
// Please see the comment in SpecialPowersObserver.jsm above
// this._serviceWorkerListener's assignment for what this returns.
if (this._serviceWorkerRegistered) {
// This test registered at least one service worker. Send a synchronous
// call to the parent to make sure that it called unregister on all of its
// service workers.
return this._sendSyncMessage("SPCheckServiceWorkers")[0].hasWorkers;
}
return false;
};
// Attach our API to the window.