Bug 1510654 - Extract service worker actors to dedicated files;r=ochameau,ladybenko
authorJulian Descottes <jdescottes@mozilla.com>
Thu, 10 Jan 2019 17:28:27 +0000
changeset 510411 08b043c4ef1b2a1a90b213ab407bd0f2fc497259
parent 510410 247e6818b26264099735ce8a0c972940d15940c9
child 510412 ab1bfb032425503fe0b2a4b9abd888e40882d2cc
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau, ladybenko
bugs1510654
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1510654 - Extract service worker actors to dedicated files;r=ochameau,ladybenko Depends on D15377 Differential Revision: https://phabricator.services.mozilla.com/D15378
devtools/server/actors/worker/moz.build
devtools/server/actors/worker/push-subscription.js
devtools/server/actors/worker/service-worker-registration-list.js
devtools/server/actors/worker/service-worker-registration.js
devtools/server/actors/worker/service-worker.js
devtools/shared/fronts/worker/moz.build
devtools/shared/fronts/worker/push-subscription.js
devtools/shared/fronts/worker/service-worker-registration.js
devtools/shared/fronts/worker/service-worker.js
devtools/shared/specs/index.js
devtools/shared/specs/worker/moz.build
devtools/shared/specs/worker/push-subscription.js
devtools/shared/specs/worker/service-worker-registration.js
devtools/shared/specs/worker/service-worker.js
--- a/devtools/server/actors/worker/moz.build
+++ b/devtools/server/actors/worker/moz.build
@@ -1,12 +1,14 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 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',
 )
