Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

/* Any copyright is dedicated to the Public Domain.
"use strict";
// Test the TargetCommand API with all possible descriptors
const CHROME_WORKER_URL = CHROME_URL_ROOT + "test_worker.js";
const DESCRIPTOR_TYPES = require("resource://devtools/client/fronts/descriptors/descriptor-types.js");
add_task(async function () {
// Enabled fission prefs
await pushPref("devtools.browsertoolbox.scope", "everything");
// Disable the preloaded process as it gets created lazily and may interfere
// with process count assertions
await pushPref("dom.ipc.processPrelaunch.enabled", false);
// This preference helps destroying the content process when we close the tab
await pushPref("dom.ipc.keepProcessesAlive.web", 1);
await testLocalTab();
await testRemoteTab();
await testParentProcess();
await testWorker();
await testWebExtension();
});
async function testParentProcess() {
info("Test TargetCommand against parent process descriptor");
const commands = await CommandsFactory.forMainProcess();
const { descriptorFront } = commands;
is(
descriptorFront.descriptorType,
DESCRIPTOR_TYPES.PROCESS,
"The descriptor type is correct"
);
is(
descriptorFront.isParentProcessDescriptor,
true,
"Descriptor front isParentProcessDescriptor is correct"
);
is(
descriptorFront.isProcessDescriptor,
true,
"Descriptor front isProcessDescriptor is correct"
);
const targetCommand = commands.targetCommand;
await targetCommand.startListening();
const targets = await targetCommand.getAllTargets(targetCommand.ALL_TYPES);
Assert.greater(
targets.length,
1,
"We get many targets when debugging the parent process"
);
const targetFront = targets[0];
is(targetFront, targetCommand.targetFront, "The first is the top level one");
is(
targetFront.targetType,
targetCommand.TYPES.FRAME,
"the parent process target is of frame type, because it inherits from WindowGlobalTargetActor"
);
is(targetFront.isTopLevel, true, "This is flagged as top level");
targetCommand.destroy();
await waitForAllTargetsToBeAttached(targetCommand);
await commands.destroy();
}
async function testLocalTab() {
info("Test TargetCommand against local tab descriptor (via getTab({ tab }))");
const tab = await addTab(TEST_URL);
const commands = await CommandsFactory.forTab(tab);
const { descriptorFront } = commands;
is(
descriptorFront.descriptorType,
DESCRIPTOR_TYPES.TAB,
"The descriptor type is correct"
);
is(
descriptorFront.isTabDescriptor,
true,
"Descriptor front isTabDescriptor is correct"
);
const targetCommand = commands.targetCommand;
await targetCommand.startListening();
const targets = await targetCommand.getAllTargets(targetCommand.ALL_TYPES);
is(targets.length, 1, "Got a unique target");
const targetFront = targets[0];
is(targetFront, targetCommand.targetFront, "The first is the top level one");
is(
targetFront.targetType,
targetCommand.TYPES.FRAME,
"the tab target is of frame type"
);
is(targetFront.isTopLevel, true, "This is flagged as top level");
targetCommand.destroy();
BrowserTestUtils.removeTab(tab);
await commands.destroy();
}
async function testRemoteTab() {
info(
"Test TargetCommand against remote tab descriptor (via getTab({ browserId }))"
);
const tab = await addTab(TEST_URL);
const commands = await CommandsFactory.forRemoteTab(
tab.linkedBrowser.browserId
);
const { descriptorFront } = commands;
is(
descriptorFront.descriptorType,
DESCRIPTOR_TYPES.TAB,
"The descriptor type is correct"
);
is(
descriptorFront.isTabDescriptor,
true,
"Descriptor front isTabDescriptor is correct"
);
const targetCommand = commands.targetCommand;
await targetCommand.startListening();
const targets = await targetCommand.getAllTargets(targetCommand.ALL_TYPES);
is(targets.length, 1, "Got a unique target");
const targetFront = targets[0];
is(
targetFront,
targetCommand.targetFront,
"TargetCommand top target is the same as the first target"
);
is(
targetFront.targetType,
targetCommand.TYPES.FRAME,
"the tab target is of frame type"
);
is(targetFront.isTopLevel, true, "This is flagged as top level");
const browser = tab.linkedBrowser;
const onLoaded = BrowserTestUtils.browserLoaded(browser);
BrowserTestUtils.startLoadingURIString(browser, SECOND_TEST_URL);
await onLoaded;
info("Wait for the new target");
await waitFor(() => targetCommand.targetFront != targetFront);
isnot(
targetCommand.targetFront,
targetFront,
"The top level target changes on navigation"
);
ok(
!targetCommand.targetFront.isDestroyed(),
"The new target isn't destroyed"
);
ok(targetFront.isDestroyed(), "While the previous target is destroyed");
targetCommand.destroy();
BrowserTestUtils.removeTab(tab);
await commands.destroy();
}
async function testWebExtension() {
info("Test TargetCommand against webextension descriptor");
const extension = ExtensionTestUtils.loadExtension({
useAddonManager: "temporary",
manifest: {
name: "Sample extension",
},
});
await extension.startup();
const commands = await CommandsFactory.forAddon(extension.id);
const { descriptorFront } = commands;
is(
descriptorFront.descriptorType,
DESCRIPTOR_TYPES.EXTENSION,
"The descriptor type is correct"
);
is(
descriptorFront.isWebExtensionDescriptor,
true,
"Descriptor front isWebExtensionDescriptor is correct"
);
const targetCommand = commands.targetCommand;
await targetCommand.startListening();
const targets = await targetCommand.getAllTargets(targetCommand.ALL_TYPES);
is(targets.length, 1, "Got a unique target");
const targetFront = targets[0];
is(targetFront, targetCommand.targetFront, "The first is the top level one");
is(
targetFront.targetType,
targetCommand.TYPES.FRAME,
"the web extension target is of frame type, because it inherits from WindowGlobalTargetActor"
);
is(targetFront.isTopLevel, true, "This is flagged as top level");
targetCommand.destroy();
await extension.unload();
await commands.destroy();
}
// CommandsFactory expect the worker id, which is computed from the nsIWorkerDebugger.id attribute
function getNextWorkerDebuggerId() {
return new Promise(resolve => {
const wdm = Cc[
"@mozilla.org/dom/workers/workerdebuggermanager;1"
].createInstance(Ci.nsIWorkerDebuggerManager);
const listener = {
onRegister(dbg) {
wdm.removeListener(listener);
resolve(dbg.id);
},
};
wdm.addListener(listener);
});
}
async function testWorker() {
info("Test TargetCommand against worker descriptor");
const workerUrl = CHROME_WORKER_URL + "#descriptor";
const onNextWorker = getNextWorkerDebuggerId();
const worker = new Worker(workerUrl);
const workerId = await onNextWorker;
ok(workerId, "Found the worker Debugger ID");
const commands = await CommandsFactory.forWorker(workerId);
const { descriptorFront } = commands;
is(
descriptorFront.descriptorType,
DESCRIPTOR_TYPES.WORKER,
"The descriptor type is correct"
);
is(
descriptorFront.isWorkerDescriptor,
true,
"Descriptor front isWorkerDescriptor is correct"
);
const targetCommand = commands.targetCommand;
await targetCommand.startListening();
const targets = await targetCommand.getAllTargets(targetCommand.ALL_TYPES);
is(targets.length, 1, "Got a unique target");
const targetFront = targets[0];
is(targetFront, targetCommand.targetFront, "The first is the top level one");
is(
targetFront.targetType,
targetCommand.TYPES.WORKER,
"the worker target is of worker type"
);
is(targetFront.isTopLevel, true, "This is flagged as top level");
targetCommand.destroy();
// Calling CommandsFactory.forWorker, will call RootFront.getWorker
// which will spawn lots of worker legacy code, firing lots of requests,
// which may still be pending
await commands.waitForRequestsToSettle();
await commands.destroy();
worker.terminate();
}