1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
5 // Test that we can detect a new service worker and hit breakpoints that we've
10 add_task(async function () {
12 await pushPref("devtools.debugger.features.windowless-service-workers", true);
13 await pushPref("devtools.debugger.threads-visible", true);
14 await pushPref("dom.serviceWorkers.enabled", true);
15 await pushPref("dom.serviceWorkers.testing.enabled", true);
16 const dbg = await initDebugger("doc-service-workers.html");
18 invokeInTab("registerWorker");
19 await waitForSource(dbg, "service-worker.sjs");
20 const workerSource = findSource(dbg, "service-worker.sjs");
22 await addBreakpoint(dbg, "service-worker.sjs", 13);
24 invokeInTab("fetchFromWorker");
26 await waitForPaused(dbg);
27 assertPausedAtSourceAndLine(dbg, workerSource.id, 13);
28 // Leave the breakpoint and worker in place for the next subtest.
30 await waitForRequestsToSettle(dbg);
31 await removeTab(gBrowser.selectedTab);
34 // Test that breakpoints can be immediately hit in service workers when reloading.
35 add_task(async function () {
38 const toolbox = await openNewTabAndToolbox(
39 `${EXAMPLE_URL}doc-service-workers.html`,
42 const dbg = createDebuggerContext(toolbox);
44 await checkWorkerThreads(dbg, 1);
46 // The test page will immediately fetch from the service worker if registered.
47 const onReloaded = reload(dbg);
49 await waitForSource(dbg, "service-worker.sjs");
50 const workerSource = findSource(dbg, "service-worker.sjs");
52 await waitForPaused(dbg);
53 assertPausedAtSourceAndLine(dbg, workerSource.id, 13);
54 await checkWorkerThreads(dbg, 1);
57 await dbg.actions.removeAllBreakpoints();
59 info("Wait for reload to complete after resume");
62 invokeInTab("unregisterWorker");
64 await checkWorkerThreads(dbg, 0);
65 await waitForRequestsToSettle(dbg);
66 await removeTab(gBrowser.selectedTab);
69 // Test having a waiting and active service worker for the same registration.
70 add_task(async function () {
73 const toolbox = await openNewTabAndToolbox(
74 `${EXAMPLE_URL}doc-service-workers.html`,
77 const dbg = createDebuggerContext(toolbox);
79 invokeInTab("registerWorker");
80 await checkWorkerThreads(dbg, 1);
81 await checkWorkerStatus(dbg, "activated");
83 const firstTab = gBrowser.selectedTab;
85 await addTab(`${EXAMPLE_URL}service-worker.sjs?setStatus=newServiceWorker`);
86 await removeTab(gBrowser.selectedTab);
88 const secondTab = await addTab(`${EXAMPLE_URL}doc-service-workers.html`);
90 await gBrowser.selectTabAtIndex(gBrowser.tabs.indexOf(firstTab));
91 await checkWorkerThreads(dbg, 2);
93 const sources = await waitFor(() => {
94 const list = dbg.selectors
96 .filter(s => s.url.includes("service-worker.sjs"));
97 return list.length == 1 ? list : null;
99 ok(sources.length, "Found one sources for service worker");
101 // Add a breakpoint for the next subtest.
102 await addBreakpoint(dbg, "service-worker.sjs", 2);
104 invokeInTab("unregisterWorker");
106 await checkWorkerThreads(dbg, 0);
107 await waitForRequestsToSettle(dbg);
108 await removeTab(firstTab);
109 await removeTab(secondTab);
111 // Reset the SJS in case we will be repeating the test.
112 await addTab(`${EXAMPLE_URL}service-worker.sjs?setStatus=`);
113 await removeTab(gBrowser.selectedTab);
116 // Test setting breakpoints while the service worker is starting up.
117 add_task(async function () {
119 if (Services.appinfo.fissionAutostart) {
120 // Disabled when serviceworker isolation is used due to bug 1749341
124 const toolbox = await openNewTabAndToolbox(
125 `${EXAMPLE_URL}doc-service-workers.html`,
128 const dbg = createDebuggerContext(toolbox);
130 invokeInTab("registerWorker");
131 await checkWorkerThreads(dbg, 1);
133 await waitForSource(dbg, "service-worker.sjs");
134 const workerSource = findSource(dbg, "service-worker.sjs");
136 await waitForBreakpointCount(dbg, 1);
137 await waitForPaused(dbg);
138 assertPausedAtSourceAndLine(dbg, workerSource.id, 2);
139 await checkWorkerStatus(dbg, "parsed");
141 await addBreakpoint(dbg, "service-worker.sjs", 19);
143 await waitForPaused(dbg);
144 assertPausedAtSourceAndLine(dbg, workerSource.id, 19);
145 await checkWorkerStatus(dbg, "installing");
147 await addBreakpoint(dbg, "service-worker.sjs", 5);
149 await waitForPaused(dbg);
150 assertPausedAtSourceAndLine(dbg, workerSource.id, 5);
151 await checkWorkerStatus(dbg, "activating");
154 invokeInTab("unregisterWorker");
156 await checkWorkerThreads(dbg, 0);
157 await waitForRequestsToSettle(dbg);
158 await removeTab(gBrowser.selectedTab);
161 async function checkWorkerThreads(dbg, count) {
162 await waitUntil(() => dbg.selectors.getThreads().length == count);
163 ok(true, `Have ${count} threads`);
166 async function checkWorkerStatus(dbg, status) {
167 /* TODO: Re-Add support for showing service worker status (Bug 1641099)
168 await waitUntil(() => {
169 const threads = dbg.selectors.getThreads();
170 return threads.some(t => t.serviceWorkerStatus == status);
172 ok(true, `Have thread with status ${status}`);