Bug 1528695 - Part 2 : Use referrerInfo in openWindow, contextmenu and openLinkIn r=Gijs
authorThomas Nguyen <tnguyen@mozilla.com>
Fri, 15 Mar 2019 05:10:17 +0000
changeset 464120 4d62ab0e31fd6918ca95763914a8bdf41afe757a
parent 464119 e5b9c443c421e5c77177584bfd60099b9b7212b5
child 464121 5edbe9b1b82220b07ff446bd4a3b9ff2f7dda508
child 464122 a7d81b7bc493094223744d4010c87789cdf2977e
child 464140 9daec44d681e328c4827b23f16ad587c325fe20f
push id35709
push useropoprus@mozilla.com
push dateFri, 15 Mar 2019 09:39:17 +0000
treeherdermozilla-central@4d62ab0e31fd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1528695
milestone67.0a1
first release with
nightly linux32
4d62ab0e31fd / 67.0a1 / 20190315093917 / files
nightly linux64
4d62ab0e31fd / 67.0a1 / 20190315093917 / files
nightly mac
4d62ab0e31fd / 67.0a1 / 20190315093917 / files
nightly win32
4d62ab0e31fd / 67.0a1 / 20190315093917 / files
nightly win64
4d62ab0e31fd / 67.0a1 / 20190315093917 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1528695 - Part 2 : Use referrerInfo in openWindow, contextmenu and openLinkIn r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D21911
browser/actors/ClickHandlerChild.jsm
browser/base/content/browser.js
browser/base/content/nsContextMenu.js
browser/base/content/tabbrowser.js
browser/base/content/test/general/browser_relatedTabs.js
browser/base/content/utilityOverlay.js
browser/components/BrowserContentHandler.jsm
browser/components/contextualidentity/test/browser/browser_relatedTab.js
browser/components/contextualidentity/test/browser/browser_usercontextid_new_window.js
browser/components/extensions/parent/ext-windows.js
browser/modules/ContentClick.jsm
testing/mochitest/api.js
--- a/browser/actors/ClickHandlerChild.jsm
+++ b/browser/actors/ClickHandlerChild.jsm
@@ -51,39 +51,48 @@ class ClickHandlerChild extends ActorChi
     }
 
     // Bug 965637, query the CSP from the doc instead of the Principal
     let csp = ownerDoc.nodePrincipal.csp;
     if (csp) {
       csp = E10SUtils.serializeCSP(csp);
     }
 
+    let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
+                                              "nsIReferrerInfo",
+                                              "init");
+    let referrerInfo = new ReferrerInfo(
+      referrerPolicy,
+      !BrowserUtils.linkHasNoReferrer(node),
+      ownerDoc.documentURIObject);
+    referrerInfo = E10SUtils.serializeReferrerInfo(referrerInfo);
     let frameOuterWindowID = WebNavigationFrames.getFrameId(ownerDoc.defaultView);
 
     let json = { button: event.button, shiftKey: event.shiftKey,
                  ctrlKey: event.ctrlKey, metaKey: event.metaKey,
                  altKey: event.altKey, href: null, title: null,
-                 frameOuterWindowID, referrerPolicy,
+                 frameOuterWindowID,
                  triggeringPrincipal: principal,
                  csp,
+                 referrerInfo,
                  originAttributes: principal ? principal.originAttributes : {},
                  isContentWindowPrivate: PrivateBrowsingUtils.isContentWindowPrivate(ownerDoc.defaultView)};
 
     if (href) {
       try {
         BrowserUtils.urlSecurityCheck(href, principal);
       } catch (e) {
         return;
       }
 
       json.href = href;
       if (node) {
         json.title = node.getAttribute("title");
       }
-      json.noReferrer = BrowserUtils.linkHasNoReferrer(node);
+
 
       // Check if the link needs to be opened with mixed content allowed.
       // Only when the owner doc has |mixedContentChannel| and the same origin
       // should we allow mixed content.
       json.allowMixedContent = false;
       let docshell = ownerDoc.defaultView.docShell;
       if (this.mm.docShell.mixedContentChannel) {
         const sm = Services.scriptSecurityManager;
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -260,16 +260,21 @@ var gURLBarHandler = {
     }
   },
 };
 
 XPCOMUtils.defineLazyPreferenceGetter(gURLBarHandler, "quantumbar",
                                       "browser.urlbar.quantumbar", false,
                                       gURLBarHandler.handlePrefChange.bind(gURLBarHandler));
 
+XPCOMUtils.defineLazyGetter(this, "ReferrerInfo", () =>
+  Components.Constructor("@mozilla.org/referrer-info;1",
+                         "nsIReferrerInfo",
+                         "init"));
+
 // High priority notification bars shown at the top of the window.
 XPCOMUtils.defineLazyGetter(this, "gHighPriorityNotificationBox", () => {
   return new MozElements.NotificationBox(element => {
     element.classList.add("global-notificationbox");
     element.setAttribute("notificationside", "top");
     document.getElementById("appcontent").prepend(element);
   });
 });
