From f2caf19094aa246617ea2139a114fc663a83eb42 Mon Sep 17 00:00:00 2001 From: Tom Schuster Date: Wed, 15 Jun 2022 19:01:02 +0000 Subject: [PATCH] Bug 1738694 - Pass around hasValidUserGestureActivation and fromExternal when opening links from the UI or command-line. r=Gijs,edgar Differential Revision: https://phabricator.services.mozilla.com/D147515 --- browser/actors/ClickHandlerParent.jsm | 2 ++ browser/base/content/browser.js | 35 +++++++++++++++++-- browser/base/content/nsContextMenu.js | 1 + browser/base/content/utilityOverlay.js | 22 ++++++++---- browser/components/BrowserContentHandler.jsm | 7 +++- .../extensions/parent/ext-windows.js | 2 +- 6 files changed, 58 insertions(+), 11 deletions(-) diff --git a/browser/actors/ClickHandlerParent.jsm b/browser/actors/ClickHandlerParent.jsm index 5bf2ebaa5c65..9330ce5eeaac 100644 --- a/browser/actors/ClickHandlerParent.jsm +++ b/browser/actors/ClickHandlerParent.jsm @@ -115,6 +115,8 @@ class ClickHandlerParent extends JSWindowActorParent { csp: data.csp ? lazy.E10SUtils.deserializeCSP(data.csp) : null, frameID: data.frameID, openerBrowser: browser, + // The child ensures that untrusted events have a valid user activation. + hasValidUserGestureActivation: true, }; // The new tab/window must use the same userContextId. diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 7104ada10814..ce10a28e6225 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1508,11 +1508,13 @@ function _loadURI(browser, uri, params = {}) { userContextId, csp, remoteTypeOverride, + hasValidUserGestureActivation, } = params || {}; let loadFlags = params.loadFlags || params.flags || Ci.nsIWebNavigation.LOAD_FLAGS_NONE; - let hasValidUserGestureActivation = + hasValidUserGestureActivation ??= document.hasValidTransientUserGestureActivation; + if (!triggeringPrincipal) { throw new Error("Must load with a triggering Principal"); } @@ -2245,7 +2247,7 @@ var gBrowserInit = { }); } catch (e) {} } else if (window.arguments.length >= 3) { - // window.arguments[1]: unused (bug 871161) + // window.arguments[1]: extraOptions (nsIPropertyBag) // [2]: referrerInfo (nsIReferrerInfo) // [3]: postData (nsIInputStream) // [4]: allowThirdPartyFixup (bool) @@ -2261,6 +2263,26 @@ var gBrowserInit = { ? window.arguments[5] : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID; + let hasValidUserGestureActivation = undefined; + let fromExternal = undefined; + if (window.arguments[1]) { + if (!(window.arguments[1] instanceof Ci.nsIPropertyBag2)) { + throw new Error( + "window.arguments[1] must be null or Ci.nsIPropertyBag2!" + ); + } + + let extraOptions = window.arguments[1]; + if (extraOptions.hasKey("hasValidUserGestureActivation")) { + hasValidUserGestureActivation = extraOptions.getPropertyAsBool( + "hasValidUserGestureActivation" + ); + } + if (extraOptions.hasKey("fromExternal")) { + fromExternal = extraOptions.getPropertyAsBool("fromExternal"); + } + } + try { openLinkIn(uriToLoad, "current", { referrerInfo: window.arguments[2] || null, @@ -2277,6 +2299,8 @@ var gBrowserInit = { allowInheritPrincipal: window.arguments[9] !== false, csp: window.arguments[10], forceAboutBlankViewerInCurrent: !!window.arguments[6], + hasValidUserGestureActivation, + fromExternal, }); } catch (e) { Cu.reportError(e); @@ -6277,13 +6301,18 @@ nsBrowserAccess.prototype = { // Pass all params to openDialog to ensure that "url" isn't passed through // loadOneOrMoreURIs, which splits based on "|" try { + let extraOptions = Cc[ + "@mozilla.org/hash-property-bag;1" + ].createInstance(Ci.nsIWritablePropertyBag2); + extraOptions.setPropertyAsBool("fromExternal", isExternal); + openDialog( AppConstants.BROWSER_CHROME_URL, "_blank", features, // window.arguments url, - null, + extraOptions, null, null, null, diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js index a197cefb1f26..ee4dd39d3f21 100644 --- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -1309,6 +1309,7 @@ class nsContextMenu { triggeringPrincipal: this.principal, csp: this.csp, frameID: this.contentData.frameID, + hasValidUserGestureActivation: true, }; for (let p in extra) { params[p] = extra[p]; diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js index 40a1fa59d0e2..8afaccf7b5d3 100644 --- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -409,12 +409,17 @@ function openLinkIn(url, where, params) { ); wuri.data = url; - let charset = null; - if (aCharset) { - charset = Cc["@mozilla.org/supports-string;1"].createInstance( - Ci.nsISupportsString + let extraOptions = Cc["@mozilla.org/hash-property-bag;1"].createInstance( + Ci.nsIWritablePropertyBag2 + ); + if (params.hasValidUserGestureActivation !== undefined) { + extraOptions.setPropertyAsBool( + "hasValidUserGestureActivation", + params.hasValidUserGestureActivation ); - charset.data = "charset=" + aCharset; + } + if (params.fromExternal !== undefined) { + extraOptions.setPropertyAsBool("fromExternal", params.fromExternal); } var allowThirdPartyFixupSupports = Cc[ @@ -428,7 +433,7 @@ function openLinkIn(url, where, params) { userContextIdSupports.data = aUserContextId; sa.appendElement(wuri); - sa.appendElement(charset); + sa.appendElement(extraOptions); sa.appendElement(aReferrerInfo); sa.appendElement(aPostData); sa.appendElement(allowThirdPartyFixupSupports); @@ -579,6 +584,9 @@ function openLinkIn(url, where, params) { if (aForceAllowDataURI) { flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FORCE_ALLOW_DATA_URI; } + if (params.fromExternal) { + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL; + } let { URI_INHERITS_SECURITY_CONTEXT } = Ci.nsIProtocolHandler; if ( @@ -600,6 +608,7 @@ function openLinkIn(url, where, params) { referrerInfo: aReferrerInfo, postData: aPostData, userContextId: aUserContextId, + hasValidUserGestureActivation: params.hasValidUserGestureActivation, }); if (aResolveOnContentBrowserReady) { aResolveOnContentBrowserReady(targetBrowser); @@ -636,6 +645,7 @@ function openLinkIn(url, where, params) { csp: aCsp, focusUrlBar, openerBrowser: params.openerBrowser, + fromExternal: params.fromExternal, }); targetBrowser = tabUsedForLoad.linkedBrowser; diff --git a/browser/components/BrowserContentHandler.jsm b/browser/components/BrowserContentHandler.jsm index 3eab259898b8..47647e8e9126 100644 --- a/browser/components/BrowserContentHandler.jsm +++ b/browser/components/BrowserContentHandler.jsm @@ -250,12 +250,17 @@ function openBrowserWindow( }); args = [uriArray]; } else { + let extraOptions = Cc["@mozilla.org/hash-property-bag;1"].createInstance( + Ci.nsIWritablePropertyBag2 + ); + extraOptions.setPropertyAsBool("fromExternal", true); + // Always pass at least 3 arguments to avoid the "|"-splitting behavior, // ie. avoid the loadOneOrMoreURIs function. // Also, we need to pass the triggering principal. args = [ urlOrUrlList, - null, // charset + extraOptions, null, // refererInfo postData, undefined, // allowThirdPartyFixup; this would be `false` but that diff --git a/browser/components/extensions/parent/ext-windows.js b/browser/components/extensions/parent/ext-windows.js index 34b7b0fa6dce..9968a54232ef 100644 --- a/browser/components/extensions/parent/ext-windows.js +++ b/browser/components/extensions/parent/ext-windows.js @@ -260,7 +260,7 @@ this.windows = class extends ExtensionAPIPersistent { } } - args.appendElement(null); // unused + args.appendElement(null); // extraOptions args.appendElement(null); // referrerInfo args.appendElement(null); // postData args.appendElement(null); // allowThirdPartyFixup