Bug 1399068 - Send the context menu target node up to the parent as an explicit CPOW to fix login selection. r?felipe draft
authorMike Conley <mconley@mozilla.com>
Wed, 04 Oct 2017 14:29:09 -0400
changeset 675007 4782772b7a8bd106930674ee005ed1005bbd6c8a
parent 674178 11fe0a2895aab26c57bcfe61b3041d7837e954cd
child 734489 b140c3b28072d702016b9a629563bbf2b84c943e
push id83008
push usermconley@mozilla.com
push dateWed, 04 Oct 2017 18:31:41 +0000
reviewersfelipe
bugs1399068, 1360406
milestone58.0a1
Bug 1399068 - Send the context menu target node up to the parent as an explicit CPOW to fix login selection. r?felipe LoginManagerParent expects either a CPOW or a DOM node (in the non-e10s case) to be passed as the inputElement for LoginManagerParent.fillForm. In bug 1360406, we serialized the target in the content process so that the parent didn't have access to the CPOW anymore. This patch adds a targetAsCPOW property to the nsContextMenu solely for passing back and forth between the parent and content processes in order to refer to the target DOM node. MozReview-Commit-ID: IMwVK0Ewlhy
browser/base/content/nsContextMenu.js
browser/modules/ContextMenu.jsm
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -24,16 +24,23 @@ function setContextMenuContentData(data)
   gContextMenuContentData = data;
 }
 
 function openContextMenu(aMessage) {
   let data = aMessage.data;
   let browser = aMessage.target;
   let spellInfo = data.spellInfo;
 
+  // ContextMenu.jsm sends us the target as a CPOW only so that
+  // we can send that CPOW back down to the content process and
+  // have it resolve to a DOM node. The parent should not attempt
+  // to access any properties on this CPOW (in fact, doing so
+  // will throw an exception).
+  data.context.targetAsCPOW = aMessage.objects.targetAsCPOW;
+
   if (spellInfo) {
     spellInfo.target = aMessage.target.messageManager;
   }
 
   let documentURIObject = makeURI(data.docLocation,
                                   data.charSet,
                                   makeURI(data.baseURI));
   gContextMenuContentData = { context: data.context,
@@ -199,16 +206,17 @@ nsContextMenu.prototype = {
     this.onMozExtLink        = context.onMozExtLink;
     this.onNumeric           = context.onNumeric;
     this.onPassword          = context.onPassword;
     this.onSaveableLink      = context.onSaveableLink;
     this.onTextInput         = context.onTextInput;
     this.onVideo             = context.onVideo;
 
     this.target = this.isRemote ? context.target : document.popupNode;
+    this.targetAsCPOW = context.targetAsCPOW;
 
     this.principal = context.principal;
     this.frameOuterWindowID = context.frameOuterWindowID;
 
     this.inSyntheticDoc = context.inSyntheticDoc;
 
     // Everything after this isn't sent directly from ContextMenu
     this.ownerDoc = this.target.ownerDocument;
@@ -712,17 +720,17 @@ nsContextMenu.prototype = {
       fillMenu.setAttribute("label", fillMenu.getAttribute("label-login"));
       fillMenu.setAttribute("accesskey", fillMenu.getAttribute("accesskey-login"));
     }
 
     if (!showFill || disableFill) {
       return;
     }
     let documentURI = gContextMenuContentData.documentURIObject;
-    let fragment = LoginManagerContextMenu.addLoginsToMenu(this.target, this.browser, documentURI);
+    let fragment = LoginManagerContextMenu.addLoginsToMenu(this.targetAsCPOW, this.browser, documentURI);
 
     this.showItem("fill-login-no-logins", !fragment);
 
     if (!fragment) {
       return;
     }
     let popup = document.getElementById("fill-login-popup");
     let insertBeforeElement = document.getElementById("fill-login-no-logins");
--- a/browser/modules/ContextMenu.jsm
+++ b/browser/modules/ContextMenu.jsm
@@ -567,17 +567,18 @@ class ContextMenu {
     let context = this.context;
     this.target = context.target;
 
     let spellInfo = null;
     let editFlags = null;
     let principal = null;
     let customMenuItems = null;
 
-    if (context.target) {
+    let targetAsCPOW = context.target;
+    if (targetAsCPOW) {
       this._cleanContext();
     }
 
     let isRemote = Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT;
 
     if (isRemote) {
       editFlags = SpellCheckHelper.isEditable(aEvent.target, this.content);
 
@@ -616,25 +617,29 @@ class ContextMenu {
       contentDisposition,
       frameOuterWindowID,
       popupNodeSelectors,
       disableSetDesktopBg,
       parentAllowsMixedContent,
     };
 
     if (isRemote) {
-      this.global.sendAsyncMessage("contextmenu", data);
+      this.global.sendAsyncMessage("contextmenu", data, {
+        targetAsCPOW,
+      });
     } else {
       let browser = this.global.docShell.chromeEventHandler;
       let mainWin = browser.ownerGlobal;
 
       data.documentURIObject = doc.documentURIObject;
       data.disableSetDesktopBackground = data.disableSetDesktopBg;
       delete data.disableSetDesktopBg;
 
+      data.context.targetAsCPOW = targetAsCPOW;
+
       mainWin.setContextMenuContentData(data);
     }
   }
 
   /**
    * Some things are not serializable, so we either have to only send
    * their needed data or regenerate them in nsContextMenu.js
    * - target and target.ownerDocument