Bug 1563607 Part 2 - Attach to service workers in debugger when pref is enabled, r=jdescottes,jlast.
☠☠ backed out by f690fa2d0e1f ☠ ☠
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 06 Nov 2019 20:20:36 +0000
changeset 500937 6d02ecfce856b46a71d1c0a2050f57c7736c81f8
parent 500936 33e9b3eecd98dd808a50a21204cff4f954333cad
child 500938 ee2bb2d156595d2c03dbd478922f56a538935e6f
push id114166
push userapavel@mozilla.com
push dateThu, 07 Nov 2019 10:04:01 +0000
treeherdermozilla-inbound@d271c572a9bc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes, jlast
bugs1563607
milestone72.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 1563607 Part 2 - Attach to service workers in debugger when pref is enabled, r=jdescottes,jlast. Depends on D47541 Differential Revision: https://phabricator.services.mozilla.com/D47542
devtools/client/debugger/src/client/firefox/events.js
devtools/client/debugger/src/client/firefox/targets.js
devtools/client/debugger/src/client/firefox/types.js
devtools/client/debugger/src/utils/prefs.js
devtools/client/debugger/src/utils/url.js
devtools/client/preferences/debugger.js
--- a/devtools/client/debugger/src/client/firefox/events.js
+++ b/devtools/client/debugger/src/client/firefox/events.js
@@ -11,16 +11,22 @@ import type {
   Actions,
   Target,
   DebuggerClient,
 } from "./types";
 
 import { createPause, prepareSourcePayload } from "./create";
 import sourceQueue from "../../utils/source-queue";
 import { recordEvent } from "../../utils/telemetry";
