Bug 1510654 - Extract service worker actors to dedicated files;r=ochameau,ladybenko

Depends on D15377

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

--HG--
rename : devtools/server/actors/worker/service-worker.js => devtools/server/actors/worker/push-subscription.js
rename : devtools/server/actors/worker/service-worker.js => devtools/server/actors/worker/service-worker-registration.js
rename : devtools/shared/fronts/worker/service-worker.js => devtools/shared/fronts/worker/push-subscription.js
rename : devtools/shared/fronts/worker/service-worker.js => devtools/shared/fronts/worker/service-worker-registration.js
rename : devtools/shared/specs/worker/service-worker.js => devtools/shared/specs/worker/push-subscription.js
rename : devtools/shared/specs/worker/service-worker.js => devtools/shared/specs/worker/service-worker-registration.js
extra : moz-landing-system : lando
This commit is contained in:
Julian Descottes 2019-01-10 17:28:27 +00:00
Родитель c468557cf4
Коммит cf82f78c6e
14 изменённых файлов: 426 добавлений и 363 удалений

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

@ -5,8 +5,10 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'push-subscription.js',
'service-worker-process.js',
'service-worker-registration-list.js',
'service-worker-registration.js',
'service-worker.js',
'worker-target-actor-list.js',
)

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

@ -0,0 +1,36 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const protocol = require("devtools/shared/protocol");
const { pushSubscriptionSpec } =
require("devtools/shared/specs/worker/push-subscription");
const PushSubscriptionActor = protocol.ActorClassWithSpec(pushSubscriptionSpec, {
initialize(conn, subscription) {
protocol.Actor.prototype.initialize.call(this, conn);
this._subscription = subscription;
},
form(detail) {
if (detail === "actorid") {
return this.actorID;
}
const subscription = this._subscription;
return {
actor: this.actorID,
endpoint: subscription.endpoint,
pushCount: subscription.pushCount,
lastPush: subscription.lastPush,
quota: subscription.quota,
};
},
destroy() {
this._subscription = null;
protocol.Actor.prototype.destroy.call(this);
},
});
exports.PushSubscriptionActor = PushSubscriptionActor;

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

