Bug 1691755 - Move view-source context menu items to nsContextMenu r=Gijs

Differential Revision: https://phabricator.services.mozilla.com/D104956
This commit is contained in:
Kagami Sascha Rosylight 2021-02-12 18:31:47 +00:00
parent 90f209f9d1
commit b97e032178
5 changed files with 95 additions and 101 deletions

View File

@ -34,6 +34,15 @@
</menugroup>
<menuseparator id="context-sep-navigation"/>
<menuseparator id="page-menu-separator"/>
<menuitem id="context-viewsource-goToLine"
oncommand="gViewSourceUtils.getPageActor(gContextMenu.browser).promptAndGoToLine()"/>
<menuitem id="context-viewsource-wrapLongLines"
type="checkbox"
oncommand="gViewSourceUtils.getPageActor(gContextMenu.browser).sendAsyncMessage('ViewSource:ToggleWrapping');"/>
<menuitem id="context-viewsource-highlightSyntax"
type="checkbox"
oncommand="gViewSourceUtils.getPageActor(gContextMenu.browser).sendAsyncMessage('ViewSource:ToggleSyntaxHighlighting');"/>
<menuseparator id="context-sep-viewsource-commands"/>
<menuitem id="spell-no-suggestions"
disabled="true"
label="&spellNoSuggestions.label;"/>

View File