@@ -1735,69 +1740,58 @@ var gBrowserInit = {
           gURLBar.removeAttribute("focused");
       });
     }
   },
 
   _handleURIToLoad() {
     this._callWithURIToLoad(uriToLoad => {
       if (!uriToLoad) {
-        // We don't check whether window.arguments[6] (userContextId) is set
+        // We don't check whether window.arguments[5] (userContextId) is set
         // because tabbrowser.js takes care of that for the initial tab.
         return;
       }
 
       // We don't check if uriToLoad is a XULElement because this case has
       // already been handled before first paint, and the argument cleared.
       if (Array.isArray(uriToLoad)) {
         // This function throws for certain malformed URIs, so use exception handling
         // so that we don't disrupt startup
         try {
           gBrowser.loadTabs(uriToLoad, {
             inBackground: false,
             replace: true,
             // See below for the semantics of window.arguments. Only the minimum is supported.
-            userContextId: window.arguments[6],
-            triggeringPrincipal: window.arguments[8] || Services.scriptSecurityManager.getSystemPrincipal(),
-            allowInheritPrincipal: window.arguments[9],
-            csp: window.arguments[10],
+            userContextId: window.arguments[5],
+            triggeringPrincipal: window.arguments[7] || Services.scriptSecurityManager.getSystemPrincipal(),
+            allowInheritPrincipal: window.arguments[8],
+            csp: window.arguments[9],
             fromExternal: true,
           });
         } catch (e) {}
       } else if (window.arguments.length >= 3) {
         // window.arguments[1]: unused (bug 871161)
-        //                 [2]: referrer (nsIURI | string)
+        //                 [2]: referrerInfo (nsIReferrerInfo)
         //                 [3]: postData (nsIInputStream)
         //                 [4]: allowThirdPartyFixup (bool)
-        //                 [5]: referrerPolicy (int)
-        //                 [6]: userContextId (int)
-        //                 [7]: originPrincipal (nsIPrincipal)
-        //                 [8]: triggeringPrincipal (nsIPrincipal)
-        //                 [9]: allowInheritPrincipal (bool)
-        //                [10]: csp (nsIContentSecurityPolicy)
-        let referrerURI = window.arguments[2];
-        if (typeof(referrerURI) == "string") {
-          try {
-            referrerURI = makeURI(referrerURI);
-          } catch (e) {
-            referrerURI = null;
-          }
-        }
-        let referrerPolicy = (window.arguments[5] != undefined ?
-            window.arguments[5] : Ci.nsIHttpChannel.REFERRER_POLICY_UNSET);
-        let userContextId = (window.arguments[6] != undefined ?
-            window.arguments[6] : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID);
-        loadURI(uriToLoad, referrerURI, window.arguments[3] || null,
-                window.arguments[4] || false, referrerPolicy, userContextId,
+        //                 [5]: userContextId (int)
+        //                 [6]: originPrincipal (nsIPrincipal)
+        //                 [7]: triggeringPrincipal (nsIPrincipal)
+        //                 [8]: allowInheritPrincipal (bool)
+        //                 [9]: csp (nsIContentSecurityPolicy)
+        let userContextId = (window.arguments[5] != undefined ?
+            window.arguments[5] : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID);
+        loadURI(uriToLoad, window.arguments[2] || null, window.arguments[3] || null,
+                window.arguments[4] || false, userContextId,
                 // pass the origin principal (if any) and force its use to create
                 // an initial about:blank viewer if present:
-                window.arguments[7], !!window.arguments[7], window.arguments[8],
+                window.arguments[6], !!window.arguments[6], window.arguments[7],
                 // TODO fix allowInheritPrincipal to default to false.
                 // Default to true unless explicitly set to false because of bug 1475201.
-                window.arguments[9] !== false, window.arguments[10]);
+                window.arguments[8] !== false, window.arguments[9]);
         window.focus();
       } else {
         // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
         // Such callers expect that window.arguments[0] is handled as a single URI.
         loadOneOrMoreURIs(uriToLoad, Services.scriptSecurityManager.getSystemPrincipal());
       }
     });
   },
@@ -2504,27 +2498,26 @@ function BrowserCloseTabOrWindow(event) 
   gBrowser.removeCurrentTab({animate: true});
 }
 
 function BrowserTryToCloseWindow() {
   if (WindowIsClosing())
     window.close(); // WindowIsClosing does all the necessary checks
 }
 
