Bug 1550030 - Part 1: Implement the DOM mutation breakpoint context menu items in the markup view. r=loganfsmyth,jdescottes

This implements the context menu items for the DOM mutation breakpoint.
In addition, there were some server changes to:
- Update the mutationBreakpoints form for the NodeActor
- Expose the mutationBreakpoints form
- Moved the setMutationBreakpoints method from the Node spec to Walker spec
since the Node spec only consisted of getter methods. It made more sense
that the setter went into the Walker spec to be more consistent with how
the Walker and Node spec have been arranged.

Unit tests will be followed up in Part 2 immediately.

Differential Revision: https://phabricator.services.mozilla.com/D36074
This commit is contained in:
Gabriel Luong 2019-06-26 15:16:22 -04:00
parent b7763aca9f
commit 1aa241f2d1
9 changed files with 89 additions and 27 deletions

View File

@ -473,6 +473,37 @@ class MarkupContextMenu {
return copySubmenu;
}
_getDOMBreakpointSubmenu(isSelectionElement) {
const menu = new Menu();
const mutationBreakpoints = this.selection.nodeFront.mutationBreakpoints;
menu.append(new MenuItem({
checked: mutationBreakpoints.subtree,
click: () => this.markup.toggleMutationBreakpoint("subtree"),
disabled: !isSelectionElement,
label: INSPECTOR_L10N.getStr("inspectorSubtreeModification.label"),
type: "checkbox",
}));
menu.append(new MenuItem({
checked: mutationBreakpoints.attribute,
click: () => this.markup.toggleMutationBreakpoint("attribute"),
disabled: !isSelectionElement,
label: INSPECTOR_L10N.getStr("inspectorAttributeModification.label"),
type: "checkbox",
}));
menu.append(new MenuItem({
checked: mutationBreakpoints.removal,
click: () => this.markup.toggleMutationBreakpoint("removal"),
disabled: !isSelectionElement,
label: INSPECTOR_L10N.getStr("inspectorNodeRemoval.label"),
type: "checkbox",
}));
return menu;
}
/**
* Link menu items can be shown or hidden depending on the context and
* selected node, and their labels can vary.
@ -673,6 +704,14 @@ class MarkupContextMenu {
type: "separator",
}));
if (Services.prefs.getBoolPref("devtools.markup.mutationBreakpoints.enabled") &&
this.selection.nodeFront.mutationBreakpoints) {
menu.append(new MenuItem({
label: INSPECTOR_L10N.getStr("inspectorBreakpointSubmenu.label"),
submenu: this._getDOMBreakpointSubmenu(isSelectionElement),
}));
}
menu.append(new MenuItem({
id: "node-menu-useinconsole",
label: INSPECTOR_L10N.getStr("inspectorUseInConsole.label"),

View File

@ -1136,6 +1136,18 @@ MarkupView.prototype = {
this.inspector.selection.nodeFront.scrollIntoView();
},
async toggleMutationBreakpoint(name) {
if (!this.inspector.selection.isElementNode()) {
return;
}
const nodeFront = this.inspector.selection.nodeFront;
const mutationBreakpoints = nodeFront.mutationBreakpoints;
await this.walker.setMutationBreakpoints(nodeFront, {
[name]: !mutationBreakpoints[name],
});
},
/**
* If an editable item is focused, select its container.
*/

View File

@ -294,6 +294,25 @@ inspectorAddAttribute.accesskey=A
# shown in the inspector contextual-menu for the sub-menu of the pseudo-classes.
inspectorPseudoClassSubmenu.label=Change Pseudo-class
# LOCALIZATION NOTE (inspectorBreakpointSubmenu.label): This is the label
# shown in the inspector contextual-menu for the sub-menu of the DOM breakpoints.
inspectorBreakpointSubmenu.label=Break on…
# LOCALIZATION NOTE (inspectorSubtreeModification.label): This is the label shown
# in the inspector contextual-menu for the item that lets users add a DOM breakpoint
# for subtree modification.
inspectorSubtreeModification.label=Subtree Modification
# LOCALIZATION NOTE (inspectorAttributeModification.label): This is the label shown
# in the inspector contextual-menu for the item that lets users add a DOM breakpoint
# for attribute modification.
inspectorAttributeModification.label=Attribute Modification
# LOCALIZATION NOTE (inspectorNodeRemoval.label): This is the label shown
# in the inspector contextual-menu for the item that lets users add a DOM breakpoint
# for node removal.
inspectorNodeRemoval.label=Node Removal
# LOCALIZATION NOTE (inspectorSearchHTML.label3): This is the label that is
# shown as the placeholder for the markup view search in the inspector.
inspectorSearchHTML.label3=Search HTML

View File

@ -81,12 +81,12 @@ pref("devtools.eyedropper.zoom", 6);
// Enable to collapse attributes that are too long.
pref("devtools.markup.collapseAttributes", true);
// Length to collapse attributes
pref("devtools.markup.collapseAttributeLength", 120);
// Whether to auto-beautify the HTML on copy.
pref("devtools.markup.beautifyOnCopy", false);
// Whether or not the DOM mutation breakpoints context menu are enabled in the markup view
pref("devtools.markup.mutationBreakpoints.enabled", false);
// DevTools default color unit
pref("devtools.defaultColorUnit", "authored");

View File

@ -534,16 +534,6 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
innerHeight: win.innerHeight,
};
},
/**
* The breakpoint values to toggle off and on for this node. Only
* breakpoint types specified in 'bps' will be toggled.
*
* @param {Object} bps The subset of bp types to set the state for.
*/
setMutationBreakpoints(bps) {
this.walker.setMutationBreakpoints(this, bps);
},
});
/**

View File

@ -1784,9 +1784,9 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
const actor = this.getNode(rawNode);
if (actor) {
this.queueMutation({
type: "mutationBreakpointUpdate",
target: actor.actorID,
mutationBreakpoints: this.getMutationBreakpoints(rawNode),
type: "mutationBreakpoint",
mutationBreakpoints: this.getMutationBreakpoints(actor),
});
}
},

View File

@ -218,6 +218,8 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
this._form.pseudoClassLocks = change.pseudoClassLocks;
} else if (change.type === "events") {
this._form.hasEventListeners = change.hasEventListeners;
} else if (change.type === "mutationBreakpoint") {
this._form.mutationBreakpoints = change.mutationBreakpoints;
}
}
@ -343,6 +345,10 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
return this._form.attrs;
}
get mutationBreakpoints() {
return this._form.mutationBreakpoints;
}
get pseudoClassLocks() {
return this._form.pseudoClassLocks || [];
}

View File

@ -350,6 +350,15 @@ const walkerSpec = generateActorSpec({
value: RetVal("boolean"),
},
},
setMutationBreakpoints: {
request: {
node: Arg(0, "nullable:domnode"),
subtree: Option(1, "nullable:boolean"),
removal: Option(1, "nullable:boolean"),
attribute: Option(1, "nullable:boolean"),
},
response: {},
},
},
});

View File

@ -45,12 +45,6 @@ types.addDictType("disconnectedNodeArray", {
newParents: "array:domnode",
});
types.addDictType("mutationBreakpointsRequest", {
subtree: "nullable:boolean",
removal: "nullable:boolean",
attribute: "nullable:boolean",
});
const nodeListSpec = generateActorSpec({
typeName: "domnodelist",
@ -140,13 +134,6 @@ const nodeSpec = generateActorSpec({
request: {},
response: RetVal("windowDimensions"),
},
setMutationBreakpoints: {
request: {
breakpoints: Arg(0, "mutationBreakpointsRequest"),
},
response: {},
},
},
});