Bug 1563607 Part 2 - Attach to service workers in debugger when pref is enabled, r=jdescottes,jlast.
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 06 Nov 2019 20:20:36 +0000
changeset 500947 c48a3caec5154d92f6c1478714850a62d8a6a0b1
parent 500946 0e88cb72397fa245f67084efc779a9eeb1eca32f
child 500948 237b6839502b53bff53ed21a29522e3d6c9b2c04
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);