Bug 1730167 - [devtools] Use appropriate walker front to retrieve frame children when EFT is enabled. r=ochameau

Differential Revision: https://phabricator.services.mozilla.com/D126064
This commit is contained in:
Nicolas Chevobbe 2021-10-01 16:24:49 +00:00
Родитель 389ea3b113
Коммит 295c4f6eff
6 изменённых файлов: 66 добавлений и 39 удалений

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

@ -281,12 +281,15 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
get numChildren() {
return this._form.numChildren;
}
get remoteFrame() {
get useChildTargetToFetchChildren() {
if (!BROWSER_TOOLBOX_FISSION_ENABLED && this._hasParentProcessTarget) {
return false;
}
return this._form.remoteFrame;
// @backward-compat { version 94 } useChildTargetToFetchChildren was added in 94, so
// we still need to check for `remoteFrame` when connecting to older server.
// When 94 is in release, we can check useChildTargetToFetchChildren only
return this._form.useChildTargetToFetchChildren || this._form.remoteFrame;
}
get hasEventListeners() {
return this._form.hasEventListeners;
@ -529,20 +532,23 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
return actor.rawNode;
}
async connectToRemoteFrame() {
if (!this.remoteFrame) {
console.warn("Tried to open remote connection to an invalid frame.");
async connectToFrame() {
if (!this.useChildTargetToFetchChildren) {
console.warn("Tried to open connection to an invalid frame.");
return null;
}
if (this._remoteFrameTarget && !this._remoteFrameTarget.isDestroyed()) {
return this._remoteFrameTarget;
if (
this._childBrowsingContextTarget &&
!this._childBrowsingContextTarget.isDestroyed()
) {
return this._childBrowsingContextTarget;
}
// Get the target for this remote frame element
this._remoteFrameTarget = await this.targetFront.getWindowGlobalTarget(
// Get the target for this frame element
this._childBrowsingContextTarget = await this.targetFront.getWindowGlobalTarget(
this._form.browsingContextID
);
return this._remoteFrameTarget;
return this._childBrowsingContextTarget;
}
}

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

@ -334,11 +334,11 @@ class WalkerFront extends FrontClassWithSpec(walkerSpec) {
}
async children(node, options) {
if (!node.remoteFrame) {
if (!node.useChildTargetToFetchChildren) {
return super.children(node, options);
}
const remoteTarget = await node.connectToRemoteFrame();
const walker = (await remoteTarget.getFront("inspector")).walker;
const target = await node.connectToFrame();
const walker = (await target.getFront("inspector")).walker;
// Finally retrieve the NodeFront of the remote frame's document
const documentNode = await walker.getRootNode();

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

@ -9,12 +9,15 @@ const TEST_URL = URL_ROOT + "doc_inspector_delete-selected-node-01.html";
add_task(async function() {
const { inspector } = await openInspectorForURL(TEST_URL);
const span = await getNodeFrontInFrames(["iframe", "span"], inspector);
await selectNode(span, inspector);
const spanNodeFront = await getNodeFrontInFrames(
["iframe", "span"],
inspector
);
await selectNode(spanNodeFront, inspector);
info("Removing selected <span> element.");
const parentNode = span.parentNode();
await inspector.walker.removeNode(span);
const parentNode = spanNodeFront.parentNode();
await spanNodeFront.inspectorFront.walker.removeNode(spanNodeFront);
// Wait for the inspector to process the mutation
await inspector.once("inspector-updated");

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

@ -276,26 +276,26 @@ async function getNodeFrontInFrames(selectors, inspector) {
const url = walker.targetFront.url;
info(`Find the frame element for selector ${frameSelector} in ${url}`);
const frameFront = await walker.querySelector(rootNode, frameSelector);
const frameNodeFront = await walker.querySelector(rootNode, frameSelector);
// For a remote frame, connect to the corresponding frame target.
// If needed, connect to the corresponding frame target.
// Otherwise, reuse the current targetFront.
let frameTarget = frameFront.targetFront;
if (frameFront.remoteFrame) {
info("Connect to remote frame and retrieve the targetFront");
frameTarget = await frameFront.connectToRemoteFrame();
let frameTarget = frameNodeFront.targetFront;
if (frameNodeFront.useChildTargetToFetchChildren) {
info("Connect to frame and retrieve the targetFront");
frameTarget = await frameNodeFront.connectToFrame();
}
walker = (await frameTarget.getFront("inspector")).walker;
if (frameFront.remoteFrame) {
// For remote frames or browser elements, use the walker's rootNode.
if (frameNodeFront.useChildTargetToFetchChildren) {
// For frames or browser elements, use the walker's rootNode.
rootNode = walker.rootNode;
} else {
// For same-process frames, select the document front as the root node.
// It is a different node from the walker's rootNode.
info("Retrieve the children of the frame to find the document node");
const { nodes } = await walker.children(frameFront);
const { nodes } = await walker.children(frameNodeFront);
rootNode = nodes.find(n => n.nodeType === Node.DOCUMENT_NODE);
}
}

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

@ -10,6 +10,7 @@ const InspectorUtils = require("InspectorUtils");
const protocol = require("devtools/shared/protocol");
const { PSEUDO_CLASSES } = require("devtools/shared/css/constants");
const { nodeSpec, nodeListSpec } = require("devtools/shared/specs/node");
loader.lazyRequireGetter(
this,
["getCssPath", "getXPath", "findCssSelector", "findAllCssSelectors"],
@ -29,7 +30,7 @@ loader.lazyRequireGetter(
"isShadowHost",
"isShadowRoot",
"getShadowRootMode",
"isRemoteFrame",
"isFrameWithChildTarget",
],
"devtools/shared/layout/utils",
true
@ -212,10 +213,12 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
form.isDocumentElement = true;
}
// Flag the remote frame and declare at least one child (the #document element) so
// that they can be expanded.
if (this.isRemoteFrame) {
form.remoteFrame = true;
// Flag the node if a different walker is needed to retrieve its children (i.e. if
// this is a remote frame, or if it's an iframe and we're creating targets for every iframes)
if (this.useChildTargetToFetchChildren) {
form.useChildTargetToFetchChildren = true;
// Declare at least one child (the #document element) so
// that they can be expanded.
form.numChildren = 1;
form.browsingContextID = this.rawNode.browsingContext.id;
}
@ -253,14 +256,13 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
},
/**
* Check if the current node is representing a remote frame.
* In the context of the browser toolbox, a remote frame can be the <browser remote>
* element found inside each tab.
* In the context of the content toolbox, a remote frame can be a <iframe> that contains
* a different origin document.
* Check if the current node represents an element (e.g. an iframe) which has a dedicated
* target for its underlying document that we would need to use to fetch the child nodes.
* This will be the case for iframes if EFT is enabled, or if this is a remote iframe and
* fission is enabled.
*/
get isRemoteFrame() {
return isRemoteFrame(this.rawNode);
get useChildTargetToFetchChildren() {
return isFrameWithChildTarget(this.walker.targetActor, this.rawNode);
},
get isTopLevelDocument() {

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

@ -827,6 +827,10 @@ function getAbsoluteScrollOffsetsForNode(node) {
}
exports.getAbsoluteScrollOffsetsForNode = getAbsoluteScrollOffsetsForNode;
function isIframe(node) {
return ChromeUtils.getClassName(node) == "HTMLIFrameElement";
}
/**
* Check if the provided node is representing a remote <browser> element.
*
@ -854,7 +858,7 @@ exports.isRemoteBrowserElement = isRemoteBrowserElement;
* @return {Boolean}
*/
function isRemoteFrame(node) {
if (ChromeUtils.getClassName(node) == "HTMLIFrameElement") {
if (isIframe(node)) {
return node.frameLoader?.isRemoteFrame;
}
@ -865,3 +869,15 @@ function isRemoteFrame(node) {
return false;
}
exports.isRemoteFrame = isRemoteFrame;
/**
* Check if the provided node is representing a frame that has its own dedicated child target.
*
* @param {BrowsingContextTargetActor} targetActor
* @param {DOMNode} node
* @returns {Boolean}
*/
function isFrameWithChildTarget(targetActor, node) {
return isRemoteFrame(node) || (isIframe(node) && targetActor.ignoreSubFrames);
}
exports.isFrameWithChildTarget = isFrameWithChildTarget;