summaryrefslogtreecommitdiffstats
path: root/devtools/client/debugger/test/mochitest/browser_dbg-windowless-service-workers.js
blob: dd222489b25c6b5b26dc556fcb9f1f9a71b907b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/* 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/>. */

// Test that we can detect a new service worker and hit breakpoints that we've
// set in it.

"use strict";

add_task(async function () {
  info("Subtest #1");
  await pushPref("devtools.debugger.features.windowless-service-workers", true);
  await pushPref("devtools.debugger.threads-visible", true);
  await pushPref("dom.serviceWorkers.enabled", true);
  await pushPref("dom.serviceWorkers.testing.enabled", true);
  const dbg = await initDebugger("doc-service-workers.html");

  invokeInTab("registerWorker");
  await waitForSource(dbg, "service-worker.sjs");
  const workerSource = findSource(dbg, "service-worker.sjs");

  await addBreakpoint(dbg, "service-worker.sjs", 13);

  invokeInTab("fetchFromWorker");

  await waitForPaused(dbg);
  assertPausedAtSourceAndLine(dbg, workerSource.id, 13);
  // Leave the breakpoint and worker in place for the next subtest.
  await resume(dbg);
  await waitForRequestsToSettle(dbg);
  await removeTab(gBrowser.selectedTab);
});

// Test that breakpoints can be immediately hit in service workers when reloading.
add_task(async function () {
  info("Subtest #2");

  const toolbox = await openNewTabAndToolbox(
    `${EXAMPLE_URL}doc-service-workers.html`,
    "jsdebugger"
  );
  const dbg = createDebuggerContext(toolbox);

  await checkWorkerThreads(dbg, 1);

  // The test page will immediately fetch from the service worker if registered.
  const onReloaded = reload(dbg);

  await waitForSource(dbg, "service-worker.sjs");
  const workerSource = findSource(dbg, "service-worker.sjs");

  await waitForPaused(dbg);
  assertPausedAtSourceAndLine(dbg, workerSource.id, 13);
  await checkWorkerThreads(dbg, 1);

  await resume(dbg);
  await dbg.actions.removeAllBreakpoints(getContext(dbg));

  info("Wait for reload to complete after resume");
  await onReloaded;

  invokeInTab("unregisterWorker");

  await checkWorkerThreads(dbg, 0);
  await waitForRequestsToSettle(dbg);
  await removeTab(gBrowser.selectedTab);
});

// Test having a waiting and active service worker for the same registration.
add_task(async function () {
  info("Subtest #3");

  const toolbox = await openNewTabAndToolbox(
    `${EXAMPLE_URL}doc-service-workers.html`,
    "jsdebugger"
  );
  const dbg = createDebuggerContext(toolbox);

  invokeInTab("registerWorker");
  await checkWorkerThreads(dbg, 1);
  await checkWorkerStatus(dbg, "activated");

  const firstTab = gBrowser.selectedTab;

  await addTab(`${EXAMPLE_URL}service-worker.sjs?setStatus=newServiceWorker`);
  await removeTab(gBrowser.selectedTab);

  const secondTab = await addTab(`${EXAMPLE_URL}doc-service-workers.html`);

  await gBrowser.selectTabAtIndex(gBrowser.tabs.indexOf(firstTab));
  await checkWorkerThreads(dbg, 2);

  const sources = await waitFor(() => {
    const list = dbg.selectors
      .getSourceList()
      .filter(s => s.url.includes("service-worker.sjs"));
    return list.length == 1 ? list : null;
  });
  ok(sources.length, "Found one sources for service worker");

  // Add a breakpoint for the next subtest.
  await addBreakpoint(dbg, "service-worker.sjs", 2);

  invokeInTab("unregisterWorker");

  await checkWorkerThreads(dbg, 0);
  await waitForRequestsToSettle(dbg);
  await removeTab(firstTab);
  await removeTab(secondTab);

  // Reset the SJS in case we will be repeating the test.
  await addTab(`${EXAMPLE_URL}service-worker.sjs?setStatus=`);
  await removeTab(gBrowser.selectedTab);
});

// Test setting breakpoints while the service worker is starting up.
add_task(async function () {
  info("Subtest #4");
  if (Services.appinfo.fissionAutostart) {
    // Disabled when serviceworker isolation is used due to bug 1749341
    return;
  }

  const toolbox = await openNewTabAndToolbox(
    `${EXAMPLE_URL}doc-service-workers.html`,
    "jsdebugger"
  );
  const dbg = createDebuggerContext(toolbox);

  invokeInTab("registerWorker");
  await checkWorkerThreads(dbg, 1);

  await waitForSource(dbg, "service-worker.sjs");
  const workerSource = findSource(dbg, "service-worker.sjs");

  await waitForBreakpointCount(dbg, 1);
  await waitForPaused(dbg);
  assertPausedAtSourceAndLine(dbg, workerSource.id, 2);
  await checkWorkerStatus(dbg, "parsed");

  await addBreakpoint(dbg, "service-worker.sjs", 19);
  await resume(dbg);
  await waitForPaused(dbg);
  assertPausedAtSourceAndLine(dbg, workerSource.id, 19);
  await checkWorkerStatus(dbg, "installing");

  await addBreakpoint(dbg, "service-worker.sjs", 5);
  await resume(dbg);
  await waitForPaused(dbg);
  assertPausedAtSourceAndLine(dbg, workerSource.id, 5);
  await checkWorkerStatus(dbg, "activating");

  await resume(dbg);
  invokeInTab("unregisterWorker");

  await checkWorkerThreads(dbg, 0);
  await waitForRequestsToSettle(dbg);
  await removeTab(gBrowser.selectedTab);
});

async function checkWorkerThreads(dbg, count) {
  await waitUntil(() => dbg.selectors.getThreads().length == count);
  ok(true, `Have ${count} threads`);
}

async function checkWorkerStatus(dbg, status) {
  /* TODO: Re-Add support for showing service worker status (Bug 1641099)
  await waitUntil(() => {
    const threads = dbg.selectors.getThreads();
    return threads.some(t => t.serviceWorkerStatus == status);
  });
  ok(true, `Have thread with status ${status}`);
  */
}