-function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy,
+function loadURI(uri, referrerInfo, postData, allowThirdPartyFixup,
                  userContextId, originPrincipal, forceAboutBlankViewerInCurrent,
                  triggeringPrincipal, allowInheritPrincipal = false, csp = null) {
   if (!triggeringPrincipal) {
     throw new Error("Must load with a triggering Principal");
   }
 
   try {
     openLinkIn(uri, "current",
-               { referrerURI: referrer,
-                 referrerPolicy,
+               { referrerInfo,
                  postData,
                  allowThirdPartyFixup,
                  userContextId,
                  originPrincipal,
                  triggeringPrincipal,
                  csp,
                  forceAboutBlankViewerInCurrent,
                  allowInheritPrincipal,
@@ -5538,17 +5531,17 @@ var TabsProgressListener = {
   },
 };
 
 function nsBrowserAccess() { }
 
 nsBrowserAccess.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIBrowserDOMWindow]),
 
-  _openURIInNewTab(aURI, aReferrer, aReferrerPolicy, aIsPrivate,
+  _openURIInNewTab(aURI, aReferrerInfo, aIsPrivate,
                    aIsExternal, aForceNotRemote = false,
                    aUserContextId = Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID,
                    aOpenerWindow = null, aOpenerBrowser = null,
                    aTriggeringPrincipal = null, aNextTabParentId = 0, aName = "", aCsp = null) {
     let win, needToFocusWin;
 
     // try the current window.  if we're in a popup, fall back on the most recent browser window
     if (window.toolbar.visible) {
@@ -5568,18 +5561,17 @@ nsBrowserAccess.prototype = {
       win.focus();
       return win.gBrowser.selectedBrowser;
     }
 
     let loadInBackground = Services.prefs.getBoolPref("browser.tabs.loadDivertedInBackground");
 
     let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : "about:blank", {
                                       triggeringPrincipal: aTriggeringPrincipal,
-                                      referrerURI: aReferrer,
-                                      referrerPolicy: aReferrerPolicy,
+                                      referrerInfo: aReferrerInfo,
                                       userContextId: aUserContextId,
                                       fromExternal: aIsExternal,
                                       inBackground: loadInBackground,
                                       forceNotRemote: aForceNotRemote,
                                       opener: aOpenerWindow,
                                       openerBrowser: aOpenerBrowser,
                                       nextTabParentId: aNextTabParentId,
                                       name: aName,
@@ -5633,20 +5625,20 @@ nsBrowserAccess.prototype = {
     if (aWhere == Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW) {
       if (isExternal &&
           Services.prefs.prefHasUserValue("browser.link.open_newwindow.override.external"))
         aWhere = Services.prefs.getIntPref("browser.link.open_newwindow.override.external");
       else
         aWhere = Services.prefs.getIntPref("browser.link.open_newwindow");
     }
 
-    let referrer = aOpener ? makeURI(aOpener.location.href) : null;
-    let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_UNSET;
+    let referrerInfo = new ReferrerInfo(Ci.nsIHttpChannel.REFERRER_POLICY_UNSET, true,
+      aOpener ? makeURI(aOpener.location.href) : null);
     if (aOpener && aOpener.document) {
-      referrerPolicy = aOpener.document.referrerPolicy;
+      referrerInfo.referrerPolicy = aOpener.document.referrerPolicy;
     }
     // Bug 965637, query the CSP from the doc instead of the Principal
     let csp = aTriggeringPrincipal.csp;
     let isPrivate = aOpener
                   ? PrivateBrowsingUtils.isContentWindowPrivate(aOpener)
                   : PrivateBrowsingUtils.isWindowPrivate(window);
 
     switch (aWhere) {
@@ -5658,34 +5650,34 @@ nsBrowserAccess.prototype = {
         if (isPrivate) {
           features += ",private";
         }
         // Pass all params to openDialog to ensure that "url" isn't passed through
         // loadOneOrMoreURIs, which splits based on "|"
         try {
           newWindow = openDialog(AppConstants.BROWSER_CHROME_URL, "_blank", features,
                       // window.arguments
-                      url, null, null, null, null, null, null, null, aTriggeringPrincipal);
+                      url, null, null, null, null, null, null, aTriggeringPrincipal);
         } catch (ex) {
           Cu.reportError(ex);
         }
         break;
       case Ci.nsIBrowserDOMWindow.OPEN_NEWTAB :
         // If we have an opener, that means that the caller is expecting access
         // to the nsIDOMWindow of the opened tab right away. For e10s windows,
         // this means forcing the newly opened browser to be non-remote so that
         // we can hand back the nsIDOMWindow. The XULBrowserWindow.shouldLoadURI
         // will do the job of shuttling off the newly opened browser to run in
         // the right process once it starts loading a URI.
         let forceNotRemote = !!aOpener;
         let userContextId = aOpener && aOpener.document
                               ? aOpener.document.nodePrincipal.originAttributes.userContextId
                               : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
         let openerWindow = (aFlags & Ci.nsIBrowserDOMWindow.OPEN_NO_OPENER) ? null : aOpener;
-        let browser = this._openURIInNewTab(aURI, referrer, referrerPolicy,
+        let browser = this._openURIInNewTab(aURI, referrerInfo,
                                             isPrivate, isExternal,
                                             forceNotRemote, userContextId,
                                             openerWindow, null, aTriggeringPrincipal,
                                             0, "", csp);
         if (browser)
           newWindow = browser.contentWindow;
         break;
       default : // OPEN_CURRENTWINDOW or an illegal value
@@ -5693,18 +5685,17 @@ nsBrowserAccess.prototype = {
         if (aURI) {
           let loadflags = isExternal ?
                             Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL :
                             Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
           gBrowser.loadURI(aURI.spec, {
             triggeringPrincipal: aTriggeringPrincipal,
             csp,
             flags: loadflags,
-            referrerURI: referrer,
-            referrerPolicy,
+            referrerInfo,
           });
         }
         if (!Services.prefs.getBoolPref("browser.tabs.loadDivertedInBackground"))
           window.focus();
     }
     return newWindow;
   },
 
@@ -5732,19 +5723,18 @@ nsBrowserAccess.prototype = {
 
     var isExternal = !!(aFlags & Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
 
     var userContextId = aParams.openerOriginAttributes &&
                         ("userContextId" in aParams.openerOriginAttributes)
                           ? aParams.openerOriginAttributes.userContextId
                           : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
 
-    let referrer = aParams.referrer ? makeURI(aParams.referrer) : null;
-    return this._openURIInNewTab(aURI, referrer,
-                                 aParams.referrerPolicy,
+    return this._openURIInNewTab(aURI,
+                                 aParams.referrerInfo,
                                  aParams.isPrivate,
                                  isExternal, false,
                                  userContextId, null, aParams.openerBrowser,
                                  aParams.triggeringPrincipal,
                                  aNextTabParentId, aName, aParams.csp);
   },
 
   isTabContentWindow(aWindow) {
@@ -6290,27 +6280,29 @@ function handleLinkClick(event, href, li
     let referrerAttrValue = Services.netUtils.parseAttributePolicyString(linkNode.
                             getAttribute("referrerpolicy"));
     if (referrerAttrValue != Ci.nsIHttpChannel.REFERRER_POLICY_UNSET) {
       referrerPolicy = referrerAttrValue;
     }
   }
 
   let frameOuterWindowID = WebNavigationFrames.getFrameId(doc.defaultView);
+  let referrerInfo = new ReferrerInfo(
+    referrerPolicy,
+    !BrowserUtils.linkHasNoReferrer(linkNode),
+    referrerURI);
 
   // Bug 965637, query the CSP from the doc instead of the Principal
   let csp = doc.nodePrincipal.csp;
 
   urlSecurityCheck(href, doc.nodePrincipal);
   let params = {
     charset: doc.characterSet,
     allowMixedContent: persistAllowMixedContentInChildTab,
-    referrerURI,
-    referrerPolicy,
-    noReferrer: BrowserUtils.linkHasNoReferrer(linkNode),
+    referrerInfo,
     originPrincipal: doc.nodePrincipal,
     triggeringPrincipal: doc.nodePrincipal,
     csp,
     frameOuterWindowID,
   };
 
   // The new tab/window must use the same userContextId
   if (doc.nodePrincipal.originAttributes.userContextId) {
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -40,29 +40,40 @@ function openContextMenu(aMessage) {
 
   if (spellInfo) {
     spellInfo.target = aMessage.target.messageManager;
   }
 
   let documentURIObject = makeURI(data.docLocation,
                                   data.charSet,
                                   makeURI(data.baseURI));
+  let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
+                                        "nsIReferrerInfo",
+                                        "init");
+  let referrerInfo = new ReferrerInfo(
+    data.referrerPolicy,
+    !data.context.linkHasNoReferrer,
+    documentURIObject);
+  let frameReferrerInfo = new ReferrerInfo(
+    data.referrerPolicy,
+    !data.context.linkHasNoReferrer,
+    data.referrer ? makeURI(data.referrer) : null);
   gContextMenuContentData = { context: data.context,
                               isRemote: data.isRemote,
                               popupNodeSelectors: data.popupNodeSelectors,
                               browser,
                               editFlags: data.editFlags,
                               spellInfo,
                               principal: data.principal,
                               customMenuItems: data.customMenuItems,
                               documentURIObject,
                               docLocation: data.docLocation,
                               charSet: data.charSet,
-                              referrer: data.referrer,
-                              referrerPolicy: data.referrerPolicy,
+                              referrerInfo,
+                              frameReferrerInfo,
                               contentType: data.contentType,
                               contentDisposition: data.contentDisposition,
                               frameOuterWindowID: data.frameOuterWindowID,
                               selectionInfo: data.selectionInfo,
                               disableSetDesktopBackground: data.disableSetDesktopBg,
                               loginFillInfo: data.loginFillInfo,
                               parentAllowsMixedContent: data.parentAllowsMixedContent,
                               userContextId: data.userContextId,
@@ -189,17 +200,16 @@ nsContextMenu.prototype = {
     this.inFrame             = context.inFrame;
     this.inSrcdocFrame       = context.inSrcdocFrame;
     this.inSyntheticDoc      = context.inSyntheticDoc;
     this.inTabBrowser        = context.inTabBrowser;
     this.inWebExtBrowser     = context.inWebExtBrowser;
 
     this.link                = context.link;
     this.linkDownload        = context.linkDownload;
-    this.linkHasNoReferrer   = context.linkHasNoReferrer;
     this.linkProtocol        = context.linkProtocol;
     this.linkTextStr         = context.linkTextStr;
     this.linkURL             = context.linkURL;
     this.linkURI             = this.getLinkURI(); // can't send; regenerate
 
     this.onAudio             = context.onAudio;
     this.onCanvas            = context.onCanvas;
     this.onCompletedImage    = context.onCompletedImage;
@@ -776,37 +786,37 @@ nsContextMenu.prototype = {
     return DevToolsShim.inspectA11Y(gBrowser.selectedTab, this.targetSelectors);
   },
 
   _openLinkInParameters(extra) {
     let params = { charset: gContextMenuContentData.charSet,
                    originPrincipal: this.principal,
                    triggeringPrincipal: this.principal,
                    csp: this.csp,
-                   referrerURI: gContextMenuContentData.documentURIObject,
-                   referrerPolicy: gContextMenuContentData.referrerPolicy,
-                   frameOuterWindowID: gContextMenuContentData.frameOuterWindowID,
-                   noReferrer: this.linkHasNoReferrer || this.onPlainTextLink };
+                   frameOuterWindowID: gContextMenuContentData.frameOuterWindowID};
     for (let p in extra) {
       params[p] = extra[p];
     }
 
     if (!this.isRemote) {
       // Propagate the frameOuterWindowID value saved when
       // the context menu has been opened.
       params.frameOuterWindowID = this.frameOuterWindowID;
     }
 
+    let referrerInfo = gContextMenuContentData.referrerInfo;
     // If we want to change userContextId, we must be sure that we don't
     // propagate the referrer.
-    if ("userContextId" in params &&
-        params.userContextId != gContextMenuContentData.userContextId) {
-      params.noReferrer = true;
+    if (("userContextId" in params &&
+        params.userContextId != gContextMenuContentData.userContextId) ||
+      this.onPlainTextLink) {
+      referrerInfo.sendReferrer = false;
     }
 
+    params.referrerInfo = referrerInfo;
     return params;
   },
 
   // Open linked-to URL in a new window.
   openLink() {
     openLinkIn(this.linkURL, "window", this._openLinkInParameters());
   },
 
@@ -845,47 +855,44 @@ nsContextMenu.prototype = {
 
   // open URL in current tab
   openLinkInCurrent() {
     openLinkIn(this.linkURL, "current", this._openLinkInParameters());
   },
 
   // Open frame in a new tab.
   openFrameInTab() {
-    let referrer = gContextMenuContentData.referrer;
     openLinkIn(gContextMenuContentData.docLocation, "tab",
                { charset: gContextMenuContentData.charSet,
                  triggeringPrincipal: this.browser.contentPrincipal,
-                 referrerURI: referrer ? makeURI(referrer) : null });
+                 referrerInfo: gContextMenuContentData.frameReferrerInfo });
   },
 
   // Reload clicked-in frame.
   reloadFrame(aEvent) {
     let forceReload = aEvent.shiftKey;
     this.browser.messageManager.sendAsyncMessage("ContextMenu:ReloadFrame",
                                                  null, { target: this.target, forceReload });
   },
 
   // Open clicked-in frame in its own window.
   openFrame() {
-    let referrer = gContextMenuContentData.referrer;
     openLinkIn(gContextMenuContentData.docLocation, "window",
                { charset: gContextMenuContentData.charSet,
                  triggeringPrincipal: this.browser.contentPrincipal,
-                 referrerURI: referrer ? makeURI(referrer) : null });
+                 referrerInfo: gContextMenuContentData.frameReferrerInfo });
   },
 
   // Open clicked-in frame in the same window.
   showOnlyThisFrame() {
     urlSecurityCheck(gContextMenuContentData.docLocation,
                      this.browser.contentPrincipal,
                      Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
-    let referrer = gContextMenuContentData.referrer;
     openWebLinkIn(gContextMenuContentData.docLocation, "current", {
-      referrerURI: referrer ? makeURI(referrer) : null,
+      referrerInfo: gContextMenuContentData.frameReferrerInfo,
       triggeringPrincipal: this.browser.contentPrincipal,
     });
   },
 
   // View Partial Source
   viewPartialSource() {
     let {browser} = this;
     let openSelectionFn = function() {
@@ -928,17 +935,17 @@ nsContextMenu.prototype = {
     BrowserPageInfo(gContextMenuContentData.docLocation, "mediaTab",
                     this.imageInfo, null, this.browser);
   },
 
   viewImageDesc(e) {
     urlSecurityCheck(this.imageDescURL,
                      this.principal,
                      Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
-    openUILink(this.imageDescURL, e, { referrerURI: gContextMenuContentData.documentURIObject,
+    openUILink(this.imageDescURL, e, { referrerInfo: gContextMenuContentData.referrerInfo,
                                        triggeringPrincipal: this.principal,
     });
   },
 
   viewFrameInfo() {
     BrowserPageInfo(gContextMenuContentData.docLocation, null, null,
                     this.frameOuterWindowID, this.browser);
   },
@@ -962,28 +969,28 @@ nsContextMenu.prototype = {
         resolve(message.data.blobURL);
       };
       mm.addMessageListener("ContextMenu:Canvas:ToBlobURL:Result", onMessage);
     });
   },
 
   // Change current window to the URL of the image, video, or audio.
   viewMedia(e) {
-    let referrerURI = gContextMenuContentData.documentURIObject;
+    let referrerInfo = gContextMenuContentData.referrerInfo;
     let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
     if (this.onCanvas) {
       this._canvasToBlobURL(this.target).then(function(blobURL) {
-        openUILink(blobURL, e, { referrerURI,
+        openUILink(blobURL, e, { referrerInfo,
                                  triggeringPrincipal: systemPrincipal});
       }, Cu.reportError);
     } else {
       urlSecurityCheck(this.mediaURL,
                        this.principal,
                        Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
-      openUILink(this.mediaURL, e, { referrerURI,
+      openUILink(this.mediaURL, e, { referrerInfo,
                                      forceAllowDataURI: true,
                                      triggeringPrincipal: this.principal,
       });
     }
   },
 
   saveVideoFrameAsImage() {
     let mm = this.browser.messageManager;
@@ -1030,17 +1037,17 @@ nsContextMenu.prototype = {
   },
 
   // Change current window to the URL of the background image.
   viewBGImage(e) {
     urlSecurityCheck(this.bgImageURL,
                      this.principal,
                      Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
 
-    openUILink(this.bgImageURL, e, { referrerURI: gContextMenuContentData.documentURIObject,
+    openUILink(this.bgImageURL, e, { referrerInfo: gContextMenuContentData.referrerInfo,
                                      triggeringPrincipal: this.principal,
     });
   },
 
   setDesktopBackground() {
     let mm = this.browser.messageManager;
 
     mm.sendAsyncMessage("ContextMenu:SetAsDesktopBackground", null,
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -277,17 +277,17 @@ window._gBrowser = {
 
   get selectedBrowser() {
     return this._selectedBrowser;
   },
 
   _setupInitialBrowserAndTab() {
     // See browser.js for the meaning of window.arguments.
     // Bug 1485961 covers making this more sane.
-    let userContextId = window.arguments && window.arguments[6];
+    let userContextId = window.arguments && window.arguments[5];
 
     let tabArgument = gBrowserInit.getTabToAdopt();
 
     // We only need sameProcessAsFrameLoader in the case where we're passed a tab
     let sameProcessAsFrameLoader;
     // If we have a tab argument with browser, we use its remoteType. Otherwise,
     // if e10s is disabled or there's a parent process opener (e.g. parent
     // process about: page) for the content tab, we use a parent
@@ -1381,56 +1381,53 @@ window._gBrowser = {
 
     if (aTab.selected) {
       this.updateTitlebar();
     }
 
     return true;
   },
 
-  loadOneTab(aURI, aReferrerURI, aCharset, aPostData, aLoadInBackground, aAllowThirdPartyFixup) {
+  loadOneTab(aURI, aReferrerInfoOrParams, aCharset, aPostData, aLoadInBackground, aAllowThirdPartyFixup) {
     var aTriggeringPrincipal;
-    var aReferrerPolicy;
+    var aReferrerInfo;
     var aFromExternal;
     var aRelatedToCurrent;
     var aAllowInheritPrincipal;
     var aAllowMixedContent;
     var aSkipAnimation;
     var aForceNotRemote;
     var aPreferredRemoteType;
-    var aNoReferrer;
     var aUserContextId;
     var aSameProcessAsFrameLoader;
     var aOriginPrincipal;
     var aOpener;
     var aOpenerBrowser;
     var aCreateLazyBrowser;
     var aNextTabParentId;
     var aFocusUrlBar;
     var aName;
     var aCsp;
     if (arguments.length == 2 &&
         typeof arguments[1] == "object" &&
         !(arguments[1] instanceof Ci.nsIURI)) {
       let params = arguments[1];
       aTriggeringPrincipal = params.triggeringPrincipal;
-      aReferrerURI = params.referrerURI;
-      aReferrerPolicy = params.referrerPolicy;
+      aReferrerInfo = params.referrerInfo;
       aCharset = params.charset;
       aPostData = params.postData;
       aLoadInBackground = params.inBackground;
       aAllowThirdPartyFixup = params.allowThirdPartyFixup;
       aFromExternal = params.fromExternal;
       aRelatedToCurrent = params.relatedToCurrent;
       aAllowInheritPrincipal = !!params.allowInheritPrincipal;
       aAllowMixedContent = params.allowMixedContent;
       aSkipAnimation = params.skipAnimation;
       aForceNotRemote = params.forceNotRemote;
       aPreferredRemoteType = params.preferredRemoteType;
-      aNoReferrer = params.noReferrer;
       aUserContextId = params.userContextId;
       aSameProcessAsFrameLoader = params.sameProcessAsFrameLoader;
       aOriginPrincipal = params.originPrincipal;
       aOpener = params.opener;
       aOpenerBrowser = params.openerBrowser;
       aCreateLazyBrowser = params.createLazyBrowser;
       aNextTabParentId = params.nextTabParentId;
       aFocusUrlBar = params.focusUrlBar;
@@ -1444,31 +1441,29 @@ window._gBrowser = {
     }
 
     var bgLoad = (aLoadInBackground != null) ? aLoadInBackground :
       Services.prefs.getBoolPref("browser.tabs.loadInBackground");
     var owner = bgLoad ? null : this.selectedTab;
 
     var tab = this.addTab(aURI, {
       triggeringPrincipal: aTriggeringPrincipal,
-      referrerURI: aReferrerURI,
-      referrerPolicy: aReferrerPolicy,
+      referrerInfo: aReferrerInfo,
       charset: aCharset,
       postData: aPostData,
       ownerTab: owner,
       allowInheritPrincipal: aAllowInheritPrincipal,
       allowThirdPartyFixup: aAllowThirdPartyFixup,
       fromExternal: aFromExternal,
       relatedToCurrent: aRelatedToCurrent,
       skipAnimation: aSkipAnimation,
       allowMixedContent: aAllowMixedContent,
       forceNotRemote: aForceNotRemote,
       createLazyBrowser: aCreateLazyBrowser,
       preferredRemoteType: aPreferredRemoteType,
-      noReferrer: aNoReferrer,
       userContextId: aUserContextId,
       originPrincipal: aOriginPrincipal,
       sameProcessAsFrameLoader: aSameProcessAsFrameLoader,
       opener: aOpener,
       openerBrowser: aOpenerBrowser,
       nextTabParentId: aNextTabParentId,
       focusUrlBar: aFocusUrlBar,
       name: aName,
@@ -2339,26 +2334,24 @@ window._gBrowser = {
     focusUrlBar,
     forceNotRemote,
     fromExternal,
     index,
     lazyTabTitle,
     name,
     nextTabParentId,
     noInitialLabel,
-    noReferrer,
     opener,
     openerBrowser,
     originPrincipal,
     ownerTab,
     pinned,
     postData,
     preferredRemoteType,
-    referrerPolicy,
-    referrerURI,
+    referrerInfo,
     relatedToCurrent,
     sameProcessAsFrameLoader,
     skipAnimation,
     skipBackgroundNotify,
     triggeringPrincipal,
     userContextId,
     recordExecution,
     replayExecution,
@@ -2380,23 +2373,23 @@ window._gBrowser = {
     // determining positioning, and inherited attributes such as the
     // user context ID.
     //
     // If we have a browser opener (which is usually the browser
     // element from a remote window.open() call), use that.
     //
     // Otherwise, if the tab is related to the current tab (e.g.,
     // because it was opened by a link click), use the selected tab as
-    // the owner. If referrerURI is set, and we don't have an
+    // the owner. If referrerInfo is set, and we don't have an
     // explicit relatedToCurrent arg, we assume that the tab is
     // related to the current tab, since referrerURI is null or
     // undefined if the tab is opened from an external application or
     // bookmark (i.e. somewhere other than an existing tab).
     if (relatedToCurrent == null) {
-      relatedToCurrent = !!referrerURI;
+      relatedToCurrent = !!(referrerInfo && referrerInfo.originalReferrer);
     }
     let openerTab = ((openerBrowser && this.getTabForBrowser(openerBrowser)) ||
       (relatedToCurrent && this.selectedTab));
 
     var t = document.createXULElement("tab");
 
     t.openerTab = openerTab;
 
@@ -2532,19 +2525,21 @@ window._gBrowser = {
       // opener, use the opener's remote type.
       if (!preferredRemoteType && openerBrowser) {
         preferredRemoteType = openerBrowser.remoteType;
       }
 
       // If URI is about:blank and we don't have a preferred remote type,
       // then we need to use the referrer, if we have one, to get the
       // correct remote type for the new tab.
-      if (uriIsAboutBlank && !preferredRemoteType && referrerURI) {
+      if (uriIsAboutBlank && !preferredRemoteType && referrerInfo &&
+          referrerInfo.originalReferrer) {
         preferredRemoteType =
-          E10SUtils.getRemoteTypeForURI(referrerURI.spec, gMultiProcessBrowser);
+          E10SUtils.getRemoteTypeForURI(referrerInfo.originalReferrer.spec,
+                                        gMultiProcessBrowser);
       }
 
       let remoteType =
         forceNotRemote ? E10SUtils.NOT_REMOTE :
         E10SUtils.getRemoteTypeForURI(aURI, gMultiProcessBrowser,
           preferredRemoteType);
 
       // If we open a new tab with the newtab URL in the default
@@ -2662,26 +2657,21 @@ window._gBrowser = {
         flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL;
       }
       if (allowMixedContent) {
         flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT;
       }
       if (!allowInheritPrincipal) {
         flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
       }
-
-      let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
-                                                "nsIReferrerInfo",
-                                                "init");
       try {
         b.loadURI(aURI, {
           flags,
           triggeringPrincipal,
-          referrerInfo: new ReferrerInfo(
-            referrerPolicy, !noReferrer, referrerURI),
+          referrerInfo,
           charset,
           postData,
           csp,
         });
       } catch (ex) {
         Cu.reportError(ex);
       }
     }
--- a/browser/base/content/test/general/browser_relatedTabs.js
+++ b/browser/base/content/test/general/browser_relatedTabs.js
@@ -5,18 +5,24 @@
 add_task(async function() {
   is(gBrowser.tabs.length, 1, "one tab is open initially");
 
   // Add several new tabs in sequence, interrupted by selecting a
   // different tab, moving a tab around and closing a tab,
   // returning a list of opened tabs for verifying the expected order.
   // The new tab behaviour is documented in bug 465673
   let tabs = [];
+  let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
+                                            "nsIReferrerInfo",
+                                            "init");
+
   function addTab(aURL, aReferrer) {
-    let tab = BrowserTestUtils.addTab(gBrowser, aURL, {referrerURI: aReferrer});
+    let referrerInfo = new ReferrerInfo(
+      Ci.nsIHttpChannel.REFERRER_POLICY_UNSET, true, aReferrer);
+    let tab = BrowserTestUtils.addTab(gBrowser, aURL, { referrerInfo });
     tabs.push(tab);
     return BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   }
 
   await addTab("http://mochi.test:8888/#0");
   gBrowser.selectedTab = tabs[0];
   await addTab("http://mochi.test:8888/#1");
   await addTab("http://mochi.test:8888/#2", gBrowser.currentURI);
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -97,37 +97,36 @@ function doGetProtocolFlags(aURI) {
  *
  * @param url {string}
  * @param event {Event | Object} Event or JSON object representing an Event
  * @param {Boolean | Object} aIgnoreButton
  * @param {Boolean} aIgnoreButton
  * @param {Boolean} aIgnoreAlt
  * @param {Boolean} aAllowThirdPartyFixup
  * @param {Object} aPostData
- * @param {nsIURI} aReferrerURI
+ * @param {Object} aReferrerInfo
  */
 function openUILink(url, event, aIgnoreButton, aIgnoreAlt, aAllowThirdPartyFixup,
-                    aPostData, aReferrerURI) {
+                    aPostData, aReferrerInfo) {
   event = getRootEvent(event);
   let params;
 
   if (aIgnoreButton && typeof aIgnoreButton == "object") {
     params = aIgnoreButton;
 
     // don't forward "ignoreButton" and "ignoreAlt" to openUILinkIn
     aIgnoreButton = params.ignoreButton;
     aIgnoreAlt = params.ignoreAlt;
     delete params.ignoreButton;
     delete params.ignoreAlt;
   } else {
     params = {
       allowThirdPartyFixup: aAllowThirdPartyFixup,
       postData: aPostData,
-      referrerURI: aReferrerURI,
-      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
+      referrerInfo: aReferrerInfo,
       initiatingDoc: event ? event.target.ownerDocument : null,
     };
   }
 
   if (!params.triggeringPrincipal) {
     throw new Error("Required argument triggeringPrincipal missing within openUILink");
   }
 
@@ -275,25 +274,25 @@ function openWebLinkIn(url, where, param
  * allowThirdPartyFixup controls whether third party services such as Google's
  * I Feel Lucky are allowed to interpret this URL. This parameter may be
  * undefined, which is treated as false.
  *
  * Instead of aAllowThirdPartyFixup, you may also pass an object with any of
  * these properties:
  *   allowThirdPartyFixup (boolean)
  *   postData             (nsIInputStream)
- *   referrerURI          (nsIURI)
+ *   referrerInfo         (nsIReferrerInfo)
  *   relatedToCurrent     (boolean)
  *   skipTabAnimation     (boolean)
  *   allowPinnedTabHostChange (boolean)
  *   allowPopups          (boolean)
  *   userContextId        (unsigned int)
  *   targetBrowser        (XUL browser)
  */
-function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI) {
+function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerInfo) {
   var params;
 
   if (arguments.length == 3 && typeof arguments[2] == "object") {
     params = aAllowThirdPartyFixup;
   }
   if (!params || !params.triggeringPrincipal) {
     throw new Error("Required argument triggeringPrincipal missing within openUILinkIn");
   }
@@ -302,62 +301,63 @@ function openUILinkIn(url, where, aAllow
 
   openLinkIn(url, where, params);
 }
 
 /* eslint-disable complexity */
 function openLinkIn(url, where, params) {
   if (!where || !url)
     return;
+  let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
+                                            "nsIReferrerInfo",
+                                            "init");
 
   var aFromChrome           = params.fromChrome;
   var aAllowThirdPartyFixup = params.allowThirdPartyFixup;
   var aPostData             = params.postData;
   var aCharset              = params.charset;
-  var aReferrerURI          = params.referrerURI;
-  var aReferrerPolicy       = ("referrerPolicy" in params ?
-      params.referrerPolicy : Ci.nsIHttpChannel.REFERRER_POLICY_UNSET);
+  var aReferrerInfo       = ("referrerInfo" in params)
+    ? params.referrerInfo
+    : new ReferrerInfo(Ci.nsIHttpChannel.REFERRER_POLICY_UNSET, true, null);
   var aRelatedToCurrent     = params.relatedToCurrent;
   var aAllowInheritPrincipal = !!params.allowInheritPrincipal;
   var aAllowMixedContent    = params.allowMixedContent;
   var aForceAllowDataURI    = params.forceAllowDataURI;
   var aInBackground         = params.inBackground;
   var aInitiatingDoc        = params.initiatingDoc;
   var aIsPrivate            = params.private;
   var aSkipTabAnimation     = params.skipTabAnimation;
   var aAllowPinnedTabHostChange = !!params.allowPinnedTabHostChange;
-  var aNoReferrer           = params.noReferrer;
   var aAllowPopups          = !!params.allowPopups;
   var aUserContextId        = params.userContextId;
   var aIndicateErrorPageLoad = params.indicateErrorPageLoad;
   var aPrincipal            = params.originPrincipal;
   var aTriggeringPrincipal  = params.triggeringPrincipal;
   var aCsp                  = params.csp;
   var aForceAboutBlankViewerInCurrent =
       params.forceAboutBlankViewerInCurrent;
   var aResolveOnNewTabCreated = params.resolveOnNewTabCreated;
 
   if (!aTriggeringPrincipal) {
     throw new Error("Must load with a triggering Principal");
   }
 
   if (where == "save") {
     // TODO(1073187): propagate referrerPolicy.
-
     // ContentClick.jsm passes isContentWindowPrivate for saveURL instead of passing a CPOW initiatingDoc
     if ("isContentWindowPrivate" in params) {
-      saveURL(url, null, null, true, true, aNoReferrer ? null : aReferrerURI,
+      saveURL(url, null, null, true, true, aReferrerInfo.sendReferrer ? aReferrerInfo.originalReferrer : null,
               null, params.isContentWindowPrivate, aPrincipal);
     } else {
       if (!aInitiatingDoc) {
         Cu.reportError("openUILink/openLinkIn was called with " +
           "where == 'save' but without initiatingDoc.  See bug 814264.");
         return;
       }
-      saveURL(url, null, null, true, true, aNoReferrer ? null : aReferrerURI, aInitiatingDoc);
+      saveURL(url, null, null, true, true, aReferrerInfo.sendReferrer ? aReferrerInfo.originalReferrer : null, aInitiatingDoc);
     }
     return;
   }
 
   // Establish which window we'll load the link in.
   let w;
   if (where == "current" && params.targetBrowser) {
     w = params.targetBrowser.ownerGlobal;
@@ -391,17 +391,17 @@ function openLinkIn(url, where, params) 
   aTriggeringPrincipal = useOAForPrincipal(aTriggeringPrincipal);
 
   if (!w || where == "window") {
     let features = "chrome,dialog=no,all";
     if (aIsPrivate) {
       features += ",private";
       // To prevent regular browsing data from leaking to private browsing sites,
       // strip the referrer when opening a new private window. (See Bug: 1409226)
-      aNoReferrer = true;
+      aReferrerInfo.sendReferrer = false;
     }
 
     // This propagates to window.arguments.
     var sa = Cc["@mozilla.org/array;1"].
              createInstance(Ci.nsIMutableArray);
 
     var wuri = Cc["@mozilla.org/supports-string;1"].
                createInstance(Ci.nsISupportsString);
@@ -413,37 +413,25 @@ function openLinkIn(url, where, params) 
                   .createInstance(Ci.nsISupportsString);
       charset.data = "charset=" + aCharset;
     }
 
     var allowThirdPartyFixupSupports = Cc["@mozilla.org/supports-PRBool;1"].
                                        createInstance(Ci.nsISupportsPRBool);
     allowThirdPartyFixupSupports.data = aAllowThirdPartyFixup;
 
-    var referrerURISupports = null;
-    if (aReferrerURI && !aNoReferrer) {
-      referrerURISupports = Cc["@mozilla.org/supports-string;1"].
-                            createInstance(Ci.nsISupportsString);
-      referrerURISupports.data = aReferrerURI.spec;
-    }
-
-    var referrerPolicySupports = Cc["@mozilla.org/supports-PRUint32;1"].
-                                 createInstance(Ci.nsISupportsPRUint32);
-    referrerPolicySupports.data = aReferrerPolicy;
-
     var userContextIdSupports = Cc["@mozilla.org/supports-PRUint32;1"].
                                  createInstance(Ci.nsISupportsPRUint32);
     userContextIdSupports.data = aUserContextId;
 
     sa.appendElement(wuri);
     sa.appendElement(charset);
-    sa.appendElement(referrerURISupports);
+    sa.appendElement(aReferrerInfo);
     sa.appendElement(aPostData);
     sa.appendElement(allowThirdPartyFixupSupports);
-    sa.appendElement(referrerPolicySupports);
     sa.appendElement(userContextIdSupports);
     sa.appendElement(aPrincipal);
     sa.appendElement(aTriggeringPrincipal);
     sa.appendElement(null); // allowInheritPrincipal
     sa.appendElement(aCsp);
 
     const sourceWindow = (w || window);
     let win;
@@ -553,25 +541,21 @@ function openLinkIn(url, where, params) 
     // start a new recording.
     if (targetBrowser.hasAttribute("recordExecution") &&
         targetBrowser.currentURI.spec != "about:blank") {
       w.gBrowser.updateBrowserRemoteness(targetBrowser,
                                          { recordExecution: "*", newFrameloader: true,
                                            remoteType: E10SUtils.DEFAULT_REMOTE_TYPE });
     }
 
-    let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
-                                              "nsIReferrerInfo",
-                                              "init");
     targetBrowser.loadURI(url, {
       triggeringPrincipal: aTriggeringPrincipal,
       csp: aCsp,
-      referrerInfo: new ReferrerInfo(
-        aReferrerPolicy, !aNoReferrer, aReferrerURI),
       flags,
+      referrerInfo: aReferrerInfo,
       postData: aPostData,
       userContextId: aUserContextId,
     });
 
     // Don't focus the content area if focus is in the address bar and we're
     // loading the New Tab page.
     focusUrlBar = w.document.activeElement == w.gURLBar.inputField &&
                   w.isBlankPageURL(url);
@@ -579,26 +563,24 @@ function openLinkIn(url, where, params) 
   case "tabshifted":
     loadInBackground = !loadInBackground;
     // fall through
   case "tab":
     focusUrlBar = !loadInBackground && w.isBlankPageURL(url)
       && !aboutNewTabService.willNotifyUser;
 
     let tabUsedForLoad = w.gBrowser.loadOneTab(url, {
-      referrerURI: aReferrerURI,
-      referrerPolicy: aReferrerPolicy,
+      referrerInfo: aReferrerInfo,
       charset: aCharset,
       postData: aPostData,
       inBackground: loadInBackground,
       allowThirdPartyFixup: aAllowThirdPartyFixup,
       relatedToCurrent: aRelatedToCurrent,
       skipAnimation: aSkipTabAnimation,
       allowMixedContent: aAllowMixedContent,
-      noReferrer: aNoReferrer,
       userContextId: aUserContextId,
       originPrincipal: aPrincipal,
       triggeringPrincipal: aTriggeringPrincipal,
       allowInheritPrincipal: aAllowInheritPrincipal,
       csp: aCsp,
       focusUrlBar,
     });
     targetBrowser = tabUsedForLoad.linkedBrowser;
--- a/browser/components/BrowserContentHandler.jsm
+++ b/browser/components/BrowserContentHandler.jsm
@@ -240,21 +240,20 @@ function openBrowserWindow(cmdLine, trig
       });
       args = [uriArray];
     } else {
       // 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
-              null, // referer
+              null, // refererInfo
               postData,
               undefined, // allowThirdPartyFixup; this would be `false` but that
                          // needs a conversion. Hopefully bug 1485961 will fix.
-              undefined, // referrer policy
               undefined, // user context id
               null, // origin principal
               triggeringPrincipal];
     }
   }
 
   if (cmdLine && cmdLine.state == Ci.nsICommandLine.STATE_INITIAL_LAUNCH) {
     let win = Services.wm.getMostRecentWindow("navigator:blank");
--- a/browser/components/contextualidentity/test/browser/browser_relatedTab.js
+++ b/browser/components/contextualidentity/test/browser/browser_relatedTab.js
@@ -1,31 +1,38 @@
 "use strict";
 
 /*
  * Bug 1325014 - Adding tab related to current tab inherits current tab's container usercontextid unless otherwise specified
  */
 
 add_task(async function() {
   let tab = BrowserTestUtils.addTab(gBrowser, "about:blank", {userContextId: 1});
+  let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
+                                            "nsIReferrerInfo",
+                                            "init");
 
   gBrowser.selectedTab = tab;
   let relatedTab = BrowserTestUtils.addTab(gBrowser, "about:blank", {relatedToCurrent: true});
   is(relatedTab.getAttribute("usercontextid"), 1, "Related tab (relatedToCurrent) inherits current tab's usercontextid");
   BrowserTestUtils.removeTab(relatedTab);
 
   gBrowser.selectedTab = tab;
   relatedTab = BrowserTestUtils.addTab(gBrowser, "about:blank", {relatedToCurrent: true, userContextId: 2});
   is(relatedTab.getAttribute("usercontextid"), 2, "Related tab (relatedToCurrent) with overridden usercontextid");
   BrowserTestUtils.removeTab(relatedTab);
 
   gBrowser.selectedTab = tab;
-  relatedTab = BrowserTestUtils.addTab(gBrowser, "about:blank", {referrerURI: gBrowser.currentURI});
+  let referrerInfo = new ReferrerInfo(
+    Ci.nsIHttpChannel.REFERRER_POLICY_UNSET, true, gBrowser.currentURI);
+  relatedTab = BrowserTestUtils.addTab(gBrowser, "about:blank", { referrerInfo });
   is(relatedTab.getAttribute("usercontextid"), 1, "Related tab (referrer) inherits current tab's usercontextid");
   BrowserTestUtils.removeTab(relatedTab);
 
   gBrowser.selectedTab = tab;
-  relatedTab = BrowserTestUtils.addTab(gBrowser, "about:blank", {referrerURI: gBrowser.currentURI, userContextId: 2});
+  referrerInfo = new ReferrerInfo(
+    Ci.nsIHttpChannel.REFERRER_POLICY_UNSET, true, gBrowser.currentURI);
+  relatedTab = BrowserTestUtils.addTab(gBrowser, "about:blank", { referrerInfo, userContextId: 2});
   is(relatedTab.getAttribute("usercontextid"), 2, "Related tab (referrer) with overridden usercontextid");
   BrowserTestUtils.removeTab(relatedTab);
 
   BrowserTestUtils.removeTab(tab);
 });
--- a/browser/components/contextualidentity/test/browser/browser_usercontextid_new_window.js
+++ b/browser/components/contextualidentity/test/browser/browser_usercontextid_new_window.js
@@ -19,17 +19,16 @@ function openWindowWithUserContextId(use
   let urlSupports = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
   urlSupports.data = TEST_URI;
   args.appendElement(urlSupports);
 
   args.appendElement(null);
   args.appendElement(null);
   args.appendElement(null);
   args.appendElement(null);
-  args.appendElement(null);
 
   let userContextIdSupports = Cc["@mozilla.org/supports-PRUint32;1"].createInstance(Ci.nsISupportsPRUint32);
   userContextIdSupports.data = userContextId;
   args.appendElement(userContextIdSupports);
 
   args.appendElement(Services.scriptSecurityManager.getSystemPrincipal());
   args.appendElement(Services.scriptSecurityManager.getSystemPrincipal());
 
--- a/browser/components/extensions/parent/ext-windows.js
+++ b/browser/components/extensions/parent/ext-windows.js
@@ -199,20 +199,19 @@ this.windows = class extends ExtensionAP
                 !context.checkLoadURL(url, {dontReportErrors: true})) {
               // The extension principal cannot directly load about:-URLs,
               // except for about:blank. So use the system principal instead.
               principal = Services.scriptSecurityManager.getSystemPrincipal();
             }
           }
 
           args.appendElement(null); // unused
-          args.appendElement(null); // referrer
+          args.appendElement(null); // referrerInfo
           args.appendElement(null); // postData
           args.appendElement(null); // allowThirdPartyFixup
-          args.appendElement(null); // referrerPolicy
 
           if (createData.cookieStoreId) {
             let userContextIdSupports = Cc["@mozilla.org/supports-PRUint32;1"].createInstance(Ci.nsISupportsPRUint32);
             // May throw if validation fails.
             userContextIdSupports.data = getUserContextIdForCookieStoreId(extension, createData.cookieStoreId, createData.incognito);
             args.appendElement(userContextIdSupports); // userContextId
           } else {
             args.appendElement(null);
--- a/browser/modules/ContentClick.jsm
+++ b/browser/modules/ContentClick.jsm
@@ -66,19 +66,17 @@ var ContentClick = {
     var where = window.whereToOpenLink(json);
     if (where == "current")
       return;
 
     // Todo(903022): code for where == save
 
     let params = {
       charset: browser.characterSet,
-      referrerURI: browser.documentURI,
-      referrerPolicy: json.referrerPolicy,
-      noReferrer: json.noReferrer,
+      referrerInfo: E10SUtils.deserializeReferrerInfo(json.referrerInfo),
       allowMixedContent: json.allowMixedContent,
       isContentWindowPrivate: json.isContentWindowPrivate,
       originPrincipal: json.originPrincipal,
       triggeringPrincipal: json.triggeringPrincipal,
       csp: json.csp ? E10SUtils.deserializeCSP(json.csp) : null,
       frameOuterWindowID: json.frameOuterWindowID,
     };
 
--- a/testing/mochitest/api.js
+++ b/testing/mochitest/api.js
@@ -94,17 +94,17 @@ function loadMochitest(e) {
   let flavor = e.detail[0];
   let url = e.detail[1];
 
   let win = Services.wm.getMostRecentWindow(WINDOW_TYPE);
   win.removeEventListener("mochitest-load", loadMochitest);
 
   // for mochitest-plain, navigating to the url is all we need
   if (!IS_THUNDERBIRD) {
-    win.loadURI(url, null, null, null, null, null, null, null,
+    win.loadURI(url, null, null, null, null, null, null,
       Services.scriptSecurityManager.getSystemPrincipal());
   }
   if (flavor == "mochitest") {
     return;
   }
 
   WindowListener.setupWindow(win);
   Services.wm.addListener(WindowListener);