Bug 1472491: Part 5e - Add ContextMenuChild actor. r=felipe
MozReview-Commit-ID: GUJfyCPkRw8
rename from browser/modules/ContextMenu.jsm
rename to browser/actors/ContextMenuChild.jsm
--- a/browser/modules/ContextMenu.jsm
+++ b/browser/actors/ContextMenuChild.jsm
@@ -1,21 +1,23 @@
/* -*- mode: js; indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 sw=2 sts=2 et tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
-var EXPORTED_SYMBOLS = ["ContextMenu"];
+var EXPORTED_SYMBOLS = ["ContextMenuChild"];
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ChromeUtils.import("resource://gre/modules/ActorChild.jsm");
+
XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]);
XPCOMUtils.defineLazyModuleGetters(this, {
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
BrowserUtils: "resource://gre/modules/BrowserUtils.jsm",
findAllCssSelectors: "resource://gre/modules/css-selector.js",
SpellCheckHelper: "resource://gre/modules/InlineSpellChecker.jsm",
LoginManagerContent: "resource://gre/modules/LoginManagerContent.jsm",
@@ -29,24 +31,24 @@ XPCOMUtils.defineLazyGetter(this, "PageM
ChromeUtils.import("resource://gre/modules/PageMenu.jsm", tmp);
return new tmp.PageMenuChild();
});
const messageListeners = {
"ContextMenu:BookmarkFrame": function(aMessage) {
let frame = this.getTarget(aMessage).ownerDocument;
- this.global.sendAsyncMessage("ContextMenu:BookmarkFrame:Result",
- { title: frame.title });
+ this.mm.sendAsyncMessage("ContextMenu:BookmarkFrame:Result",
+ { title: frame.title });
},
"ContextMenu:Canvas:ToBlobURL": function(aMessage) {
this.getTarget(aMessage).toBlob((blob) => {
let blobURL = URL.createObjectURL(blob);
- this.global.sendAsyncMessage("ContextMenu:Canvas:ToBlobURL:Result", { blobURL });
+ this.mm.sendAsyncMessage("ContextMenu:Canvas:ToBlobURL:Result", { blobURL });
});
},
"ContextMenu:DoCustomCommand": function(aMessage) {
E10SUtils.wrapHandlingUserInput(
this.content,
aMessage.data.handlingUserInput,
() => PageMenuChild.executeMenu(aMessage.data.generatedItemId)
@@ -163,31 +165,31 @@ const messageListeners = {
if (isURLEncoded) {
postData = formData.join("&");
} else {
let separator = spec.includes("?") ? "&" : "?";
spec += separator + formData.join("&");
}
- this.global.sendAsyncMessage("ContextMenu:SearchFieldBookmarkData:Result",
- { spec, title, postData, charset });
+ this.mm.sendAsyncMessage("ContextMenu:SearchFieldBookmarkData:Result",
+ { spec, title, postData, charset });
},
"ContextMenu:SaveVideoFrameAsImage": function(aMessage) {
let video = this.getTarget(aMessage);
let canvas = this.content.document.createElementNS("http://www.w3.org/1999/xhtml",
"canvas");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
let ctxDraw = canvas.getContext("2d");
ctxDraw.drawImage(video, 0, 0);
- this.global.sendAsyncMessage("ContextMenu:SaveVideoFrameAsImage:Result", {
+ this.mm.sendAsyncMessage("ContextMenu:SaveVideoFrameAsImage:Result", {
dataURL: canvas.toDataURL("image/jpeg", ""),
});
},
"ContextMenu:SetAsDesktopBackground": function(aMessage) {
let target = this.getTarget(aMessage);
// Paranoia: check disableSetDesktopBackground again, in case the
@@ -201,44 +203,52 @@ const messageListeners = {
let canvas = this.content.document.createElement("canvas");
canvas.width = target.naturalWidth;
canvas.height = target.naturalHeight;
let ctx = canvas.getContext("2d");
ctx.drawImage(target, 0, 0);
let dataUrl = canvas.toDataURL();
let url = (new URL(target.ownerDocument.location.href)).pathname;
let imageName = url.substr(url.lastIndexOf("/") + 1);
- this.global.sendAsyncMessage("ContextMenu:SetAsDesktopBackground:Result",
- { dataUrl, imageName });
+ this.mm.sendAsyncMessage("ContextMenu:SetAsDesktopBackground:Result",
+ { dataUrl, imageName });
} catch (e) {
Cu.reportError(e);
disable = true;
}
}
if (disable) {
- this.global.sendAsyncMessage("ContextMenu:SetAsDesktopBackground:Result",
- { disable });
+ this.mm.sendAsyncMessage("ContextMenu:SetAsDesktopBackground:Result",
+ { disable });
}
},
};
-class ContextMenu {
+let contextMenus = new WeakMap();
+
+class ContextMenuChild extends ActorChild {
// PUBLIC
constructor(global) {
+ super(global);
+
+ contextMenus.set(global, this);
+
this.target = null;
this.context = null;
- this.global = global;
- this.content = global.content;
Object.keys(messageListeners).forEach(key =>
global.addMessageListener(key, messageListeners[key].bind(this))
);
}
+ static getTarget(global, message, key) {
+ return contextMenus.get(global).getTarget(message, key);
+ }
+
/**
* Returns the event target of the context menu, using a locally stored
* reference if possible. If not, and aMessage.objects is defined,
* aMessage.objects[aKey] is returned. Otherwise null.
* @param {Object} aMessage Message with a objects property
* @param {String} aKey Key for the target on aMessage.objects
* @return {Object} Context menu target
*/
@@ -483,17 +493,17 @@ class ContextMenu {
referrer,
referrerPolicy
} = doc;
docLocation = docLocation && docLocation.spec;
let frameOuterWindowID = WebNavigationFrames.getFrameId(doc.defaultView);
let loginFillInfo = LoginManagerContent.getFieldContext(aEvent.composedTarget);
// The same-origin check will be done in nsContextMenu.openLinkInTab.
- let parentAllowsMixedContent = !!this.global.docShell.mixedContentChannel;
+ let parentAllowsMixedContent = !!this.docShell.mixedContentChannel;
// Get referrer attribute from clicked link and parse it
let referrerAttrValue =
Services.netUtils.parseAttributePolicyString(aEvent.composedTarget.
getAttribute("referrerpolicy"));
if (referrerAttrValue !== Ci.nsIHttpChannel.REFERRER_POLICY_UNSET) {
referrerPolicy = referrerAttrValue;
@@ -522,17 +532,17 @@ class ContextMenu {
try {
contentDisposition = props.get("content-disposition", Ci.nsISupportsCString).data;
} catch (e) {}
} catch (e) {}
}
let selectionInfo = BrowserUtils.getSelectionDetails(this.content);
- let loadContext = this.global.docShell.QueryInterface(Ci.nsILoadContext);
+ let loadContext = this.docShell.QueryInterface(Ci.nsILoadContext);
let userContextId = loadContext.originAttributes.userContextId;
let popupNodeSelectors = findAllCssSelectors(aEvent.composedTarget);
this._setContext(aEvent);
let context = this.context;
this.target = context.target;
let spellInfo = null;
@@ -546,24 +556,24 @@ class ContextMenu {
}
let isRemote = Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT;
if (isRemote) {
editFlags = SpellCheckHelper.isEditable(aEvent.composedTarget, this.content);
if (editFlags & SpellCheckHelper.SPELLCHECKABLE) {
- spellInfo = InlineSpellCheckerContent.initContextMenu(aEvent, editFlags, this.global);
+ spellInfo = InlineSpellCheckerContent.initContextMenu(aEvent, editFlags, this.mm);
}
// Set the event target first as the copy image command needs it to
// determine what was context-clicked on. Then, update the state of the
// commands on the context menu.
- this.global.docShell.contentViewer.QueryInterface(Ci.nsIContentViewerEdit)
- .setCommandNode(aEvent.composedTarget);
+ this.docShell.contentViewer.QueryInterface(Ci.nsIContentViewerEdit)
+ .setCommandNode(aEvent.composedTarget);
aEvent.composedTarget.ownerGlobal.updateCommands("contentcontextmenu");
customMenuItems = PageMenuChild.build(aEvent.composedTarget);
principal = doc.nodePrincipal;
}
let data = {
context,
@@ -584,21 +594,21 @@ class ContextMenu {
contentDisposition,
frameOuterWindowID,
popupNodeSelectors,
disableSetDesktopBg,
parentAllowsMixedContent,
};
if (isRemote) {
- this.global.sendAsyncMessage("contextmenu", data, {
+ this.mm.sendAsyncMessage("contextmenu", data, {
targetAsCPOW,
});
} else {
- let browser = this.global.docShell.chromeEventHandler;
+ let browser = this.docShell.chromeEventHandler;
let mainWin = browser.ownerGlobal;
data.documentURIObject = doc.documentURIObject;
data.disableSetDesktopBackground = data.disableSetDesktopBg;
delete data.disableSetDesktopBg;
data.context.targetAsCPOW = targetAsCPOW;
--- a/browser/actors/moz.build
+++ b/browser/actors/moz.build
@@ -6,10 +6,11 @@
with Files("PageStyleChild.jsm"):
BUG_COMPONENT = ("Firefox", "Menus")
FINAL_TARGET_FILES.actors += [
'AboutReaderChild.jsm',
'BrowserTabChild.jsm',
'ContentSearchChild.jsm',
+ 'ContextMenuChild.jsm',
'PageStyleChild.jsm',
]
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -22,21 +22,17 @@ XPCOMUtils.defineLazyModuleGetters(this,
ContentWebRTC: "resource:///modules/ContentWebRTC.jsm",
LoginFormFactory: "resource://gre/modules/LoginManagerContent.jsm",
InsecurePasswordUtils: "resource://gre/modules/InsecurePasswordUtils.jsm",
PluginContent: "resource:///modules/PluginContent.jsm",
FormSubmitObserver: "resource:///modules/FormSubmitObserver.jsm",
NetErrorContent: "resource:///modules/NetErrorContent.jsm",
PageMetadata: "resource://gre/modules/PageMetadata.jsm",
WebNavigationFrames: "resource://gre/modules/WebNavigationFrames.jsm",
- ContextMenu: "resource:///modules/ContextMenu.jsm",
-});
-
-XPCOMUtils.defineLazyProxy(this, "contextMenu", () => {
- return new ContextMenu(global);
+ ContextMenuChild: "resource:///modules/ContextMenuChild.jsm",
});
XPCOMUtils.defineLazyProxy(this, "ClickEventHandler", () => {
let tmp = {};
ChromeUtils.import("resource:///modules/ClickEventHandler.jsm", tmp);
return new tmp.ClickEventHandler(global);
});
@@ -55,26 +51,24 @@ XPCOMUtils.defineLazyProxy(this, "formSu
});
XPCOMUtils.defineLazyProxy(this, "PageInfoListener",
"resource:///modules/PageInfoListener.jsm");
XPCOMUtils.defineLazyProxy(this, "LightWeightThemeWebInstallListener",
"resource:///modules/LightWeightThemeWebInstallListener.jsm");
-Services.els.addSystemEventListener(global, "contextmenu", contextMenu, false);
-
Services.obs.addObserver(formSubmitObserver, "invalidformsubmit", true);
addMessageListener("PageInfo:getData", PageInfoListener);
// NOTE: Much of this logic is duplicated in BrowserCLH.js for Android.
addMessageListener("RemoteLogins:fillForm", function(message) {
// intercept if ContextMenu.jsm had sent a plain object for remote targets
- message.objects.inputElement = contextMenu.getTarget(message, "inputElement");
+ message.objects.inputElement = ContextMenuChild.getTarget(global, message, "inputElement");
LoginManagerContent.receiveMessage(message, content);
});
addEventListener("DOMFormHasPassword", function(event) {
LoginManagerContent.onDOMFormHasPassword(event, content);
let formLike = LoginFormFactory.createFromForm(event.originalTarget);
InsecurePasswordUtils.reportInsecurePasswords(formLike);
});
addEventListener("DOMInputPasswordAdded", function(event) {
@@ -264,23 +258,23 @@ var PageMetadataMessenger = {
init() {
addMessageListener("PageMetadata:GetPageData", this);
addMessageListener("PageMetadata:GetMicroformats", this);
this.init = null;
},
receiveMessage(message) {
switch (message.name) {
case "PageMetadata:GetPageData": {
- let target = contextMenu.getTarget(message);
+ let target = ContextMenuChild.getTarget(global, message);
let result = PageMetadata.getData(content.document, target);
sendAsyncMessage("PageMetadata:PageDataResult", result);
break;
}
case "PageMetadata:GetMicroformats": {
- let target = contextMenu.getTarget(message);
+ let target = ContextMenuChild.getTarget(global, message);
let result = PageMetadata.getMicroformats(content.document, target);
sendAsyncMessage("PageMetadata:MicroformatsResult", result);
break;
}
}
}
};
PageMetadataMessenger.init();
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -48,16 +48,25 @@ let ACTORS = {
"Browser:Reload",
"MixedContent:ReenableProtection",
"SwitchDocumentDirection",
"UpdateCharacterSet",
],
},
},
+ ContextMenu: {
+ child: {
+ module: "resource:///actors/ContextMenuChild.jsm",
+ events: {
+ "contextmenu": {mozSystemGroup: true},
+ },
+ },
+ },
+
ContentSearch: {
child: {
module: "resource:///actors/ContentSearchChild.jsm",
group: "browsers",
matches: ["about:home", "about:newtab", "about:welcome",
"chrome://mochitests/content/*"],
events: {
"ContentSearchClient": {capture: true, wantUntrusted: true},
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -138,17 +138,16 @@ EXTRA_JS_MODULES += [
'ClickEventHandler.jsm',
'ContentClick.jsm',
'ContentCrashHandlers.jsm',
'ContentLinkHandler.jsm',
'ContentMetaHandler.jsm',
'ContentObservers.js',
'ContentSearch.jsm',
'ContentWebRTC.jsm',
- 'ContextMenu.jsm',
'ExtensionsUI.jsm',
'Feeds.jsm',
'FormSubmitObserver.jsm',
'FormValidationHandler.jsm',
'HomePage.jsm',
'LaterRun.jsm',
'LightweightThemeChildHelper.jsm',
'LightWeightThemeWebInstallListener.jsm',