From ecbfe149126cd5c86784c67fdb1154c27e1ddb68 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Mon, 12 Dec 2022 23:41:22 +0000 Subject: [PATCH] Bug 1800149 - Part 1: Stop sending some values from a content process in nsContextMenu, r=Gijs,extension-reviewers,robwu Currently we are sending some values, such as principals, from the content process when creating a nsContextMenu. This information is already available in the parent process on WindowGlobalParent, so changes the code to fetch the values from there instead. Differential Revision: https://phabricator.services.mozilla.com/D161835 --- browser/actors/ContextMenuChild.sys.mjs | 51 +++++------------ browser/base/content/nsContextMenu.js | 55 +++++++++++-------- .../components/extensions/child/ext-menus.js | 4 +- 3 files changed, 48 insertions(+), 62 deletions(-) diff --git a/browser/actors/ContextMenuChild.sys.mjs b/browser/actors/ContextMenuChild.sys.mjs index 99c54a41ccb9..9071b16e0f17 100644 --- a/browser/actors/ContextMenuChild.sys.mjs +++ b/browser/actors/ContextMenuChild.sys.mjs @@ -20,7 +20,6 @@ ChromeUtils.defineESModuleGetters(lazy, { XPCOMUtils.defineLazyModuleGetters(lazy, { LoginManagerChild: "resource://gre/modules/LoginManagerChild.jsm", - WebNavigationFrames: "resource://gre/modules/WebNavigationFrames.jsm", }); let contextMenus = new WeakMap(); @@ -564,11 +563,8 @@ export class ContextMenuChild extends JSWindowActorChild { mozDocumentURIIfNotForErrorPages: docLocation, characterSet: charSet, baseURI, - cookieJarSettings, } = doc; docLocation = docLocation && docLocation.spec; - let frameID = lazy.WebNavigationFrames.getFrameId(doc.defaultView); - let frameBrowsingContextID = doc.defaultView.docShell.browsingContext.id; const loginManagerChild = lazy.LoginManagerChild.forWindow(doc.defaultView); const docState = loginManagerChild.stateForDocument(doc); const loginFillInfo = docState.getFieldContext(aEvent.composedTarget); @@ -614,8 +610,6 @@ export class ContextMenuChild extends JSWindowActorChild { let selectionInfo = lazy.SelectionUtils.getSelectionDetails( this.contentWindow ); - let loadContext = this.docShell.QueryInterface(Ci.nsILoadContext); - let userContextId = loadContext.originAttributes.userContextId; this._setContext(aEvent); let context = this.context; @@ -623,7 +617,6 @@ export class ContextMenuChild extends JSWindowActorChild { let spellInfo = null; let editFlags = null; - let principal = null; let referrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance( Ci.nsIReferrerInfo @@ -673,15 +666,11 @@ export class ContextMenuChild extends JSWindowActorChild { baseURI, referrerInfo, editFlags, - principal, contentType, docLocation, loginFillInfo, selectionInfo, - userContextId, contentDisposition, - frameID, - frameBrowsingContextID, disableSetDesktopBackground, }; @@ -697,19 +686,15 @@ export class ContextMenuChild extends JSWindowActorChild { ); } - Services.obs.notifyObservers( - { wrappedJSObject: data }, - "on-prepare-contextmenu" - ); - - data.principal = doc.nodePrincipal; - data.context.principal = context.principal; - data.storagePrincipal = doc.effectiveStoragePrincipal; - data.context.storagePrincipal = context.storagePrincipal; - - data.cookieJarSettings = lazy.E10SUtils.serializeCookieJarSettings( - cookieJarSettings - ); + // Notify observers (currently only webextensions) of the context menu being + // prepared, allowing them to set webExtContextData for us. + let prepareContextMenu = { + principal: doc.nodePrincipal, + setWebExtContextData(webExtContextData) { + data.webExtContextData = webExtContextData; + }, + }; + Services.obs.notifyObservers(prepareContextMenu, "on-prepare-contextmenu"); // In the event that the content is running in the parent process, we don't // actually want the contextmenu events to reach the parent - we'll dispatch @@ -899,21 +884,8 @@ export class ContextMenuChild extends JSWindowActorChild { context.target = node; context.targetIdentifier = lazy.ContentDOMReference.get(node); - context.principal = context.target.ownerDocument.nodePrincipal; - context.storagePrincipal = - context.target.ownerDocument.effectiveStoragePrincipal; context.csp = lazy.E10SUtils.serializeCSP(context.target.ownerDocument.csp); - context.frameID = lazy.WebNavigationFrames.getFrameId( - context.target.ownerGlobal - ); - - context.frameOuterWindowID = - context.target.ownerGlobal.docShell.outerWindowID; - - context.frameBrowsingContextID = - context.target.ownerGlobal.browsingContext.id; - // Check if we are in the PDF Viewer. context.inPDFViewer = context.target.ownerDocument.nodePrincipal.originNoSuffix == @@ -1191,7 +1163,10 @@ export class ContextMenuChild extends JSWindowActorChild { try { if (elem.download) { // Ignore download attribute on cross-origin links - context.principal.checkMayLoad(context.linkURI, true); + context.target.ownerDocument.nodePrincipal.checkMayLoad( + context.linkURI, + true + ); context.linkDownload = elem.download; } } catch (ex) {} diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js index 8397d36ac379..8d8bd37db3f5 100644 --- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -15,58 +15,68 @@ function openContextMenu(aMessage, aBrowser, aActor) { let data = aMessage.data; let browser = aBrowser; let actor = aActor; - let spellInfo = data.spellInfo; + let wgp = actor.manager; + + if (!wgp.isCurrentGlobal) { + // Don't display context menus for unloaded documents + return; + } + + // NOTE: We don't use `wgp.documentURI` here as we want to use the failed + // channel URI in the case we have loaded an error page. + let documentURIObject = wgp.browsingContext.currentURI; + let frameReferrerInfo = data.frameReferrerInfo; - let linkReferrerInfo = data.linkReferrerInfo; - let principal = data.principal; - let storagePrincipal = data.storagePrincipal; - - let documentURIObject = makeURI( - data.docLocation, - data.charSet, - makeURI(data.baseURI) - ); - if (frameReferrerInfo) { frameReferrerInfo = E10SUtils.deserializeReferrerInfo(frameReferrerInfo); } + let linkReferrerInfo = data.linkReferrerInfo; if (linkReferrerInfo) { linkReferrerInfo = E10SUtils.deserializeReferrerInfo(linkReferrerInfo); } + let frameID = nsContextMenu.WebNavigationFrames.getFrameId( + wgp.browsingContext + ); + nsContextMenu.contentData = { context: data.context, browser, actor, editFlags: data.editFlags, - spellInfo, - principal, - storagePrincipal, + spellInfo: data.spellInfo, + principal: wgp.documentPrincipal, + storagePrincipal: wgp.documentStoragePrincipal, documentURIObject, - docLocation: data.docLocation, + docLocation: documentURIObject.spec, charSet: data.charSet, referrerInfo: E10SUtils.deserializeReferrerInfo(data.referrerInfo), frameReferrerInfo, linkReferrerInfo, contentType: data.contentType, contentDisposition: data.contentDisposition, - frameID: data.frameID, - frameOuterWindowID: data.frameID, - frameBrowsingContext: BrowsingContext.get(data.frameBrowsingContextID), + frameID, + frameOuterWindowID: frameID, + frameBrowsingContext: wgp.browsingContext, selectionInfo: data.selectionInfo, disableSetDesktopBackground: data.disableSetDesktopBackground, loginFillInfo: data.loginFillInfo, - userContextId: data.userContextId, + userContextId: wgp.browsingContext.userContextId, webExtContextData: data.webExtContextData, - cookieJarSettings: E10SUtils.deserializeCookieJarSettings( - data.cookieJarSettings - ), + cookieJarSettings: wgp.cookieJarSettings, }; let popup = browser.ownerDocument.getElementById("contentAreaContextMenu"); let context = nsContextMenu.contentData.context; + // Fill in some values in the context from the WindowGlobalParent actor. + context.principal = wgp.documentPrincipal; + context.storagePrincipal = wgp.documentStoragePrincipal; + context.frameID = frameID; + context.frameOuterWindowID = wgp.outerWindowId; + context.frameBrowsingContextID = wgp.browsingContext.id; + // We don't have access to the original event here, as that happened in // another process. Therefore we synthesize a new MouseEvent to propagate the // inputSource to the subsequently triggered popupshowing event. @@ -2471,6 +2481,7 @@ ChromeUtils.defineESModuleGetters(nsContextMenu, { XPCOMUtils.defineLazyModuleGetters(nsContextMenu, { LoginManagerContextMenu: "resource://gre/modules/LoginManagerContextMenu.jsm", + WebNavigationFrames: "resource://gre/modules/WebNavigationFrames.jsm", }); XPCOMUtils.defineLazyPreferenceGetter( diff --git a/browser/components/extensions/child/ext-menus.js b/browser/components/extensions/child/ext-menus.js index 8a61df0a83d1..6c3b7ae492c8 100644 --- a/browser/components/extensions/child/ext-menus.js +++ b/browser/components/extensions/child/ext-menus.js @@ -252,8 +252,8 @@ this.menusInternal = class extends ExtensionAPI { pendingMenuEvent = null; Services.obs.removeObserver(this, "on-prepare-contextmenu"); subject = subject.wrappedJSObject; - if (context.principal.subsumes(subject.context.principal)) { - subject.webExtContextData = this.webExtContextData; + if (context.principal.subsumes(subject.principal)) { + subject.setWebExtContextData(this.webExtContextData); } }, run() {