Bug 1596939 Part 3 - Pause new service workers for the target's origin, r=jlast.

Depends on D54293

Differential Revision: https://phabricator.services.mozilla.com/D54298

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Brian Hackett 2019-12-07 21:05:14 +00:00
Родитель ad3914884b
Коммит 44cd7a73e5
5 изменённых файлов: 105 добавлений и 33 удалений

Просмотреть файл

@ -15,6 +15,14 @@ const EMPTY_URL = (URL_ROOT + "resources/service-workers/empty.html").replace(
"test2.example.com"
);
// FIXME bug 1575427 this rejection is very common.
const { PromiseTestUtils } = ChromeUtils.import(
"resource://testing-common/PromiseTestUtils.jsm"
);
PromiseTestUtils.whitelistRejectionsGlobally(
/this._frontCreationListeners is null/
);
add_task(async function() {
await enableApplicationPanel();

Просмотреть файл

@ -50,14 +50,12 @@ function setupEvents(dependencies: Dependencies) {
sourceQueue.initialize(actions);
addThreadEventListeners(threadFront);
tabTarget.on("workerListChanged", () => threadListChanged("worker"));
debuggerClient.mainRoot.on("processListChanged", () =>
threadListChanged("contentProcess")
);
tabTarget.on("workerListChanged", () => threadListChanged());
debuggerClient.mainRoot.on("processListChanged", () => threadListChanged());
if (features.windowlessServiceWorkers || attachAllTargets(tabTarget)) {
const workersListener = new WorkersListener(debuggerClient.mainRoot);
workersListener.addListener(() => threadListChanged("worker"));
workersListener.addListener(() => threadListChanged());
}
}
@ -114,8 +112,8 @@ function newSource(threadFront: ThreadFront, { source }: SourcePacket) {
});
}
function threadListChanged(type) {
actions.updateThreads(type);
function threadListChanged() {
actions.updateThreads();
}
function replayFramePositions(

Просмотреть файл

@ -90,6 +90,7 @@ async function listWorkerTargets(args: Args) {
} else {
workers = (await currentTarget.listWorkers()).workers;
if (currentTarget.url && features.windowlessServiceWorkers) {
allWorkers = await debuggerClient.mainRoot.listAllWorkerTargets();
const {
registrations,
} = await debuggerClient.mainRoot.listServiceWorkerRegistrations();
@ -100,10 +101,16 @@ async function listWorkerTargets(args: Args) {
}
for (const front of serviceWorkerRegistrations) {
const { activeWorker, waitingWorker, installingWorker } = front;
const {
activeWorker,
waitingWorker,
installingWorker,
evaluatingWorker,
} = front;
await maybeMarkServiceWorker(activeWorker, "active");
await maybeMarkServiceWorker(waitingWorker, "waiting");
await maybeMarkServiceWorker(installingWorker, "installing");
await maybeMarkServiceWorker(evaluatingWorker, "evaluating");
}
async function maybeMarkServiceWorker(info, status) {
@ -111,9 +118,6 @@ async function listWorkerTargets(args: Args) {
return;
}
if (!allWorkers) {
allWorkers = await debuggerClient.mainRoot.listAllWorkerTargets();
}
const worker = allWorkers.find(front => front && front.id == info.id);
if (!worker) {
return;
@ -128,20 +132,37 @@ async function listWorkerTargets(args: Args) {
return workers;
}
async function listProcessTargets(args: Args) {
const { currentTarget, debuggerClient } = args;
if (!attachAllTargets(currentTarget)) {
return [];
}
async function getAllProcessTargets(args) {
const { debuggerClient } = args;
const { processes } = await debuggerClient.mainRoot.listProcesses();
const targets = await Promise.all(
return Promise.all(
processes
.filter(descriptor => !descriptor.isParent)
.map(descriptor => descriptor.getTarget())
);
}
return targets;
async function listProcessTargets(args: Args) {
const { currentTarget } = args;
if (!attachAllTargets(currentTarget)) {
if (currentTarget.url && features.windowlessServiceWorkers) {
// Service workers associated with our target's origin need to pause until
// we attach, regardless of which process they are running in.
const origin = new URL(currentTarget.url).origin;
const targets = await getAllProcessTargets(args);
try {
await Promise.all(
targets.map(t => t.pauseMatchingServiceWorkers({ origin }))
);
} catch (e) {
// Old servers without pauseMatchingServiceWorkers will throw.
// @backward-compatibility: remove in Firefox 75
}
}
return [];
}
return getAllProcessTargets(args);
}
export async function updateTargets(args: Args) {

Просмотреть файл

@ -7,6 +7,14 @@ async function checkWorkerThreads(dbg, count) {
ok(true, `Have ${count} threads`);
}
async function checkWorkerStatus(dbg, status) {
await waitUntil(() => {
const threads = dbg.selectors.getThreads();
return threads.some(t => t.serviceWorkerStatus == status);
});
ok(true, `Have thread with status ${status}`);
}
// Test that we can detect a new service worker and hit breakpoints that we've
// set in it.
add_task(async function() {
@ -31,8 +39,9 @@ add_task(async function() {
await waitForPaused(dbg);
assertPausedAtSourceAndLine(dbg, workerSource.id, 13);
// Leave the breakpoint in place for the next subtest.
// Leave the breakpoint and worker in place for the next subtest.
await resume(dbg);
await waitForRequestsToSettle(dbg);
await removeTab(gBrowser.selectedTab);
});
@ -61,6 +70,7 @@ add_task(async function() {
invokeInTab("unregisterWorker");
await checkWorkerThreads(dbg, 0);
await waitForRequestsToSettle(dbg);
await removeTab(gBrowser.selectedTab);
});
@ -73,6 +83,7 @@ add_task(async function() {
invokeInTab("registerWorker");
await checkWorkerThreads(dbg, 1);
await checkWorkerStatus(dbg, "active");
const firstTab = gBrowser.selectedTab;
@ -101,9 +112,13 @@ add_task(async function() {
ok(content0.value.includes("newServiceWorker") != content1.value.includes("newServiceWorker"),
"Got two different 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);
@ -111,3 +126,41 @@ add_task(async function() {
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");
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, "evaluating");
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, "active");
await resume(dbg);
invokeInTab("unregisterWorker");
await checkWorkerThreads(dbg, 0);
await waitForRequestsToSettle(dbg);
await removeTab(gBrowser.selectedTab);
});

Просмотреть файл

@ -19,6 +19,10 @@ self.addEventListener("fetch", event => {
event.respondWith(response);
}
});
self.addEventListener("install", event => {
dump("Install\\n");
});
`;
function handleRequest(request, response) {
@ -30,17 +34,5 @@ function handleRequest(request, response) {
}
const status = getState("status");
let newBody = body.replace("STATUS", status);
if (status == "stuckInstall") {
newBody += `
self.addEventListener("install", event => {
dump("Install\\n");
event.waitUntil(new Promise(resolve => {}));
});
`;
}
response.write(newBody);
response.write(body.replace("STATUS", status));
}