@ -6,7 +6,8 @@
const { Ci } = require("chrome");
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
loader.lazyRequireGetter(this, "ServiceWorkerRegistrationActor", "devtools/server/actors/worker/service-worker", true);
loader.lazyRequireGetter(this, "ServiceWorkerRegistrationActor",
"devtools/server/actors/worker/service-worker-registration", true);
XPCOMUtils.defineLazyServiceGetter(
this, "swm",

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

@ -0,0 +1,209 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Ci } = require("chrome");
const ChromeUtils = require("ChromeUtils");
const Services = require("Services");
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
const protocol = require("devtools/shared/protocol");
const { serviceWorkerRegistrationSpec } =
require("devtools/shared/specs/worker/service-worker-registration");
const { PushSubscriptionActor } =
require("devtools/server/actors/worker/push-subscription");
const { ServiceWorkerActor } = require("devtools/server/actors/worker/service-worker");
XPCOMUtils.defineLazyServiceGetter(
this, "swm",
"@mozilla.org/serviceworkers/manager;1",
"nsIServiceWorkerManager"
);
XPCOMUtils.defineLazyServiceGetter(
this, "PushService",
"@mozilla.org/push/Service;1",
"nsIPushService"
);
// Lazily load the service-worker-process.js process script only once.
let _serviceWorkerProcessScriptLoaded = false;
const ServiceWorkerRegistrationActor =
protocol.ActorClassWithSpec(serviceWorkerRegistrationSpec, {
/**
* Create the ServiceWorkerRegistrationActor
* @param DebuggerServerConnection conn
* The server connection.
* @param ServiceWorkerRegistrationInfo registration
* The registration's information.
*/
initialize(conn, registration) {
protocol.Actor.prototype.initialize.call(this, conn);
this._conn = conn;
this._registration = registration;
this._pushSubscriptionActor = null;
this._registration.addListener(this);
this._createServiceWorkerActors();
Services.obs.addObserver(this, PushService.subscriptionModifiedTopic);
},
onChange() {
this._destroyServiceWorkerActors();
this._createServiceWorkerActors();
this.emit("registration-changed");
},
form(detail) {
if (detail === "actorid") {
return this.actorID;
}
const registration = this._registration;
const installingWorker = this._installingWorker.form();
const waitingWorker = this._waitingWorker.form();
const activeWorker = this._activeWorker.form();
const newestWorker = (activeWorker || waitingWorker || installingWorker);
const isE10s = Services.appinfo.browserTabsRemoteAutostart;
return {
actor: this.actorID,
scope: registration.scope,
url: registration.scriptSpec,
installingWorker,
waitingWorker,
activeWorker,
fetch: newestWorker && newestWorker.fetch,
// - In e10s: only active registrations are available.
// - In non-e10s: registrations always have at least one worker, if the worker is
// active, the registration is active.
active: isE10s ? true : !!activeWorker,
lastUpdateTime: registration.lastUpdateTime,
};
},
destroy() {
protocol.Actor.prototype.destroy.call(this);
Services.obs.removeObserver(this, PushService.subscriptionModifiedTopic);
this._registration.removeListener(this);
this._registration = null;
if (this._pushSubscriptionActor) {
this._pushSubscriptionActor.destroy();
}
this._pushSubscriptionActor = null;
this._destroyServiceWorkerActors();
this._installingWorker = null;
this._waitingWorker = null;
this._activeWorker = null;
},
/**
* Standard observer interface to listen to push messages and changes.
*/
observe(subject, topic, data) {
const scope = this._registration.scope;
if (data !== scope) {
// This event doesn't concern us, pretend nothing happened.
return;
}
switch (topic) {
case PushService.subscriptionModifiedTopic:
if (this._pushSubscriptionActor) {
this._pushSubscriptionActor.destroy();
this._pushSubscriptionActor = null;
}
this.emit("push-subscription-modified");
break;
}
},
start() {
if (!_serviceWorkerProcessScriptLoaded) {
Services.ppmm.loadProcessScript(
"resource://devtools/server/actors/worker/service-worker-process.js", true);
_serviceWorkerProcessScriptLoaded = true;
}
// XXX: Send the permissions down to the content process before starting
// the service worker within the content process. As we don't know what
// content process we're starting the service worker in (as we're using a
// broadcast channel to talk to it), we just broadcast the permissions to
// everyone as well.
//
// This call should be replaced with a proper implementation when
// ServiceWorker debugging is improved to support multiple content processes
// correctly.
Services.perms.broadcastPermissionsForPrincipalToAllContentProcesses(
this._registration.principal);
Services.ppmm.broadcastAsyncMessage("serviceWorkerRegistration:start", {
scope: this._registration.scope,
});
return { type: "started" };
},
unregister() {
const { principal, scope } = this._registration;
const unregisterCallback = {
unregisterSucceeded: function() {},
unregisterFailed: function() {
console.error("Failed to unregister the service worker for " + scope);
},
QueryInterface: ChromeUtils.generateQI(
[Ci.nsIServiceWorkerUnregisterCallback]),
};
swm.propagateUnregister(principal, unregisterCallback, scope);
return { type: "unregistered" };
},
getPushSubscription() {
const registration = this._registration;
let pushSubscriptionActor = this._pushSubscriptionActor;
if (pushSubscriptionActor) {
return Promise.resolve(pushSubscriptionActor);
}
return new Promise((resolve, reject) => {
PushService.getSubscription(
registration.scope,
registration.principal,
(result, subscription) => {
if (!subscription) {
resolve(null);
return;
}
pushSubscriptionActor = new PushSubscriptionActor(this._conn, subscription);
this._pushSubscriptionActor = pushSubscriptionActor;
resolve(pushSubscriptionActor);
}
);
});
},
_destroyServiceWorkerActors() {
this._installingWorker.destroy();
this._waitingWorker.destroy();
this._activeWorker.destroy();
},
_createServiceWorkerActors() {
const {installingWorker, waitingWorker, activeWorker} = this._registration;
this._installingWorker = new ServiceWorkerActor(this._conn, installingWorker);
this._waitingWorker = new ServiceWorkerActor(this._conn, waitingWorker);
this._activeWorker = new ServiceWorkerActor(this._conn, activeWorker);
// Add the ServiceWorker actors as children of this ServiceWorkerRegistration actor,
// assigning them valid actorIDs.
this.manage(this._installingWorker);
this.manage(this._waitingWorker);
this.manage(this._activeWorker);
},
});
exports.ServiceWorkerRegistrationActor = ServiceWorkerRegistrationActor;

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