+import { features } from "../../utils/prefs";
+
+const {
+  WorkersListener,
+  // $FlowIgnore
+} = require("devtools/client/shared/workers-listener.js");
 
 const CALL_STACK_PAGE_SIZE = 1000;
 
 type Dependencies = {
   threadFront: ThreadFront,
   tabTarget: Target,
   actions: Actions,
   debuggerClient: DebuggerClient,
@@ -40,16 +46,23 @@ function setupEvents(dependencies: Depen
   actions = dependencies.actions;
   sourceQueue.initialize(actions);
 
   addThreadEventListeners(threadFront);
   tabTarget.on("workerListChanged", () => threadListChanged("worker"));
   debuggerClient.mainRoot.on("processListChanged", () =>
     threadListChanged("contentProcess")
   );
+
+  // If we are attaching to service workers we need to listen to worker changes
+  // everywhere in the browser.
+  if (features.windowlessServiceWorkers) {
+    const workersListener = new WorkersListener(debuggerClient.mainRoot);
+    workersListener.addListener(() => threadListChanged("worker"));
+  }
 }
 
 async function paused(threadFront: ThreadFront, packet: PausedPacket) {
   // If paused by an explicit interrupt, which are generated by the
   // slow script dialog and internal events such as setting
   // breakpoints, ignore the event.
   const { why } = packet;
   if (why.type === "interrupted" && !packet.why.onNext) {
--- a/devtools/client/debugger/src/client/firefox/targets.js
+++ b/devtools/client/debugger/src/client/firefox/targets.js
@@ -1,16 +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/>. */
 
 // @flow
 
 import { addThreadEventListeners } from "./events";
-import { prefs } from "../../utils/prefs";
+import { prefs, features } from "../../utils/prefs";
+import { sameOrigin } from "../../utils/url";
 import type { DebuggerClient, Target } from "./types";
 import type { ThreadType } from "../../types";
 
 // $FlowIgnore
 const { defaultThreadOptions } = require("devtools/client/shared/thread-utils");
 
 type Args = {
   currentTarget: Target,
@@ -59,22 +60,35 @@ async function attachTargets(type, targe
     } catch (e) {
       // If any of the workers have terminated since the list command initiated
       // then we will get errors. Ignore these.
     }
   }
 }
 
 export async function updateWorkerTargets(type: ThreadType, args: Args) {
-  const { currentTarget } = args;
+  const { currentTarget, debuggerClient } = args;
   if (!currentTarget.isBrowsingContext || currentTarget.isContentProcess) {
     return;
   }
 
   const { workers } = await currentTarget.listWorkers();
+
+  if (features.windowlessServiceWorkers && currentTarget.url) {
+    const { service } = await debuggerClient.mainRoot.listAllWorkers();
+    for (const { active, id, url } of service) {
+      // Attach to any service workers that are same-origin with our target.
+      // For now, ignore service workers associated with cross-origin iframes.
+      if (active && sameOrigin(url, currentTarget.url)) {
+        const workerTarget = await debuggerClient.mainRoot.getWorker(id);
+        workers.push(workerTarget);
+      }
+    }
+  }
+
   await attachTargets(type, workers, args);
 }
 
 export async function updateProcessTargets(type: ThreadType, args: Args) {
   const { currentTarget, debuggerClient } = args;
   if (!prefs.fission || !currentTarget.chrome || currentTarget.isAddon) {
     return;
   }
--- a/devtools/client/debugger/src/client/firefox/types.js
+++ b/devtools/client/debugger/src/client/firefox/types.js
@@ -181,16 +181,17 @@ export type TabPayload = {
  * @static
  */
 export type Actions = {
   paused: Pause => void,
   resumed: ActorId => void,
   newQueuedSources: (QueuedSourceData[]) => void,
   fetchEventListeners: () => void,
   updateThreads: typeof actions.updateThreads,
+  ensureHasThread: typeof actions.ensureHasThread,
   setFramePositions: typeof actions.setFramePositions,
 };
 
 type ConsoleClient = {
   evaluateJS: (
     script: Script,
     func: Function,
     params?: { frameActor: ?FrameId }
@@ -251,16 +252,18 @@ export type DebuggerClient = {
   _activeRequests: {
     get: any => any,
     delete: any => void,
   },
   mainRoot: {
     traits: any,
     getFront: string => Promise<*>,
     listProcesses: () => Promise<{ processes: ProcessDescriptor }>,
+    listAllWorkers: () => Promise<*>,
+    getWorker: any => Promise<*>,
     on: (string, Function) => void,
   },
   connect: () => Promise<*>,
   request: (packet: Object) => Promise<*>,
   attachConsole: (actor: String, listeners: Array<*>) => Promise<*>,
   createObjectFront: (grip: Grip) => ObjectFront,
   release: (actor: String) => {},
   getFrontByID: (actor: String) => { release: () => Promise<*> },
--- a/devtools/client/debugger/src/utils/prefs.js
+++ b/devtools/client/debugger/src/utils/prefs.js
@@ -138,16 +138,17 @@ export const features = new PrefsHelper(
   xhrBreakpoints: ["Bool", "xhr-breakpoints"],
   originalBlackbox: ["Bool", "original-blackbox"],
   eventListenersBreakpoints: ["Bool", "event-listeners-breakpoints"],
   domMutationBreakpoints: ["Bool", "dom-mutation-breakpoints"],
   logPoints: ["Bool", "log-points"],
   showOverlay: ["Bool", "overlay"],
   inlinePreview: ["Bool", "inline-preview"],
   watchpoints: ["Bool", "watchpoints"],
+  windowlessServiceWorkers: ["Bool", "windowless-service-workers"],
 });
 
 export const asyncStore = asyncStoreHelper("debugger", {
   pendingBreakpoints: ["pending-breakpoints", {}],
   tabs: ["tabs", []],
   xhrBreakpoints: ["xhr-breakpoints", []],
   eventListenerBreakpoints: ["event-listener-breakpoints", undefined],
 });
--- a/devtools/client/debugger/src/utils/url.js
+++ b/devtools/client/debugger/src/utils/url.js
@@ -32,8 +32,12 @@ export const parse = memoize(function pa
     // If we're given simply a filename...
     if (url) {
       return { ...defaultUrl, path: url, pathname: url };
     }
 
     return defaultUrl;
   }
 });
+
+export function sameOrigin(firstUrl: string, secondUrl: string) {
+  return parse(firstUrl).origin == parse(secondUrl).origin;
+}
--- a/devtools/client/preferences/debugger.js
+++ b/devtools/client/preferences/debugger.js
@@ -80,8 +80,9 @@ pref("devtools.debugger.features.autocom
 pref("devtools.debugger.features.map-expression-bindings", true);
 pref("devtools.debugger.features.xhr-breakpoints", true);
 pref("devtools.debugger.features.original-blackbox", true);
 pref("devtools.debugger.features.event-listeners-breakpoints", true);
 pref("devtools.debugger.features.dom-mutation-breakpoints", true);
 pref("devtools.debugger.features.log-points", true);
 pref("devtools.debugger.features.overlay", true);
 pref("devtools.debugger.features.inline-preview", true);
+pref("devtools.debugger.features.windowless-service-workers", false);