mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-11 05:39:41 +02:00
These tests were using chrome mochitest which forces the test page to be running in chrome and in parent process. This doesn't reflect typical setup where the page runs unprivileged in content process. Also, with the current bug, the pages running in system principal will be debugged with a special setup. Actors will be run with modules loaded in a distinct loader in order to be executed in a distinct compartment, distinct from the shared system principal compartment. That a prerequisite for the Debugger API. It has to run in a distinct compartment than its debuggee. Depends on D16825 Differential Revision: https://phabricator.services.mozilla.com/D16826 --HG-- rename : devtools/server/tests/mochitest/animation-data.html => devtools/server/tests/browser/animation-data.html rename : devtools/server/tests/mochitest/test_inspector-mutations-childlist.html => devtools/server/tests/browser/browser_inspector-mutations-childlist.js rename : devtools/server/tests/mochitest/inspector-helpers.js => devtools/server/tests/browser/inspector-helpers.js extra : moz-landing-system : lando
188 lines
5.7 KiB
JavaScript
188 lines
5.7 KiB
JavaScript
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
|
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
/* exported assertOwnershipTrees, checkMissing, waitForMutation,
|
|
isSrcChange, isUnretained, isNewRoot,
|
|
assertSrcChange, assertUnload, assertFrameLoad, assertChildList,
|
|
*/
|
|
|
|
function serverOwnershipTree(walkerArg) {
|
|
return ContentTask.spawn(gBrowser.selectedBrowser, [walkerArg.actorID],
|
|
function(actorID) {
|
|
const { require } =
|
|
ChromeUtils.import("resource://devtools/shared/Loader.jsm");
|
|
const { DebuggerServer } = require("devtools/server/main");
|
|
const { DocumentWalker } =
|
|
require("devtools/server/actors/inspector/document-walker");
|
|
|
|
// Convert actorID to current compartment string otherwise
|
|
// searchAllConnectionsForActor is confused and won't find the actor.
|
|
actorID = String(actorID);
|
|
const serverWalker = DebuggerServer.searchAllConnectionsForActor(actorID);
|
|
|
|
function sortOwnershipChildrenContentScript(children) {
|
|
return children.sort((a, b) => a.name.localeCompare(b.name));
|
|
}
|
|
|
|
function serverOwnershipSubtree(walker, node) {
|
|
const actor = walker._refMap.get(node);
|
|
if (!actor) {
|
|
return undefined;
|
|
}
|
|
|
|
const children = [];
|
|
const docwalker = new DocumentWalker(node, content);
|
|
let child = docwalker.firstChild();
|
|
while (child) {
|
|
const item = serverOwnershipSubtree(walker, child);
|
|
if (item) {
|
|
children.push(item);
|
|
}
|
|
child = docwalker.nextSibling();
|
|
}
|
|
return {
|
|
name: actor.actorID,
|
|
children: sortOwnershipChildrenContentScript(children),
|
|
};
|
|
}
|
|
return {
|
|
root: serverOwnershipSubtree(serverWalker, serverWalker.rootDoc),
|
|
orphaned: [...serverWalker._orphaned]
|
|
.map(o => serverOwnershipSubtree(serverWalker, o.rawNode)),
|
|
retained: [...serverWalker._retainedOrphans]
|
|
.map(o => serverOwnershipSubtree(serverWalker, o.rawNode)),
|
|
};
|
|
});
|
|
}
|
|
|
|
function sortOwnershipChildren(children) {
|
|
return children.sort((a, b) => a.name.localeCompare(b.name));
|
|
}
|
|
|
|
function clientOwnershipSubtree(node) {
|
|
return {
|
|
name: node.actorID,
|
|
children: sortOwnershipChildren(node.treeChildren()
|
|
.map(child => clientOwnershipSubtree(child))),
|
|
};
|
|
}
|
|
|
|
function clientOwnershipTree(walker) {
|
|
return {
|
|
root: clientOwnershipSubtree(walker.rootNode),
|
|
orphaned: [...walker._orphaned].map(o => clientOwnershipSubtree(o)),
|
|
retained: [...walker._retainedOrphans].map(o => clientOwnershipSubtree(o)),
|
|
};
|
|
}
|
|
|
|
function ownershipTreeSize(tree) {
|
|
let size = 1;
|
|
for (const child of tree.children) {
|
|
size += ownershipTreeSize(child);
|
|
}
|
|
return size;
|
|
}
|
|
|
|
async function assertOwnershipTrees(walker) {
|
|
const serverTree = await serverOwnershipTree(walker);
|
|
const clientTree = clientOwnershipTree(walker);
|
|
is(JSON.stringify(clientTree, null, " "), JSON.stringify(serverTree, null, " "),
|
|
"Server and client ownership trees should match.");
|
|
|
|
return ownershipTreeSize(clientTree.root);
|
|
}
|
|
|
|
// Verify that an actorID is inaccessible both from the client library and the server.
|
|
function checkMissing({client}, actorID) {
|
|
return new Promise(resolve => {
|
|
const front = client.getActor(actorID);
|
|
ok(!front, "Front shouldn't be accessible from the client for actorID: " + actorID);
|
|
|
|
client.request({
|
|
to: actorID,
|
|
type: "request",
|
|
}, response => {
|
|
is(response.error, "noSuchActor",
|
|
"node list actor should no longer be contactable.");
|
|
resolve(undefined);
|
|
});
|
|
});
|
|
}
|
|
|
|
// Load mutations aren't predictable, so keep accumulating mutations until
|
|
// the one we're looking for shows up.
|
|
function waitForMutation(walker, test, mutations = []) {
|
|
return new Promise(resolve => {
|
|
for (const change of mutations) {
|
|
if (test(change)) {
|
|
resolve(mutations);
|
|
}
|
|
}
|
|
|
|
walker.once("mutations", newMutations => {
|
|
waitForMutation(walker, test, mutations.concat(newMutations))
|
|
.then(finalMutations => {
|
|
resolve(finalMutations);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
function assertAndStrip(mutations, message, test) {
|
|
const size = mutations.length;
|
|
mutations = mutations.filter(test);
|
|
ok((mutations.size != size), message);
|
|
return mutations;
|
|
}
|
|
|
|
function isSrcChange(change) {
|
|
return change.type === "attributes" && change.attributeName === "src";
|
|
}
|
|
|
|
function isUnload(change) {
|
|
return change.type === "documentUnload";
|
|
}
|
|
|
|
function isFrameLoad(change) {
|
|
return change.type === "frameLoad";
|
|
}
|
|
|
|
function isUnretained(change) {
|
|
return change.type === "unretained";
|
|
}
|
|
|
|
function isChildList(change) {
|
|
return change.type === "childList";
|
|
}
|
|
|
|
function isNewRoot(change) {
|
|
return change.type === "newRoot";
|
|
}
|
|
|
|
// Make sure an iframe's src attribute changed and then
|
|
// strip that mutation out of the list.
|
|
function assertSrcChange(mutations) {
|
|
return assertAndStrip(mutations, "Should have had an iframe source change.",
|
|
isSrcChange);
|
|
}
|
|
|
|
// Make sure there's an unload in the mutation list and strip
|
|
// that mutation out of the list
|
|
function assertUnload(mutations) {
|
|
return assertAndStrip(mutations, "Should have had a document unload change.", isUnload);
|
|
}
|
|
|
|
// Make sure there's a frame load in the mutation list and strip
|
|
// that mutation out of the list
|
|
function assertFrameLoad(mutations) {
|
|
return assertAndStrip(mutations, "Should have had a frame load change.", isFrameLoad);
|
|
}
|
|
|
|
// Make sure there's a childList change in the mutation list and strip
|
|
// that mutation out of the list
|
|
function assertChildList(mutations) {
|
|
return assertAndStrip(mutations, "Should have had a frame load change.", isChildList);
|
|
}
|