@ -4,56 +4,8 @@
"use strict";
const { Ci } = require("chrome");
const ChromeUtils = require("ChromeUtils");
const Services = require("Services");
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
const protocol = require("devtools/shared/protocol");
const {
pushSubscriptionSpec,
serviceWorkerRegistrationSpec,
serviceWorkerSpec,
} = require("devtools/shared/specs/worker/service-worker");
loader.lazyRequireGetter(this, "ChromeUtils");
XPCOMUtils.defineLazyServiceGetter(
this, "swm",
"@mozilla.org/serviceworkers/manager;1",
"nsIServiceWorkerManager"
);
XPCOMUtils.defineLazyServiceGetter(
this, "PushService",
"@mozilla.org/push/Service;1",
"nsIPushService"
);
const PushSubscriptionActor = protocol.ActorClassWithSpec(pushSubscriptionSpec, {
initialize(conn, subscription) {
protocol.Actor.prototype.initialize.call(this, conn);
this._subscription = subscription;
},
form(detail) {
if (detail === "actorid") {
return this.actorID;
}
const subscription = this._subscription;
return {
actor: this.actorID,
endpoint: subscription.endpoint,
pushCount: subscription.pushCount,
lastPush: subscription.lastPush,
quota: subscription.quota,
};
},
destroy() {
this._subscription = null;
protocol.Actor.prototype.destroy.call(this);
},
});
const { serviceWorkerSpec } = require("devtools/shared/specs/worker/service-worker");
const ServiceWorkerActor = protocol.ActorClassWithSpec(serviceWorkerSpec, {
initialize(conn, worker) {
@ -80,183 +32,4 @@ const ServiceWorkerActor = protocol.ActorClassWithSpec(serviceWorkerSpec, {
},
});
// Lazily load the service-worker-process.js process script only once.
let _serviceWorkerProcessScriptLoaded = false;
const ServiceWorkerRegistrationActor =
protocol.ActorClassWithSpec(serviceWorkerRegistrationSpec, {
/**
* Create the ServiceWorkerRegistrationActor
* @param DebuggerServerConnection conn
* The server connection.
* @param ServiceWorkerRegistrationInfo registration
* The registration's information.
*/
initialize(conn, registration) {
protocol.Actor.prototype.initialize.call(this, conn);
this._conn = conn;
this._registration = registration;
this._pushSubscriptionActor = null;
this._registration.addListener(this);
this._createServiceWorkerActors();
Services.obs.addObserver(this, PushService.subscriptionModifiedTopic);
},
onChange() {
this._destroyServiceWorkerActors();
this._createServiceWorkerActors();
this.emit("registration-changed");
},
form(detail) {
if (detail === "actorid") {
return this.actorID;
}
const registration = this._registration;
const installingWorker = this._installingWorker.form();
const waitingWorker = this._waitingWorker.form();
const activeWorker = this._activeWorker.form();
const newestWorker = (activeWorker || waitingWorker || installingWorker);
const isE10s = Services.appinfo.browserTabsRemoteAutostart;
return {
actor: this.actorID,
scope: registration.scope,
url: registration.scriptSpec,
installingWorker,
waitingWorker,
activeWorker,
fetch: newestWorker && newestWorker.fetch,
// - In e10s: only active registrations are available.
// - In non-e10s: registrations always have at least one worker, if the worker is
// active, the registration is active.
active: isE10s ? true : !!activeWorker,
lastUpdateTime: registration.lastUpdateTime,
};
},
destroy() {
protocol.Actor.prototype.destroy.call(this);
Services.obs.removeObserver(this, PushService.subscriptionModifiedTopic);
this._registration.removeListener(this);
this._registration = null;
if (this._pushSubscriptionActor) {
this._pushSubscriptionActor.destroy();
}
this._pushSubscriptionActor = null;
this._destroyServiceWorkerActors();
this._installingWorker = null;
this._waitingWorker = null;
this._activeWorker = null;
},
/**
* Standard observer interface to listen to push messages and changes.
*/
observe(subject, topic, data) {
const scope = this._registration.scope;
if (data !== scope) {
// This event doesn't concern us, pretend nothing happened.
return;
}
switch (topic) {
case PushService.subscriptionModifiedTopic:
if (this._pushSubscriptionActor) {
this._pushSubscriptionActor.destroy();
this._pushSubscriptionActor = null;
}
this.emit("push-subscription-modified");
break;
}
},
start() {
if (!_serviceWorkerProcessScriptLoaded) {
Services.ppmm.loadProcessScript(
"resource://devtools/server/actors/worker/service-worker-process.js", true);
_serviceWorkerProcessScriptLoaded = true;
}
// XXX: Send the permissions down to the content process before starting
// the service worker within the content process. As we don't know what
// content process we're starting the service worker in (as we're using a
// broadcast channel to talk to it), we just broadcast the permissions to
// everyone as well.
//
// This call should be replaced with a proper implementation when
// ServiceWorker debugging is improved to support multiple content processes
// correctly.
Services.perms.broadcastPermissionsForPrincipalToAllContentProcesses(
this._registration.principal);
Services.ppmm.broadcastAsyncMessage("serviceWorkerRegistration:start", {
scope: this._registration.scope,
});
return { type: "started" };
},
unregister() {
const { principal, scope } = this._registration;
const unregisterCallback = {
unregisterSucceeded: function() {},
unregisterFailed: function() {
console.error("Failed to unregister the service worker for " + scope);
},
QueryInterface: ChromeUtils.generateQI(
[Ci.nsIServiceWorkerUnregisterCallback]),
};
swm.propagateUnregister(principal, unregisterCallback, scope);
return { type: "unregistered" };
},
getPushSubscription() {
const registration = this._registration;
let pushSubscriptionActor = this._pushSubscriptionActor;
if (pushSubscriptionActor) {
return Promise.resolve(pushSubscriptionActor);
}
return new Promise((resolve, reject) => {
PushService.getSubscription(
registration.scope,
registration.principal,
(result, subscription) => {
if (!subscription) {
resolve(null);
return;
}
pushSubscriptionActor = new PushSubscriptionActor(this._conn, subscription);
this._pushSubscriptionActor = pushSubscriptionActor;
resolve(pushSubscriptionActor);
}
);
});
},
_destroyServiceWorkerActors() {
this._installingWorker.destroy();
this._waitingWorker.destroy();
this._activeWorker.destroy();
},
_createServiceWorkerActors() {
const {installingWorker, waitingWorker, activeWorker} = this._registration;
this._installingWorker = new ServiceWorkerActor(this._conn, installingWorker);
this._waitingWorker = new ServiceWorkerActor(this._conn, waitingWorker);
this._activeWorker = new ServiceWorkerActor(this._conn, activeWorker);
// Add the ServiceWorker actors as children of this ServiceWorkerRegistration actor,
// assigning them valid actorIDs.
this.manage(this._installingWorker);
this.manage(this._waitingWorker);
this.manage(this._activeWorker);
},
});
exports.ServiceWorkerRegistrationActor = ServiceWorkerRegistrationActor;
exports.ServiceWorkerActor = ServiceWorkerActor;

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

@ -5,5 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'push-subscription.js',
'service-worker-registration.js',
'service-worker.js',
)

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

@ -0,0 +1,39 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { pushSubscriptionSpec } =
require("devtools/shared/specs/worker/push-subscription");
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
class PushSubscriptionFront extends FrontClassWithSpec(pushSubscriptionSpec) {
get endpoint() {
return this._form.endpoint;
}
get pushCount() {
return this._form.pushCount;
}
get lastPush() {
return this._form.lastPush;
}
get quota() {
return this._form.quota;
}
form(form, detail) {
if (detail === "actorid") {
this.actorID = form;
return;
}
this.actorID = form.actor;
this._form = form;
}
}
exports.PushSubscriptionFront = PushSubscriptionFront;
registerFront(PushSubscriptionFront);

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

@ -0,0 +1,68 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { serviceWorkerRegistrationSpec } =
require("devtools/shared/specs/worker/service-worker-registration");
const { FrontClassWithSpec, registerFront, types } = require("devtools/shared/protocol");
class ServiceWorkerRegistrationFront extends
FrontClassWithSpec(serviceWorkerRegistrationSpec) {
get active() {
return this._form.active;
}
get fetch() {
return this._form.fetch;
}
get lastUpdateTime() {
return this._form.lastUpdateTime;
}
get scope() {
return this._form.scope;
}
get type() {
return this._form.type;
}
get url() {
return this._form.url;
}
get activeWorker() {
return this._getServiceWorker("activeWorker");
}
get installingWorker() {
return this._getServiceWorker("installingWorker");
}
get waitingWorker() {
return this._getServiceWorker("waitingWorker");
}
_getServiceWorker(type) {
const workerForm = this._form[type];
if (!workerForm) {
return null;
}
return types.getType("serviceWorker").read(workerForm, this);
}
form(form, detail) {
if (detail === "actorid") {
this.actorID = form;
return;
}
this.actorID = form.actor;
this._form = form;
}
}
exports.ServiceWorkerRegistrationFront = ServiceWorkerRegistrationFront;
registerFront(ServiceWorkerRegistrationFront);

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

@ -3,101 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
pushSubscriptionSpec,
serviceWorkerRegistrationSpec,
serviceWorkerSpec,
} = require("devtools/shared/specs/worker/service-worker");
const { FrontClassWithSpec, registerFront, types } = require("devtools/shared/protocol");
class PushSubscriptionFront extends FrontClassWithSpec(pushSubscriptionSpec) {
get endpoint() {
return this._form.endpoint;
}
get pushCount() {
return this._form.pushCount;
}
get lastPush() {
return this._form.lastPush;
}
get quota() {
return this._form.quota;
}
form(form, detail) {
if (detail === "actorid") {
this.actorID = form;
return;
}
this.actorID = form.actor;
this._form = form;
}
}
exports.PushSubscriptionFront = PushSubscriptionFront;
registerFront(PushSubscriptionFront);
class ServiceWorkerRegistrationFront extends
FrontClassWithSpec(serviceWorkerRegistrationSpec) {
get active() {
return this._form.active;
}
get fetch() {
return this._form.fetch;
}
get lastUpdateTime() {
return this._form.lastUpdateTime;
}
get scope() {
return this._form.scope;
}
get type() {
return this._form.type;
}
get url() {
return this._form.url;
}
get activeWorker() {
return this._getServiceWorker("activeWorker");
}
get installingWorker() {
return this._getServiceWorker("installingWorker");
}
get waitingWorker() {
return this._getServiceWorker("waitingWorker");
}
_getServiceWorker(type) {
const workerForm = this._form[type];
if (!workerForm) {
return null;
}
return types.getType("serviceWorker").read(workerForm, this);
}
form(form, detail) {
if (detail === "actorid") {
this.actorID = form;
return;
}
this.actorID = form.actor;
this._form = form;
}
}
exports.ServiceWorkerRegistrationFront = ServiceWorkerRegistrationFront;
registerFront(ServiceWorkerRegistrationFront);
const { serviceWorkerSpec } = require("devtools/shared/specs/worker/service-worker");
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
class ServiceWorkerFront extends FrontClassWithSpec(serviceWorkerSpec) {
get fetch() {
@ -122,5 +29,6 @@ class ServiceWorkerFront extends FrontClassWithSpec(serviceWorkerSpec) {
this._form = form;
}
}
exports.ServiceWorkerFront = ServiceWorkerFront;
registerFront(ServiceWorkerFront);

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

@ -290,7 +290,17 @@ const Types = exports.__TypesForTests = [
front: "devtools/shared/fronts/webgl",
},
{
types: ["pushSubscription", "serviceWorkerRegistration", "serviceWorker"],
types: ["pushSubscription"],
spec: "devtools/shared/specs/worker/push-subscription",
front: "devtools/shared/fronts/worker/push-subscription",
},
{
types: ["serviceWorkerRegistration"],
spec: "devtools/shared/specs/worker/service-worker-registration",
front: "devtools/shared/fronts/worker/service-worker-registration",
},
{
types: ["serviceWorker"],
spec: "devtools/shared/specs/worker/service-worker",
front: "devtools/shared/fronts/worker/service-worker",
},

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

@ -5,5 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'push-subscription.js',
'service-worker-registration.js',
'service-worker.js',
)

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