@ -333,6 +333,7 @@ class nsContextMenu {
this.initClickToPlayItems();
this.initPasswordManagerItems();
this.initSyncItems();
this.initViewSourceItems();
}
initPageMenuSeparator() {
@ -1061,6 +1062,40 @@ class nsContextMenu {
gSync.updateContentContextMenu(this);
}
initViewSourceItems() {
const getString = name => {
const { bundle } = gViewSourceUtils.getPageActor(this.browser);
return bundle.GetStringFromName(name);
};
const showViewSourceItem = (id, check, accesskey) => {
const fullId = `context-viewsource-${id}`;
this.showItem(fullId, onViewSource);
if (!onViewSource) {
return;
}
check().then(checked => this.setItemAttr(fullId, "checked", checked));
this.setItemAttr(fullId, "label", getString(`context_${id}_label`));
if (accesskey) {
this.setItemAttr(
fullId,
"accesskey",
getString(`context_${id}_accesskey`)
);
}
};
const onViewSource = this.browser.currentURI.schemeIs("view-source");
showViewSourceItem("goToLine", async () => false, true);
showViewSourceItem("wrapLongLines", () =>
gViewSourceUtils.getPageActor(this.browser).queryIsWrapping()
);
showViewSourceItem("highlightSyntax", () =>
gViewSourceUtils.getPageActor(this.browser).queryIsSyntaxHighlighting()
);
this.showItem("context-sep-viewsource-commands", onViewSource);
}
openPasswordManager() {
LoginHelper.openPasswordManager(window, {
entryPoint: "contextmenu",

View File

@ -13,7 +13,6 @@ var EXPORTED_SYMBOLS = ["ViewSourcePageChild"];
XPCOMUtils.defineLazyGlobalGetters(this, ["NodeFilter"]);
const NS_XHTML = "http://www.w3.org/1999/xhtml";
const BUNDLE_URL = "chrome://global/locale/viewSource.properties";
// These are markers used to delimit the selection during processing. They
@ -36,37 +35,6 @@ let gNeedsDrawSelection = false;
*/
let gInitialLineNumber = -1;
/**
* In-page context menu items that are injected after page load.
*/
let gContextMenuItems = [
{
id: "goToLine",
accesskey: true,
handler(actor) {
actor.sendAsyncMessage("ViewSource:PromptAndGoToLine");
},
},
{
id: "wrapLongLines",
get checked() {
return Services.prefs.getBoolPref("view_source.wrap_long_lines");
},
handler(actor) {
actor.toggleWrapping();
},
},
{
id: "highlightSyntax",
get checked() {
return Services.prefs.getBoolPref("view_source.syntax_highlight");
},
handler(actor) {
actor.toggleSyntaxHighlighting();
},
},
];
class ViewSourcePageChild extends JSWindowActorChild {
constructor() {
super();
@ -85,9 +53,22 @@ class ViewSourcePageChild extends JSWindowActorChild {
}
receiveMessage(msg) {
if (msg.name == "ViewSource:GoToLine") {
this.goToLine(msg.data.lineNumber);
switch (msg.name) {
case "ViewSource:GoToLine":
this.goToLine(msg.data.lineNumber);
break;
case "ViewSource:IsWrapping":
return this.isWrapping;
case "ViewSource:IsSyntaxHighlighting":
return this.isSyntaxHighlighting;
case "ViewSource:ToggleWrapping":
this.toggleWrapping();
break;
case "ViewSource:ToggleSyntaxHighlighting":
this.toggleSyntaxHighlighting();
break;
}
return undefined;
}
/**
@ -128,20 +109,9 @@ class ViewSourcePageChild extends JSWindowActorChild {
* This handler is for click events from:
* * error page content, which can show up if the user attempts to view the
* source of an attack page.
* * in-page context menu actions
*/
onClick(event) {
let target = event.originalTarget;
// Check for content menu actions
if (target.id) {
gContextMenuItems.forEach(itemSpec => {
if (itemSpec.id !== target.id) {
return;
}
itemSpec.handler(this);
event.stopPropagation();
});
}
// Don't trust synthetic events
if (!event.isTrusted || event.target.localName != "button") {
@ -181,10 +151,6 @@ class ViewSourcePageChild extends JSWindowActorChild {
this.goToLine(gInitialLineNumber);
gInitialLineNumber = -1;
}
if (this.document.body) {
this.injectContextMenu();
}
}
/**
@ -380,6 +346,20 @@ class ViewSourcePageChild extends JSWindowActorChild {
return found || "range" in result;
}
/**
* @return {boolean} whether the "wrap" class exists on the document body.
*/
get isWrapping() {
return this.document.body.classList.contains("wrap");
}
/**
* @return {boolean} whether the "highlight" class exists on the document body.
*/
get isSyntaxHighlighting() {
return this.document.body.classList.contains("highlight");
}
/**
* Toggles the "wrap" class on the document body, which sets whether
* or not long lines are wrapped. Notifies parent to update the pref.
@ -500,56 +480,4 @@ class ViewSourcePageChild extends JSWindowActorChild {
findInst.findBackwards = findBackwards;
findInst.searchString = searchString;
}
/**
* Add context menu items for view source specific actions.
*/
injectContextMenu() {
let doc = this.document;
let menu = doc.createElementNS(NS_XHTML, "menu");
menu.setAttribute("type", "context");
menu.setAttribute("id", "actions");
doc.body.appendChild(menu);
doc.body.setAttribute("contextmenu", "actions");
gContextMenuItems.forEach(itemSpec => {
let item = doc.createElementNS(NS_XHTML, "menuitem");
item.setAttribute("id", itemSpec.id);
let labelName = `context_${itemSpec.id}_label`;
let label = this.bundle.GetStringFromName(labelName);
item.setAttribute("label", label);
if ("checked" in itemSpec) {
item.setAttribute("type", "checkbox");
}
if (itemSpec.accesskey) {
let accesskeyName = `context_${itemSpec.id}_accesskey`;
item.setAttribute(
"accesskey",
this.bundle.GetStringFromName(accesskeyName)
);
}
menu.appendChild(item);
});
this.updateContextMenu();
}
/**
* Update state of checkbox-style context menu items.
*/
updateContextMenu() {
let doc = this.document;
gContextMenuItems.forEach(itemSpec => {
if (!("checked" in itemSpec)) {
return;
}
let item = doc.getElementById(itemSpec.id);
if (itemSpec.checked) {
item.setAttribute("checked", true);
} else {
item.removeAttribute("checked");
}
});
}
}

View File

@ -139,6 +139,20 @@ class ViewSourcePageParent extends JSWindowActorParent {
this.promptAndGoToLine();
}
/**
* @return {boolean} the wrapping state
*/
queryIsWrapping() {
return this.sendQuery("ViewSource:IsWrapping");
}
/**
* @return {boolean} the syntax highlighting state
*/
queryIsSyntaxHighlighting() {
return this.sendQuery("ViewSource:IsSyntaxHighlighting");
}
/**
* Update the wrapping pref based on the child's current state.
* @param state

View File

@ -30,6 +30,14 @@ var gViewSourceUtils = {
return aBrowsingContext.currentWindowGlobal.getActor("ViewSource");
},
/**
* Get the ViewSourcePage actor.
* @param object An object with `browsingContext` field
*/
getPageActor({ browsingContext }) {
return browsingContext.currentWindowGlobal.getActor("ViewSourcePage");
},
/**
* Opens the view source window.
*