copy from devtools/server/actors/worker/service-worker.js
copy to devtools/server/actors/worker/push-subscription.js
--- a/devtools/server/actors/worker/service-worker.js
+++ b/devtools/server/actors/worker/push-subscription.js
@@ -1,38 +1,17 @@
 /* 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 {
-  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 { 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) {
@@ -49,214 +28,9 @@ const PushSubscriptionActor = protocol.A
     };
   },
 
   destroy() {
     this._subscription = null;
     protocol.Actor.prototype.destroy.call(this);
   },
 });
-
-const ServiceWorkerActor = protocol.ActorClassWithSpec(serviceWorkerSpec, {
-  initialize(conn, worker) {
-    protocol.Actor.prototype.initialize.call(this, conn);
-    this._worker = worker;
-  },
-
-  form() {
-    if (!this._worker) {
-      return null;
-    }
-
-    return {
-      actor: this.actorID,
-      url: this._worker.scriptSpec,
-      state: this._worker.state,
-      fetch: this._worker.handlesFetchEvents,
-    };
-  },
-
-  destroy() {
-    protocol.Actor.prototype.destroy.call(this);
-    this._worker = null;
-  },
-});
-
-// 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.PushSubscriptionActor = PushSubscriptionActor;
--- a/devtools/server/actors/worker/service-worker-registration-list.js
+++ b/devtools/server/actors/worker/service-worker-registration-list.js
@@ -1,17 +1,18 @@
 /* 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 { 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",
   "@mozilla.org/serviceworkers/manager;1",
   "nsIServiceWorkerManager"
 );
 
 function ServiceWorkerRegistrationActorList(conn) {
copy from devtools/server/actors/worker/service-worker.js
copy to devtools/server/actors/worker/service-worker-registration.js
--- a/devtools/server/actors/worker/service-worker.js
+++ b/devtools/server/actors/worker/service-worker-registration.js
@@ -4,87 +4,34 @@
 
 "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");
+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"
 );
 
-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 ServiceWorkerActor = protocol.ActorClassWithSpec(serviceWorkerSpec, {
-  initialize(conn, worker) {
-    protocol.Actor.prototype.initialize.call(this, conn);
-    this._worker = worker;
-  },
-
-  form() {
-    if (!this._worker) {
-      return null;
-    }
-
-    return {
-      actor: this.actorID,
-      url: this._worker.scriptSpec,
-      state: this._worker.state,
-      fetch: this._worker.handlesFetchEvents,
-    };
-  },
-
-  destroy() {
-    protocol.Actor.prototype.destroy.call(this);
-    this._worker = null;
-  },
-});
-
 // 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
--- a/devtools/server/actors/worker/service-worker.js
+++ b/devtools/server/actors/worker/service-worker.js
@@ -1,64 +1,16 @@
 /* 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 {
-  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) {
     protocol.Actor.prototype.initialize.call(this, conn);
     this._worker = worker;
   },
 
   form() {
@@ -75,188 +27,9 @@ const ServiceWorkerActor = protocol.Acto
   },
 
   destroy() {
     protocol.Actor.prototype.destroy.call(this);
     this._worker = null;
   },
 });
 
-// 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;
--- a/devtools/shared/fronts/worker/moz.build
+++ b/devtools/shared/fronts/worker/moz.build
@@ -1,9 +1,11 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
+    'push-subscription.js',
+    'service-worker-registration.js',
     'service-worker.js',
 )
copy from devtools/shared/fronts/worker/service-worker.js
copy to devtools/shared/fronts/worker/push-subscription.js
--- a/devtools/shared/fronts/worker/service-worker.js
+++ b/devtools/shared/fronts/worker/push-subscription.js
@@ -1,19 +1,16 @@
 /* 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,
-  serviceWorkerRegistrationSpec,
-  serviceWorkerSpec,
-} = require("devtools/shared/specs/worker/service-worker");
-const { FrontClassWithSpec, registerFront, types } = require("devtools/shared/protocol");
+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;
@@ -32,95 +29,11 @@ class PushSubscriptionFront extends Fron
       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);
-
-class ServiceWorkerFront extends FrontClassWithSpec(serviceWorkerSpec) {
-  get fetch() {
-    return this._form.fetch;
-  }
-
-  get url() {
-    return this._form.url;
-  }
-
-  get state() {
-    return this._form.state;
-  }
-
-  form(form, detail) {
-    if (detail === "actorid") {
-      this.actorID = form;
-      return;
-    }
-
-    this.actorID = form.actor;
-    this._form = form;
-  }
-}
-exports.ServiceWorkerFront = ServiceWorkerFront;
-registerFront(ServiceWorkerFront);
copy from devtools/shared/fronts/worker/service-worker.js
copy to devtools/shared/fronts/worker/service-worker-registration.js
--- a/devtools/shared/fronts/worker/service-worker.js
+++ b/devtools/shared/fronts/worker/service-worker-registration.js
@@ -1,50 +1,17 @@
 /* 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,
-  serviceWorkerRegistrationSpec,
-  serviceWorkerSpec,
-} = require("devtools/shared/specs/worker/service-worker");
+const { serviceWorkerRegistrationSpec } =
+  require("devtools/shared/specs/worker/service-worker-registration");
 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;
@@ -91,36 +58,11 @@ class ServiceWorkerRegistrationFront ext
       this.actorID = form;
       return;
     }
 
     this.actorID = form.actor;
     this._form = form;
   }
 }
+
 exports.ServiceWorkerRegistrationFront = ServiceWorkerRegistrationFront;
 registerFront(ServiceWorkerRegistrationFront);
-
-class ServiceWorkerFront extends FrontClassWithSpec(serviceWorkerSpec) {
-  get fetch() {
-    return this._form.fetch;
-  }
-
-  get url() {
-    return this._form.url;
-  }
-
-  get state() {
-    return this._form.state;
-  }
-
-  form(form, detail) {
-    if (detail === "actorid") {
-      this.actorID = form;
-      return;
-    }
-
-    this.actorID = form.actor;
-    this._form = form;
-  }
-}
-exports.ServiceWorkerFront = ServiceWorkerFront;
-registerFront(ServiceWorkerFront);
--- a/devtools/shared/fronts/worker/service-worker.js
+++ b/devtools/shared/fronts/worker/service-worker.js
@@ -1,108 +1,15 @@
 /* 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,
-  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() {
     return this._form.fetch;
   }
 
   get url() {
     return this._form.url;
@@ -117,10 +24,11 @@ class ServiceWorkerFront extends FrontCl
       this.actorID = form;
       return;
     }
 
     this.actorID = form.actor;
     this._form = form;
   }
 }
+
 exports.ServiceWorkerFront = ServiceWorkerFront;
 registerFront(ServiceWorkerFront);
--- a/devtools/shared/specs/index.js
+++ b/devtools/shared/specs/index.js
@@ -285,17 +285,27 @@ const Types = exports.__TypesForTests = 
     front: null,
   },
   {
     types: ["gl-shader", "gl-program", "webgl"],
     spec: "devtools/shared/specs/webgl",
     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",
   },
 ];
 
 const lazySpecs = new Map();
 const lazyFronts = new Map();
 
--- a/devtools/shared/specs/worker/moz.build
+++ b/devtools/shared/specs/worker/moz.build
@@ -1,9 +1,11 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
+    'push-subscription.js',
+    'service-worker-registration.js',
     'service-worker.js',
 )
copy from devtools/shared/specs/worker/service-worker.js
copy to devtools/shared/specs/worker/push-subscription.js
--- a/devtools/shared/specs/worker/service-worker.js
+++ b/devtools/shared/specs/worker/push-subscription.js
@@ -1,49 +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 {RetVal, generateActorSpec} = require("devtools/shared/protocol");
+const { 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 serviceWorkerSpec = generateActorSpec({
-  typeName: "serviceWorker",
-});
-
-exports.serviceWorkerSpec = serviceWorkerSpec;
-
copy from devtools/shared/specs/worker/service-worker.js
copy to devtools/shared/specs/worker/service-worker-registration.js
--- a/devtools/shared/specs/worker/service-worker.js
+++ b/devtools/shared/specs/worker/service-worker-registration.js
@@ -1,20 +1,14 @@
 /* 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 pushSubscriptionSpec = generateActorSpec({
-  typeName: "pushSubscription",
-});
-
-exports.pushSubscriptionSpec = pushSubscriptionSpec;
+const { RetVal, generateActorSpec } = require("devtools/shared/protocol");
 
 const serviceWorkerRegistrationSpec = generateActorSpec({
   typeName: "serviceWorkerRegistration",
 
   events: {
     "push-subscription-modified": {
       type: "push-subscription-modified",
     },
@@ -36,14 +30,8 @@ const serviceWorkerRegistrationSpec = ge
         subscription: RetVal("nullable:pushSubscription"),
       },
     },
   },
 });
 
 exports.serviceWorkerRegistrationSpec = serviceWorkerRegistrationSpec;
 
-const serviceWorkerSpec = generateActorSpec({
-  typeName: "serviceWorker",
-});
-
-exports.serviceWorkerSpec = serviceWorkerSpec;
-
--- a/devtools/shared/specs/worker/service-worker.js
+++ b/devtools/shared/specs/worker/service-worker.js
@@ -1,49 +1,13 @@
 /* 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 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",
 });
 
 exports.serviceWorkerSpec = serviceWorkerSpec;