@ -0,0 +1,12 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { generateActorSpec } = require("devtools/shared/protocol");
const pushSubscriptionSpec = generateActorSpec({
typeName: "pushSubscription",
});
exports.pushSubscriptionSpec = pushSubscriptionSpec;

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

@ -0,0 +1,37 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { RetVal, generateActorSpec } = require("devtools/shared/protocol");
const serviceWorkerRegistrationSpec = generateActorSpec({
typeName: "serviceWorkerRegistration",
events: {
"push-subscription-modified": {
type: "push-subscription-modified",
},
"registration-changed": {
type: "registration-changed",
},
},
methods: {
start: {
request: {},
},
unregister: {
request: {},
},
getPushSubscription: {
request: {},
response: {
subscription: RetVal("nullable:pushSubscription"),
},
},
},
});
exports.serviceWorkerRegistrationSpec = serviceWorkerRegistrationSpec;

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

@ -3,43 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {RetVal, generateActorSpec} = require("devtools/shared/protocol");
const pushSubscriptionSpec = generateActorSpec({
typeName: "pushSubscription",
});
exports.pushSubscriptionSpec = pushSubscriptionSpec;
const serviceWorkerRegistrationSpec = generateActorSpec({
typeName: "serviceWorkerRegistration",
events: {
"push-subscription-modified": {
type: "push-subscription-modified",
},
"registration-changed": {
type: "registration-changed",
},
},
methods: {
start: {
request: {},
},
unregister: {
request: {},
},
getPushSubscription: {
request: {},
response: {
subscription: RetVal("nullable:pushSubscription"),
},
},
},
});
exports.serviceWorkerRegistrationSpec = serviceWorkerRegistrationSpec;
const { generateActorSpec } = require("devtools/shared/protocol");
const serviceWorkerSpec = generateActorSpec({
typeName: "serviceWorker",