Bug 1374741 - Within browser/ make openUILinkIn() provide the correct triggeringPrincipal. r?gijs draft
authorJonathan Kingston <jkt@mozilla.com>
Wed, 21 Feb 2018 14:28:48 +0000
changeset 779220 f0f54f8cbccc1d08672430c981705404877e14dd
parent 779146 30d72755b1749953d438199456f1524ce84ab5e5
child 779221 04af342abe042e18c8115c6f3b22010ad51a7eff
push id105703
push userbmo:jkt@mozilla.com
push dateMon, 09 Apr 2018 14:09:22 +0000
reviewersgijs
bugs1374741
milestone61.0a1
Bug 1374741 - Within browser/ make openUILinkIn() provide the correct triggeringPrincipal. r?gijs MozReview-Commit-ID: 1NQrlWzIBja
browser/base/content/browser-feeds.js
browser/base/content/browser-media.js
browser/base/content/browser-places.js
browser/base/content/browser-plugins.js
browser/base/content/browser-sync.js
browser/base/content/browser.js
browser/base/content/nsContextMenu.js
browser/base/content/pageinfo/feeds.js
browser/base/content/urlbarBindings.xml
browser/base/content/utilityOverlay.js
browser/components/customizableui/CustomizableWidgets.jsm
browser/components/customizableui/CustomizeMode.jsm
browser/components/customizableui/content/panelUI.js
browser/components/migration/AutoMigrate.jsm
browser/components/nsBrowserGlue.js
browser/components/places/PlacesUIUtils.jsm
browser/components/places/content/browserPlacesViews.js
browser/components/preferences/in-content/main.js
browser/components/preferences/in-content/sync.js
browser/components/search/content/search.xml
browser/components/search/content/searchReset.js
browser/components/sessionstore/test/browser.ini
browser/components/syncedtabs/TabListComponent.js
browser/components/syncedtabs/test/xpcshell/test_TabListComponent.js
browser/components/translation/Translation.jsm
browser/components/translation/translation-infobar.xml
browser/extensions/pocket/content/Pocket.jsm
browser/extensions/pocket/content/main.js
browser/extensions/screenshots/bootstrap.js
browser/modules/ContentCrashHandlers.jsm
browser/modules/ContentSearch.jsm
browser/modules/ExtensionsUI.jsm
browser/modules/ProcessHangMonitor.jsm
browser/modules/test/browser/browser.ini
--- a/browser/base/content/browser-feeds.js
+++ b/browser/base/content/browser-feeds.js
@@ -209,17 +209,20 @@ var FeedHandler = {
     urlSecurityCheck(href, gBrowser.contentPrincipal,
                      Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
     this.loadFeed(href, event);
   },
 
   loadFeed(href, event) {
     let feeds = gBrowser.selectedBrowser.feeds;
     try {
-      openUILink(href, event, { ignoreAlt: true });
+      openUILink(href, event, {
+        ignoreAlt: true,
+        triggeringPrincipal: gBrowser.contentPrincipal,
+      });
     } finally {
       // We might default to a livebookmarks modal dialog,
       // so reset that if the user happens to click it again
       gBrowser.selectedBrowser.feeds = feeds;
     }
   },
 
   get _feedMenuitem() {
--- a/browser/base/content/browser-media.js
+++ b/browser/base/content/browser-media.js
@@ -315,17 +315,17 @@ let gDecoderDoctorHandler = {
               Services.prefs.getBoolPref(buttonClickedPref, false);
             if (!clickedInPref) {
               Services.prefs.setBoolPref(buttonClickedPref, true);
               histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_CLICKED_FIRST);
             }
             histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_CLICKED);
 
             let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
-            openUILinkIn(baseURL + sumo, "tab");
+            openTrustedLinkIn(baseURL + sumo, "tab");
           }
         });
       }
       let endpoint = gDecoderDoctorHandler.getEndpointForReportIssueButton(type);
       if (endpoint) {
         buttons.push({
           label: gNavigatorBundle.getString("decoder.decodeError.button"),
           accessKey: gNavigatorBundle.getString("decoder.decodeError.accesskey"),
@@ -345,17 +345,17 @@ let gDecoderDoctorHandler = {
             params.append("src", "media-decode-error");
 
             let details = {"Technical Information:": decodeIssue};
             if (resourceURL) {
               details["Resource:"] = resourceURL;
             }
 
             params.append("details", JSON.stringify(details));
-            openUILinkIn(endpoint + "?" + params.toString(), "tab");
+            openTrustedLinkIn(endpoint + "?" + params.toString(), "tab");
           }
         });
       }
 
       box.appendNotification(
           title,
           notificationId,
           "", // This uses the info icon as specified below.
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -718,17 +718,20 @@ HistoryMenu.prototype = {
     this.toggleTabsFromOtherComputers();
   },
 
   _onCommand: function HM__onCommand(aEvent) {
     let placesNode = aEvent.target._placesNode;
     if (placesNode) {
       if (!PrivateBrowsingUtils.isWindowPrivate(window))
         PlacesUIUtils.markPageAsTyped(placesNode.uri);
-      openUILink(placesNode.uri, aEvent, { ignoreAlt: true });
+      openUILink(placesNode.uri, aEvent, {
+        ignoreAlt: true,
+        triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
+      });
     }
   }
 };
 
 /**
  * Functions for handling events in the Bookmarks Toolbar and menu.
  */
 var BookmarksEventHandler = {
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -93,17 +93,17 @@ var gPluginHandler = {
 
   // Callback for user clicking on the link in a click-to-play plugin
   // (where the plugin has an update)
   openPluginUpdatePage(pluginTag) {
     let url = Services.blocklist.getPluginInfoURL(pluginTag);
     if (!url) {
       url = Services.blocklist.getPluginBlocklistURL(pluginTag);
     }
-    openUILinkIn(url, "tab");
+    openTrustedLinkIn(url, "tab");
   },
 
   submitReport: function submitReport(runID, keyVals, submitURLOptIn) {
     if (!AppConstants.MOZ_CRASHREPORTER) {
       return;
     }
     Services.prefs.setBoolPref("dom.ipc.plugins.reportCrashURL", submitURLOptIn);
     PluginCrashReporter.submitCrashReport(runID, keyVals);
--- a/browser/base/content/browser-sync.js
+++ b/browser/base/content/browser-sync.js
@@ -305,17 +305,17 @@ var gSync = {
     switchToTabHavingURI(url, true, {
       replaceQueryString: true,
       triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
     });
   },
 
   async openConnectAnotherDevice(entryPoint) {
     const url = await FxAccounts.config.promiseConnectDeviceURI(entryPoint);
-    openUILinkIn(url, "tab");
+    openTrustedLinkIn(url, "tab");
   },
 
   openSendToDevicePromo() {
     let url = this.PRODUCT_INFO_BASE_URL;
     url += "send-tabs/?utm_source=" + Services.appinfo.name.toLowerCase();
     switchToTabHavingURI(url, true, { replaceQueryString: true });
   },
 
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -909,17 +909,17 @@ function gKeywordURIFixup({ target: brow
         label: yesMessage,
         accessKey: gNavigatorBundle.getString("keywordURIFixup.goTo.accesskey"),
         callback() {
           // Do not set this preference while in private browsing.
           if (!PrivateBrowsingUtils.isWindowPrivate(window)) {
             let pref = "browser.fixup.domainwhitelist." + asciiHost;
             Services.prefs.setBoolPref(pref, true);
           }
-          openUILinkIn(alternativeURI.spec, "current");
+          openTrustedLinkIn(alternativeURI.spec, "current");
         }
       },
       {
         label: gNavigatorBundle.getString("keywordURIFixup.dismiss"),
         accessKey: gNavigatorBundle.getString("keywordURIFixup.dismiss.accesskey"),
         callback() {
           let notification = notificationBox.getNotificationWithValue("keyword-uri-fixup");
           notificationBox.removeNotification(notification, true);
@@ -2216,17 +2216,17 @@ function BrowserGoHome(aEvent) {
   var urls;
 
   // Home page should open in a new tab when current tab is an app tab
   if (where == "current" &&
       gBrowser &&
       gBrowser.selectedTab.pinned)
     where = "tab";
 
-  // openUILinkIn in utilityOverlay.js doesn't handle loading multiple pages
+  // openTrustedLinkIn in utilityOverlay.js doesn't handle loading multiple pages
   switch (where) {
   case "current":
     loadOneOrMoreURIs(homePage, Services.scriptSecurityManager.getSystemPrincipal());
     gBrowser.selectedBrowser.focus();
     break;
   case "tabshifted":
   case "tab":
     urls = homePage.split("|");
@@ -2339,17 +2339,19 @@ function BrowserOpenTab(event) {
         relatedToCurrent = true;
         break;
       case "current":
         where = "tab";
         break;
     }
   }
 
-  openUILinkIn(BROWSER_NEW_TAB_URL, where, { relatedToCurrent });
+  openTrustedLinkIn(BROWSER_NEW_TAB_URL, where, {
+    relatedToCurrent,
+  });
 }
 
 var gLastOpenDirectory = {
   _lastDir: null,
   get path() {
     if (!this._lastDir || !this._lastDir.exists()) {
       try {
         this._lastDir = Services.prefs.getComplexValue("browser.open.lastDir",
@@ -2388,17 +2390,17 @@ function BrowserOpenFileWindow() {
       if (aResult == nsIFilePicker.returnOK) {
         try {
           if (fp.file) {
             gLastOpenDirectory.path =
               fp.file.parent.QueryInterface(Ci.nsIFile);
           }
         } catch (ex) {
         }
-        openUILinkIn(fp.fileURL.spec, "current");
+        openTrustedLinkIn(fp.fileURL.spec, "current");
       }
     };
 
     fp.init(window, gNavigatorBundle.getString("openFile"),
             nsIFilePicker.modeOpen);
     fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText |
                      nsIFilePicker.filterImages | nsIFilePicker.filterXML |
                      nsIFilePicker.filterHTML);
@@ -3183,31 +3185,31 @@ var BrowserOnClick = {
       title = gNavigatorBundle.getString("safebrowsing.reportedAttackSite");
       // There's no button if we can not get report url, for example if the provider
       // of blockedInfo is not Google
       if (reportUrl) {
         buttons[1] = {
           label: gNavigatorBundle.getString("safebrowsing.notAnAttackButton.label"),
           accessKey: gNavigatorBundle.getString("safebrowsing.notAnAttackButton.accessKey"),
           callback() {
-            openUILinkIn(reportUrl, "tab");
+            openTrustedLinkIn(reportUrl, "tab");
           }
         };
       }
     } else if (reason === "phishing") {
       let reportUrl = gSafeBrowsing.getReportURL("PhishMistake", blockedInfo);
       title = gNavigatorBundle.getString("safebrowsing.deceptiveSite");
       // There's no button if we can not get report url, for example if the provider
       // of blockedInfo is not Google
       if (reportUrl) {
         buttons[1] = {
           label: gNavigatorBundle.getString("safebrowsing.notADeceptiveSiteButton.label"),
           accessKey: gNavigatorBundle.getString("safebrowsing.notADeceptiveSiteButton.accessKey"),
           callback() {
-            openUILinkIn(reportUrl, "tab");
+            openTrustedLinkIn(reportUrl, "tab");
           }
         };
       }
     } else if (reason === "unwanted") {
       title = gNavigatorBundle.getString("safebrowsing.reportedUnwantedSite");
       // There is no button for reporting errors since Google doesn't currently
       // provide a URL endpoint for these reports.
     } else if (reason === "harmful") {
@@ -4021,17 +4023,17 @@ const BrowserSearch = {
 
   get searchEnginesURL() {
     return formatURL("browser.search.searchEnginesURL", true);
   },
 
   loadAddEngines: function BrowserSearch_loadAddEngines() {
     var newWindowPref = Services.prefs.getIntPref("browser.link.open_newwindow");
     var where = newWindowPref == 3 ? "tab" : "window";
-    openUILinkIn(this.searchEnginesURL, where);
+    openTrustedLinkIn(this.searchEnginesURL, where);
   },
 
   _getSearchEngineId(engine) {
     if (engine && engine.identifier) {
       return engine.identifier;
     }
 
     if (!engine || (engine.name === undefined))
@@ -4219,17 +4221,17 @@ function addToUrlbarHistory(aUrlToAdd) {
       aUrlToAdd &&
       !aUrlToAdd.includes(" ") &&
       !/[\x00-\x1F]/.test(aUrlToAdd)) // eslint-disable-line no-control-regex
     PlacesUIUtils.markPageAsTyped(aUrlToAdd);
 }
 
 function BrowserDownloadsUI() {
   if (PrivateBrowsingUtils.isWindowPrivate(window)) {
-    openUILinkIn("about:downloads", "tab");
+    openTrustedLinkIn("about:downloads", "tab");
   } else {
     PlacesCommandHook.showPlacesOrganizer("Downloads");
   }
 }
 
 function toOpenWindowByType(inType, uri, features) {
   var topWindow = Services.wm.getMostRecentWindow(inType);
 
@@ -4389,17 +4391,17 @@ function updateEditUIVisibility() {
  * Opens a new tab with the userContextId specified as an attribute of
  * sourceEvent. This attribute is propagated to the top level originAttributes
  * living on the tab's docShell.
  *
  * @param event
  *        A click event on a userContext File Menu option
  */
 function openNewUserContextTab(event) {
-  openUILinkIn(BROWSER_NEW_TAB_URL, "tab", {
+  openTrustedLinkIn(BROWSER_NEW_TAB_URL, "tab", {
     userContextId: parseInt(event.target.getAttribute("data-usercontextid")),
   });
 }
 
 /**
  * Updates File Menu User Context UI visibility depending on
  * privacy.userContext.enabled pref state.
  */
@@ -6159,17 +6161,19 @@ function middleMousePaste(event) {
       // but don't let that interfere with the loading of the url.
       Cu.reportError(ex);
     }
 
     if (where != "current" ||
         lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) {
       openUILink(data.url, event,
                  { ignoreButton: true,
-                   disallowInheritPrincipal: !data.mayInheritPrincipal });
+                   disallowInheritPrincipal: !data.mayInheritPrincipal,
+                   triggeringPrincipal: gBrowser.selectedBrowser.contentPrincipal,
+                 });
     }
   });
 
   if (event instanceof Event) {
     event.stopPropagation();
   }
 }
 
@@ -7095,17 +7099,17 @@ function BrowserOpenAddonsMgr(aView) {
       return;
     }
 
     // This must be a new load, else the ping/pong would have
     // found the window above.
     let whereToOpen = (window.gBrowser && isTabEmpty(gBrowser.selectedTab)) ?
                       "current" :
                       "tab";
-    openUILinkIn("about:addons", whereToOpen);
+    openTrustedLinkIn("about:addons", whereToOpen);
 
     Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
       Services.obs.removeObserver(observer, aTopic);
       if (aView) {
         aSubject.loadView(aView);
       }
       aSubject.QueryInterface(Ci.nsIDOMWindow);
       aSubject.focus();
@@ -7271,17 +7275,17 @@ function ReportFalseDeceptiveSite() {
     docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked");
 
   if (isPhishingPage) {
     let mm = gBrowser.selectedBrowser.messageManager;
     let onMessage = (message) => {
       mm.removeMessageListener("DeceptiveBlockedDetails:Result", onMessage);
       let reportUrl = gSafeBrowsing.getReportURL("PhishMistake", message.data.blockedInfo);
       if (reportUrl) {
-        openUILinkIn(reportUrl, "tab");
+        openTrustedLinkIn(reportUrl, "tab");
       } else {
         let bundle =
           Services.strings.createBundle("chrome://browser/locale/safebrowsing/safebrowsing.properties");
         Services.prompt.alert(window,
                               bundle.GetStringFromName("errorReportFalseDeceptiveTitle"),
                               bundle.formatStringFromName("errorReportFalseDeceptiveMessage",
                                                           [message.data.blockedInfo.provider], 1));
         }
@@ -8570,18 +8574,18 @@ var gPrivateBrowsingUI = {
  *
  * @param aURI
  *        URI to search for
  * @param aOpenNew
  *        True to open a new tab and switch to it, if no existing tab is found.
  *        If no suitable window is found, a new one will be opened.
  * @param aOpenParams
  *        If switching to this URI results in us opening a tab, aOpenParams
- *        will be the parameter object that gets passed to openUILinkIn. Please
- *        see the documentation for openUILinkIn to see what parameters can be
+ *        will be the parameter object that gets passed to openTrustedLinkIn. Please
+ *        see the documentation for openTrustedLinkIn to see what parameters can be
  *        passed via this object.
  *        This object also allows:
  *        - 'ignoreFragment' property to be set to true to exclude fragment-portion
  *        matching when comparing URIs.
  *          If set to "whenComparing", the fragment will be unmodified.
  *          If set to "whenComparingAndReplace", the fragment will be replaced.
  *        - 'ignoreQueryString' boolean property to be set to true to exclude query string
  *        matching when comparing URIs.
@@ -8697,19 +8701,19 @@ function switchToTabHavingURI(aURI, aOpe
       continue;
     if (switchIfURIInWindow(browserWin))
       return true;
   }
 
   // No opened tab has that url.
   if (aOpenNew) {
     if (isBrowserWindow && isTabEmpty(gBrowser.selectedTab))
-      openUILinkIn(aURI.spec, "current", aOpenParams);
+      openTrustedLinkIn(aURI.spec, "current", aOpenParams);
     else
-      openUILinkIn(aURI.spec, "tab", aOpenParams);
+      openTrustedLinkIn(aURI.spec, "tab", aOpenParams);
   }
 
   return false;
 }
 
 var RestoreLastSessionObserver = {
   init() {
     if (SessionStore.canRestoreLastSession &&
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -779,30 +779,27 @@ nsContextMenu.prototype = {
       params.noReferrer = true;
     }
 
     return params;
   },
 
   // Open linked-to URL in a new window.
   openLink() {
-    urlSecurityCheck(this.linkURL, this.principal);
     openLinkIn(this.linkURL, "window", this._openLinkInParameters());
   },
 
   // Open linked-to URL in a new private window.
   openLinkInPrivateWindow() {
-    urlSecurityCheck(this.linkURL, this.principal);
     openLinkIn(this.linkURL, "window",
                this._openLinkInParameters({ private: true }));
   },
 
   // Open linked-to URL in a new tab.
   openLinkInTab(event) {
-    urlSecurityCheck(this.linkURL, this.principal);
     let referrerURI = gContextMenuContentData.documentURIObject;
 
     // if its parent allows mixed content and the referring URI passes
     // a same origin check with the target URI, we can preserve the users
     // decision of disabling MCB on a page for it's child tabs.
     let persistAllowMixedContentInChildTab = false;
 
     if (gContextMenuContentData.parentAllowsMixedContent) {
@@ -819,17 +816,16 @@ nsContextMenu.prototype = {
       userContextId: parseInt(event.target.getAttribute("data-usercontextid")),
     };
 
     openLinkIn(this.linkURL, "tab", this._openLinkInParameters(params));
   },
 
   // open URL in current tab
   openLinkInCurrent() {
-    urlSecurityCheck(this.linkURL, this.principal);
     openLinkIn(this.linkURL, "current", this._openLinkInParameters());
   },
 
   // Open frame in a new tab.
   openFrameInTab() {
     let referrer = gContextMenuContentData.referrer;
     openLinkIn(gContextMenuContentData.docLocation, "tab",
                { charset: gContextMenuContentData.charSet,
@@ -848,23 +844,22 @@ nsContextMenu.prototype = {
     let referrer = gContextMenuContentData.referrer;
     openLinkIn(gContextMenuContentData.docLocation, "window",
                { charset: gContextMenuContentData.charSet,
                  referrerURI: referrer ? makeURI(referrer) : null });
   },
 
   // Open clicked-in frame in the same window.
   showOnlyThisFrame() {
-    urlSecurityCheck(gContextMenuContentData.docLocation,
-                     this.browser.contentPrincipal,
-                     Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
     let referrer = gContextMenuContentData.referrer;
-    openUILinkIn(gContextMenuContentData.docLocation, "current",
-                 { disallowInheritPrincipal: true,
-                   referrerURI: referrer ? makeURI(referrer) : null });
+    openWebLinkIn(gContextMenuContentData.docLocation, "current", {
+      disallowInheritPrincipal: true,
+      referrerURI: referrer ? makeURI(referrer) : null,
+      triggeringPrincipal: this.browser.contentPrincipal,
+    });
   },
 
   reload(event) {
     BrowserReloadOrDuplicate(event);
   },
 
   // View Partial Source
   viewPartialSource(aContext) {
@@ -907,33 +902,28 @@ nsContextMenu.prototype = {
   },
 
   viewImageInfo() {
     BrowserPageInfo(gContextMenuContentData.docLocation, "mediaTab",
                     this.imageInfo, null, this.browser);
   },
 
   viewImageDesc(e) {
-    urlSecurityCheck(this.imageDescURL,
-                     this.browser.contentPrincipal,
-                     Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
     openUILink(this.imageDescURL, e, { disallowInheritPrincipal: true,
-                                       referrerURI: gContextMenuContentData.documentURIObject });
+                                       referrerURI: gContextMenuContentData.documentURIObject,
+                                       triggeringPrincipal: this.principal,
+    });
   },
 
   viewFrameInfo() {
     BrowserPageInfo(gContextMenuContentData.docLocation, null, null,
                     this.frameOuterWindowID, this.browser);
   },
 
   reloadImage() {
-    urlSecurityCheck(this.mediaURL,
-                     this.browser.contentPrincipal,
-                     Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
-
     this.browser.messageManager.sendAsyncMessage("ContextMenu:ReloadImage",
                                                  null, { target: this.target });
   },
 
   _canvasToBlobURL(target) {
     let mm = this.browser.messageManager;
     return new Promise(function(resolve) {
       mm.sendAsyncMessage("ContextMenu:Canvas:ToBlobURL", {}, { target });
@@ -952,22 +942,21 @@ nsContextMenu.prototype = {
     let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
     if (this.onCanvas) {
       this._canvasToBlobURL(this.target).then(function(blobURL) {
         openUILink(blobURL, e, { disallowInheritPrincipal: true,
                                  referrerURI,
                                  triggeringPrincipal: systemPrincipal});
       }, Cu.reportError);
     } else {
-      urlSecurityCheck(this.mediaURL,
-                       this.browser.contentPrincipal,
-                       Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
       openUILink(this.mediaURL, e, { disallowInheritPrincipal: true,
                                      referrerURI,
-                                     forceAllowDataURI: true });
+                                     forceAllowDataURI: true,
+                                     triggeringPrincipal: this.browser.contentPrincipal
+      });
     }
   },
 
   saveVideoFrameAsImage() {
     let mm = this.browser.messageManager;
     let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(this.browser);
 
     let name = "";
@@ -997,21 +986,20 @@ nsContextMenu.prototype = {
   },
 
   leaveDOMFullScreen() {
     document.exitFullscreen();
   },
 
   // Change current window to the URL of the background image.
   viewBGImage(e) {
-    urlSecurityCheck(this.bgImageURL,
-                     this.browser.contentPrincipal,
-                     Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
     openUILink(this.bgImageURL, e, { disallowInheritPrincipal: true,
-                                     referrerURI: gContextMenuContentData.documentURIObject });
+                                     referrerURI: gContextMenuContentData.documentURIObject,
+                                     triggeringPrincipal: this.browser.contentPrincipal
+    });
   },
 
   setDesktopBackground() {
     let mm = this.browser.messageManager;
 
     mm.sendAsyncMessage("ContextMenu:SetAsDesktopBackground", null,
                         { target: this.target });
 
@@ -1196,18 +1184,16 @@ nsContextMenu.prototype = {
                            timer.TYPE_ONE_SHOT);
 
     // kick off the channel with our proxy object as the listener
     channel.asyncOpen2(new saveAsListener());
   },
 
   // Save URL of clicked-on link.
   saveLink() {
-    urlSecurityCheck(this.linkURL, this.principal);
-
     let isContentWindowPrivate = this.isRemote ? this.ownerDoc.isPrivate : undefined;
     this.saveHelper(this.linkURL, this.linkTextStr, null, true, this.ownerDoc,
                     gContextMenuContentData.documentURIObject,
                     this.frameOuterWindowID,
                     this.linkDownload,
                     isContentWindowPrivate);
   },
 
@@ -1231,17 +1217,16 @@ nsContextMenu.prototype = {
                      isPrivate);
       }, Cu.reportError);
     } else if (this.onImage) {
       urlSecurityCheck(this.mediaURL, this.principal);
       saveImageURL(this.mediaURL, null, "SaveImageTitle", false,
                    false, referrerURI, null, gContextMenuContentData.contentType,
                    gContextMenuContentData.contentDisposition, isPrivate);
     } else if (this.onVideo || this.onAudio) {
-      urlSecurityCheck(this.mediaURL, this.principal);
       var dialogTitle = this.onVideo ? "SaveVideoTitle" : "SaveAudioTitle";
       this.saveHelper(this.mediaURL, null, dialogTitle, false, doc, referrerURI,
                       this.frameOuterWindowID, "", isContentWindowPrivate);
     }
   },
 
   // Backwards-compatibility wrapper
   sendImage() {
@@ -1401,17 +1386,17 @@ nsContextMenu.prototype = {
       version = Services.appinfo.version;
     } catch (e) { }
 
     uri = uri.replace(/%LOCALE%/, escape(locale)).replace(/%VERSION%/, version);
 
     var newWindowPref = Services.prefs.getIntPref("browser.link.open_newwindow");
     var where = newWindowPref == 3 ? "tab" : "window";
 
-    openUILinkIn(uri, where);
+    openTrustedLinkIn(uri, where);
   },
 
   bookmarkThisPage: function CM_bookmarkThisPage() {
     window.top.PlacesCommandHook
               .bookmarkPage(this.browser, true)
               .catch(Cu.reportError);
   },
 
@@ -1471,17 +1456,17 @@ nsContextMenu.prototype = {
   drmLearnMore(aEvent) {
     let drmInfoURL = Services.urlFormatter.formatURLPref("app.support.baseURL") + "drm-content";
     let dest = whereToOpenLink(aEvent);
     // Don't ever want this to open in the same tab as it'll unload the
     // DRM'd video, which is going to be a bad idea in most cases.
     if (dest == "current") {
       dest = "tab";
     }
-    openUILinkIn(drmInfoURL, dest);
+    openTrustedLinkIn(drmInfoURL, dest);
   },
 
   get imageURL() {
     if (this.onImage)
       return this.mediaURL;
     return "";
   },
 
--- a/browser/base/content/pageinfo/feeds.js
+++ b/browser/base/content/pageinfo/feeds.js
@@ -46,15 +46,15 @@ function addRow(name, type, url) {
   urlLabel.textContent = url;
   urlLabel.setAttribute("tooltiptext", url);
   urlLabel.addEventListener("click", ev => openUILink(this.value, ev));
   urlContainer.appendChild(urlLabel);
 
   const subscribeButton = document.createElement("button");
   subscribeButton.className = "feed-subscribe";
   subscribeButton.addEventListener("click",
-    () => openUILinkIn(url, "current", { ignoreAlt: true }));
+    () => openWebLinkIn(url, "current", { ignoreAlt: true }));
   subscribeButton.setAttribute("label", gBundle.getString("feedSubscribe"));
   subscribeButton.setAttribute("accesskey", gBundle.getString("feedSubscribe.accesskey"));
   bottom.appendChild(subscribeButton);
 
   document.getElementById("feedListbox").appendChild(item);
 }
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -647,21 +647,21 @@ file, You can obtain one at http://mozil
         This is ultimately called by the autocomplete controller as the result
         of handleEnter when the Return key is pressed in the textbox.  Since
         onPopupClick also calls handleEnter, this is also called as a result in
         that case.
 
         @param event
                The event that triggered the command.
         @param openUILinkWhere
-               Optional.  The "where" to pass to openUILinkIn.  This method
+               Optional.  The "where" to pass to openTrustedLinkIn.  This method
                computes the appropriate "where" given the event, but you can
                use this to override it.
         @param openUILinkParams
-               Optional.  The parameters to pass to openUILinkIn.  As with
+               Optional.  The parameters to pass to openTrustedLinkIn.  As with
                "where", this method computes the appropriate parameters, but
                any parameters you supply here will override those.
       -->
       <method name="handleCommand">
         <parameter name="event"/>
         <parameter name="openUILinkWhere"/>
         <parameter name="openUILinkParams"/>
         <parameter name="triggeringPrincipal"/>
@@ -875,17 +875,17 @@ file, You can obtain one at http://mozil
           // area when the current tab is re-selected.
           browser.focus();
 
           if (openUILinkWhere != "current") {
             this.handleRevert();
           }
 
           try {
-            openUILinkIn(url, openUILinkWhere, params);
+            openTrustedLinkIn(url, openUILinkWhere, params);
           } catch (ex) {
             // This load can throw an exception in certain cases, which means
             // we'll want to replace the URL with the loaded URL:
             if (ex.result != Cr.NS_ERROR_LOAD_SHOWED_ERRORPAGE) {
               this.handleRevert();
             }
           }
 
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -115,16 +115,25 @@ function openUILink(url, event, aIgnoreB
       allowThirdPartyFixup: aAllowThirdPartyFixup,
       postData: aPostData,
       referrerURI: aReferrerURI,
       referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
       initiatingDoc: event ? event.target.ownerDocument : null,
     };
   }
 
+  if (!params.triggeringPrincipal) {
+    let dt = event ? event.dataTransfer : null;
+    if (!!dt && dt.mozSourceNode) {
+      params.triggeringPrincipal = dt.mozSourceNode.nodePrincipal;
+    } else {
+      params.triggeringPrincipal = Services.scriptSecurityManager.createNullPrincipal({});
+    }
+  }
+
   let where = whereToOpenLink(event, aIgnoreButton, aIgnoreAlt);
   openUILinkIn(url, where, params);
 }
 
 
 /**
  * whereToOpenLink() looks at an event to decide where to open a link.
  *
@@ -176,26 +185,72 @@ function whereToOpenLink(e, ignoreButton
     return "save";
 
   if (shift || (middle && !middleUsesTabs))
     return "window";
 
   return "current";
 }
 
+/* openTrustedLinkIn will attempt to open the given URI using the SystemPrincipal
+ * as the trigeringPrincipal, unless a more specific Principal is provided.
+ *
+ * See openUILinkIn for a discussion of parameters
+ */
+function openTrustedLinkIn(url, where, aParams) {
+  var params = aParams;
+
+  if (!params) {
+    params = {};
+  }
+
+  if (!params.triggeringPrincipal) {
+    params.triggeringPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
+  }
+
+  openUILinkIn(url, where, params);
+}
+
+/* openWebLinkIn will attempt to open the given URI using the NullPrincipal
+ * as the triggeringPrincipal, unless a more specific Principal is provided.
+ *
+ * See openUILinkIn for a discussion of parameters
+ */
+function openWebLinkIn(url, where, params) {
+  if (!params) {
+    params = {};
+  }
+
+  if (!params.triggeringPrincipal) {
+    params.triggeringPrincipal = Services.scriptSecurityManager.createNullPrincipal({});
+  }
+
+  openUILinkIn(url, where, params);
+}
+
 /* openUILinkIn opens a URL in a place specified by the parameter |where|.
  *
  * |where| can be:
  *  "current"     current tab            (if there aren't any browser windows, then in a new window instead)
  *  "tab"         new tab                (if there aren't any browser windows, then in a new window instead)
  *  "tabshifted"  same as "tab" but in background if default is to select new tabs, and vice versa
  *  "window"      new window
  *  "save"        save to disk (with no filename hint!)
  *
- * aAllowThirdPartyFixup controls whether third party services such as Google's
+ * DEPRECATION WARNING:
+ * USE        -> openTrustedLinkIn(url, where, aParams) if the source is always
+ *                     a user event on a user- or product-specified URL (as
+ *                     opposed to URLs provided by a webpage)
+ * USE        -> openWebLinkIn(url, where, aParams) if the URI should be loaded
+ *                     with a specific triggeringPrincipal, for instance, if
+ *                     the url was supplied by web content.
+ * DEPRECATED -> openUILinkIn(url, where, AllowThirdPartyFixup, aPostData, ...)
+ *
+ *
+ * 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)
@@ -207,22 +262,17 @@ function whereToOpenLink(e, ignoreButton
  *   targetBrowser        (XUL browser)
  */
 function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI) {
   var params;
 
   if (arguments.length == 3 && typeof arguments[2] == "object") {
     params = aAllowThirdPartyFixup;
   } else {
-    params = {
-      allowThirdPartyFixup: aAllowThirdPartyFixup,
-      postData: aPostData,
-      referrerURI: aReferrerURI,
-      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
-    };
+    throw new Error("Required argument triggeringPrincipal missing within openUILinkIn");
   }
 
   params.fromChrome = true;
 
   openLinkIn(url, where, params);
 }
 
 /* eslint-disable complexity */
@@ -824,31 +874,31 @@ function openPreferences(paneID, extraAr
   }
 }
 
 /**
  * Opens the troubleshooting information (about:support) page for this version
  * of the application.
  */
 function openTroubleshootingPage() {
-  openUILinkIn("about:support", "tab");
+  openTrustedLinkIn("about:support", "tab");
 }
 
 /**
  * Opens the feedback page for this version of the application.
  */
 function openFeedbackPage() {
   var url = Services.urlFormatter.formatURLPref("app.feedback.baseURL");
-  openUILinkIn(url, "tab");
+  openTrustedLinkIn(url, "tab");
 }
 
 function openTourPage() {
   let scope = {};
   ChromeUtils.import("resource:///modules/UITour.jsm", scope);
-  openUILinkIn(scope.UITour.url, "tab");
+  openTrustedLinkIn(scope.UITour.url, "tab");
 }
 
 function buildHelpMenu() {
   document.getElementById("feedbackPage")
           .disabled = !Services.policies.isAllowed("feedbackCommands");
 
   document.getElementById("helpSafeMode")
           .disabled = !Services.policies.isAllowed("safeMode");
@@ -915,17 +965,17 @@ function getHelpLinkURL(aHelpTopic) {
 
 // aCalledFromModal is optional
 function openHelpLink(aHelpTopic, aCalledFromModal, aWhere) {
   var url = getHelpLinkURL(aHelpTopic);
   var where = aWhere;
   if (!aWhere)
     where = aCalledFromModal ? "window" : "tab";
 
-  openUILinkIn(url, where);
+  openTrustedLinkIn(url, where);
 }
 
 function openPrefsHelp() {
   // non-instant apply prefwindows are usually modal, so we can't open in the topmost window,
   // since its probably behind the window.
   var instantApply = getBoolPref("browser.preferences.instantApply");
 
   var helpTopic = document.documentElement.getAttribute("helpTopic");
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -739,17 +739,17 @@ if (Services.prefs.getBoolPref("identity
       item.setAttribute("class", "subviewbutton");
       item.setAttribute("targetURI", tabInfo.url);
       item.setAttribute("label", tabInfo.title != "" ? tabInfo.title : tabInfo.url);
       item.setAttribute("image", tabInfo.icon);
       item.setAttribute("tooltiptext", tooltipText);
       // We need to use "click" instead of "command" here so openUILink
       // respects different buttons (eg, to open in a new tab).
       item.addEventListener("click", e => {
-        doc.defaultView.openUILink(tabInfo.url, e);
+        doc.defaultView.openWebLinkIn(tabInfo.url, e);
         if (doc.defaultView.whereToOpenLink(e) != "current") {
           e.preventDefault();
           e.stopPropagation();
         } else {
           CustomizableUI.hidePanelForNode(item);
         }
         BrowserUITelemetry.countSyncedTabEvent("open", "toolbarbutton-subview");
       });
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -214,17 +214,17 @@ CustomizeMode.prototype = {
         return;
       }
       let obs = () => {
         Services.obs.removeObserver(obs, "browser-delayed-startup-finished");
         w = this.window.getTopWin(true);
         w.gCustomizeMode.enter();
       };
       Services.obs.addObserver(obs, "browser-delayed-startup-finished");
-      this.window.openUILinkIn("about:newtab", "window");
+      this.window.openTrustedLinkIn("about:newtab", "window");
       return;
     }
     this._wantToBeInCustomizeMode = true;
 
     if (this._customizing || this._handler.isEnteringCustomizeMode) {
       return;
     }
 
@@ -1239,17 +1239,17 @@ CustomizeMode.prototype = {
   openAddonsManagerThemes(aEvent) {
     aEvent.target.parentNode.parentNode.hidePopup();
     this.window.BrowserOpenAddonsMgr("addons://list/theme");
   },
 
   getMoreThemes(aEvent) {
     aEvent.target.parentNode.parentNode.hidePopup();
     let getMoreURL = Services.urlFormatter.formatURLPref("lightweightThemes.getMoreURL");
-    this.window.openUILinkIn(getMoreURL, "tab");
+    this.window.openTrustedLinkIn(getMoreURL, "tab");
   },
 
   updateUIDensity(mode) {
     this.window.gUIDensity.update(mode);
   },
 
   setUIDensity(mode) {
     let win = this.window;
--- a/browser/components/customizableui/content/panelUI.js
+++ b/browser/components/customizableui/content/panelUI.js
@@ -560,17 +560,19 @@ const PanelUI = {
     let button = event.target;
     if (event.button > 1 || !button._highlight) {
       return;
     }
     if (event.button == 1) {
       // Bug 1402849, close library panel on mid mouse click
       CustomizableUI.hidePanelForNode(button);
     }
-    window.openUILink(button._highlight.url, event);
+    window.openUILink(button._highlight.url, event, {
+      triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({})
+    });
   },
 
   /**
    * NB: The enable- and disableSingleSubviewPanelAnimations methods only
    * affect the hiding/showing animations of single-subview panels (tempPanel
    * in the showSubView method).
    */
   disableSingleSubviewPanelAnimations() {
--- a/browser/components/migration/AutoMigrate.jsm
+++ b/browser/components/migration/AutoMigrate.jsm
@@ -671,17 +671,17 @@ const AutoMigrate = {
     let migrationBrowser = this.getBrowserUsedForMigration();
     let rawURL = Preferences.get(kAutoMigrateUndoSurveyPref, "");
     if (!canDoSurveyInLocale || !migrationBrowser || !rawURL) {
       return;
     }
 
     let url = Services.urlFormatter.formatURL(rawURL);
     url = url.replace("%IMPORTEDBROWSER%", encodeURIComponent(migrationBrowser));
-    chromeWindow.openUILinkIn(url, "tab");
+    chromeWindow.openTrustedLinkIn(url, "tab");
   },
 
   QueryInterface: XPCOMUtils.generateQI(
     [Ci.nsIObserver, Ci.nsINavBookmarkObserver, Ci.nsISupportsWeakReference]
   ),
 
   /**
    * Undo action called by the UndoNotification or by the newtab
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -504,17 +504,17 @@ BrowserGlue.prototype = {
           if (win) {
             data = JSON.parse(data);
             let where = win.whereToOpenLink(data);
             // Preserve legacy behavior of non-modifier left-clicks
             // opening in a new selected tab.
             if (where == "current") {
               where = "tab";
             }
-            win.openUILinkIn(data.href, where);
+            win.openTrustedLinkIn(data.href, where);
             linkHandled.data = true;
           }
         }
         break;
       case "profile-before-change":
          // Any component depending on Places should be finalized in
          // _onPlacesShutdown.  Any component that doesn't need to act after
          // the UI has gone should be finalized in _onQuitApplicationGranted.
@@ -834,17 +834,17 @@ BrowserGlue.prototype = {
     let productName = gBrandBundle.GetStringFromName("brandFullName");
     let message = win.gNavigatorBundle.getFormattedString("slowStartup.message", [productName]);
 
     let buttons = [
       {
         label:     win.gNavigatorBundle.getString("slowStartup.helpButton.label"),
         accessKey: win.gNavigatorBundle.getString("slowStartup.helpButton.accesskey"),
         callback() {
-          win.openUILinkIn("https://support.mozilla.org/kb/reset-firefox-easily-fix-most-problems", "tab");
+          win.openTrustedLinkIn("https://support.mozilla.org/kb/reset-firefox-easily-fix-most-problems", "tab");
         }
       },
       {
         label:     win.gNavigatorBundle.getString("slowStartup.disableNotificationButton.label"),
         accessKey: win.gNavigatorBundle.getString("slowStartup.disableNotificationButton.accesskey"),
         callback() {
           Services.prefs.setBoolPref("browser.slowStartup.notificationDisabled", true);
         }
@@ -1480,17 +1480,17 @@ BrowserGlue.prototype = {
       let notifyBox = win.document.getElementById("high-priority-global-notificationbox");
 
       let buttons = [
                       {
                         label,
                         accessKey: key,
                         popup:     null,
                         callback(aNotificationBar, aButton) {
-                          win.openUILinkIn(url, "tab");
+                          win.openTrustedLinkIn(url, "tab");
                         }
                       }
                     ];
 
       notifyBox.appendNotification(text, "post-update-notification",
                                    null, notifyBox.PRIORITY_INFO_LOW,
                                    buttons);
     }
@@ -1507,17 +1507,17 @@ BrowserGlue.prototype = {
     let url = getNotifyString({propName: "alertURL",
                                prefName: "startup.homepage_override_url"});
 
     function clickCallback(subject, topic, data) {
       // This callback will be called twice but only once with this topic
       if (topic != "alertclickcallback")
         return;
       let win = RecentWindow.getMostRecentBrowserWindow();
-      win.openUILinkIn(data, "tab");
+      win.openTrustedLinkIn(data, "tab");
     }
 
     try {
       // This will throw NS_ERROR_NOT_AVAILABLE if the notification cannot
       // be displayed per the idl.
       this.AlertsService.showAlertNotification(null, title, text,
                                           true, url, clickCallback);
     } catch (e) {
@@ -1775,17 +1775,17 @@ BrowserGlue.prototype = {
     var win = RecentWindow.getMostRecentBrowserWindow();
 
     var buttons = [
                     {
                       label:     buttonText,
                       accessKey,
                       popup:     null,
                       callback(aNotificationBar, aButton) {
-                        win.openUILinkIn(url, "tab");
+                        win.openTrustedLinkIn(url, "tab");
                       }
                     }
                   ];
 
     var notifyBox = win.gBrowser.getNotificationBox();
     var notification = notifyBox.appendNotification(text, title, null,
                                                     notifyBox.PRIORITY_CRITICAL_MEDIUM,
                                                     buttons);
@@ -2692,17 +2692,17 @@ BrowserGlue.prototype = {
     }
     let productName = gBrandBundle.GetStringFromName("brandShortName");
     let message = win.gNavigatorBundle.
       getFormattedString("flashHang.message", [productName]);
     let buttons = [{
       label: win.gNavigatorBundle.getString("flashHang.helpButton.label"),
       accessKey: win.gNavigatorBundle.getString("flashHang.helpButton.accesskey"),
       callback() {
-        win.openUILinkIn("https://support.mozilla.org/kb/flash-protected-mode-autodisabled", "tab");
+        win.openTrustedLinkIn("https://support.mozilla.org/kb/flash-protected-mode-autodisabled", "tab");
       }
     }];
     let nb = win.document.getElementById("global-notificationbox");
     nb.appendNotification(message, "flash-hang", null,
                           nb.PRIORITY_INFO_MEDIUM, buttons);
   },
 
   _updateFxaBadges() {
--- a/browser/components/places/PlacesUIUtils.jsm
+++ b/browser/components/places/PlacesUIUtils.jsm
@@ -748,17 +748,17 @@ var PlacesUIUtils = {
           let browserWin = RecentWindow.getMostRecentBrowserWindow();
           if (browserWin) {
             browserWin.openWebPanel(aNode.title, aNode.uri);
             return;
           }
         }
       }
 
-      aWindow.openUILinkIn(aNode.uri, aWhere, {
+      aWindow.openTrustedLinkIn(aNode.uri, aWhere, {
         allowPopups: aNode.uri.startsWith("javascript:"),
         inBackground: this.loadBookmarksInBackground,
         private: aPrivate,
       });
     }
   },
 
   /**
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -431,17 +431,18 @@ PlacesViewBase.prototype = {
       // Add "Open (Feed Name)" menuitem.
       aPopup._siteURIMenuitem = document.createElement("menuitem");
       aPopup._siteURIMenuitem.className = "openlivemarksite-menuitem";
       if (typeof this.options.extraClasses.entry == "string") {
         aPopup._siteURIMenuitem.classList.add(this.options.extraClasses.entry);
       }
       aPopup._siteURIMenuitem.setAttribute("targetURI", siteUrl);
       aPopup._siteURIMenuitem.setAttribute("oncommand",
-        "openUILink(this.getAttribute('targetURI'), event);");
+        "openUILink(this.getAttribute('targetURI'), event, {" +
+        " triggeringPrincipal: Services.scriptSecurityManger.createNullPrincipal({})});");
 
       // If a user middle-clicks this item we serve the oncommand event.
       // We are using checkForMiddleClick because of Bug 246720.
       // Note: stopPropagation is needed to avoid serving middle-click
       // with BT_onClick that would open all items in tabs.
       aPopup._siteURIMenuitem.setAttribute("onclick",
         "checkForMiddleClick(this, event); event.stopPropagation();");
       let label =
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -688,17 +688,17 @@ var gMainPane = {
     }
     const win = Services.wm.getMostRecentWindow("navigator:browser");
     if (!win) {
       return;
     }
     const user = await fxAccounts.getSignedInUser();
     if (user) {
       // We have a user, open Sync preferences in the same tab
-      win.openUILinkIn("about:preferences#sync", "current");
+      win.openTrustedLinkIn("about:preferences#sync", "current");
       return;
     }
     let url = await FxAccounts.config.promiseSignInURI("dev-edition-setup");
     let accountsTab = win.gBrowser.addTab(url);
     win.gBrowser.selectedTab = accountsTab;
   },
 
   // HOME PAGE
--- a/browser/components/preferences/in-content/sync.js
+++ b/browser/components/preferences/in-content/sync.js
@@ -340,17 +340,17 @@ var gSyncPane = {
   _getEntryPoint() {
     let params = new URLSearchParams(document.URL.split("#")[0].split("?")[1] || "");
     return params.get("entrypoint") || "preferences";
   },
 
   openContentInBrowser(url, options) {
     let win = Services.wm.getMostRecentWindow("navigator:browser");
     if (!win) {
-      openUILinkIn(url, "tab");
+      openTrustedLinkIn(url, "tab");
       return;
     }
     win.switchToTabHavingURI(url, true, options);
   },
 
   // Replace the current tab with the specified URL.
   replaceTabWithUrl(url) {
     // Get the <browser> element hosting us.
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -388,17 +388,17 @@
           let params = {
             postData: submission.postData,
           };
           if (aParams) {
             for (let key in aParams) {
               params[key] = aParams[key];
             }
           }
-          openUILinkIn(submission.uri.spec, aWhere, params);
+          openTrustedLinkIn(submission.uri.spec, aWhere, params);
         ]]></body>
       </method>
     </implementation>
 
     <handlers>
       <handler event="command"><![CDATA[
         const target = event.originalTarget;
         if (target.engine) {
--- a/browser/components/search/content/searchReset.js
+++ b/browser/components/search/content/searchReset.js
@@ -47,17 +47,20 @@ function doSearch() {
   window.removeEventListener("unload", recordPageClosed);
 
   let win = window.QueryInterface(Ci.nsIInterfaceRequestor)
                   .getInterface(Ci.nsIWebNavigation)
                   .QueryInterface(Ci.nsIDocShellTreeItem)
                   .rootTreeItem
                   .QueryInterface(Ci.nsIInterfaceRequestor)
                   .getInterface(Ci.nsIDOMWindow);
-  win.openUILinkIn(submission.uri.spec, "current", false, submission.postData);
+  win.openTrustedLinkIn(submission.uri.spec, "current", {
+    allowThirdPartyFixup: false,
+    postData: submission.postData,
+  });
 }
 
 function openingSettings() {
   record(TELEMETRY_RESULT_ENUM.OPENED_SETTINGS);
   savePref("customized");
   window.removeEventListener("unload", recordPageClosed);
 }
 
--- a/browser/components/sessionstore/test/browser.ini
+++ b/browser/components/sessionstore/test/browser.ini
@@ -240,16 +240,17 @@ skip-if = !e10s
 [browser_send_async_message_oom.js]
 [browser_multiple_navigateAndRestore.js]
 run-if = e10s
 [browser_async_window_flushing.js]
 [browser_forget_async_closings.js]
 [browser_newtab_userTypedValue.js]
 [browser_parentProcessRestoreHash.js]
 run-if = e10s
+tags = openUILinkIn
 [browser_sessionStoreContainer.js]
 [browser_windowStateContainer.js]
 skip-if = os == "linux" && !debug
 [browser_1234021.js]
 [browser_remoteness_flip_on_restore.js]
 run-if = e10s
 [browser_background_tab_crash.js]
 run-if = e10s && crashreporter
--- a/browser/components/syncedtabs/TabListComponent.js
+++ b/browser/components/syncedtabs/TabListComponent.js
@@ -108,17 +108,17 @@ TabListComponent.prototype = {
 
   onBookmarkTab(uri, title) {
     this._window.top.PlacesCommandHook
       .bookmarkLink(this._window.top.PlacesUtils.bookmarksMenuFolderId, uri, title)
       .catch(Cu.reportError);
   },
 
   onOpenTab(url, where, params) {
-    this._window.openUILinkIn(url, where, params);
+    this._window.openTrustedLinkIn(url, where, params);
     BrowserUITelemetry.countSyncedTabEvent("open", "sidebar");
   },
 
   onOpenTabs(urls, where) {
     if (!OpenInTabsUtils.confirmOpenInTabs(urls.length, this._window)) {
       return;
     }
     if (where == "window") {
--- a/browser/components/syncedtabs/test/xpcshell/test_TabListComponent.js
+++ b/browser/components/syncedtabs/test/xpcshell/test_TabListComponent.js
@@ -84,17 +84,17 @@ add_task(async function testActions() {
     top: {
       PlacesCommandHook: {
         bookmarkLink() { return Promise.resolve(); }
       },
       PlacesUtils: { bookmarksMenuFolderId: "id" }
     },
     getBrowserURL() {},
     openDialog() {},
-    openUILinkIn() {}
+    openTrustedLinkIn() {}
   };
   let component = new TabListComponent({
     window: windowMock, store, View: null, SyncedTabs,
     clipboardHelper: clipboardHelperMock,
     getChromeWindow: getChromeWindowMock });
 
   sinon.stub(store, "getData");
   component.onFilter("query");
@@ -128,19 +128,19 @@ add_task(async function testActions() {
   component.onToggleBranch("foo-id");
   Assert.ok(store.toggleBranch.calledWith("foo-id"));
 
   sinon.spy(windowMock.top.PlacesCommandHook, "bookmarkLink");
   component.onBookmarkTab("uri", "title");
   Assert.equal(windowMock.top.PlacesCommandHook.bookmarkLink.args[0][1], "uri");
   Assert.equal(windowMock.top.PlacesCommandHook.bookmarkLink.args[0][2], "title");
 
-  sinon.spy(windowMock, "openUILinkIn");
+  sinon.spy(windowMock, "openTrustedLinkIn");
   component.onOpenTab("uri", "where", "params");
-  Assert.ok(windowMock.openUILinkIn.calledWith("uri", "where", "params"));
+  Assert.ok(windowMock.openTrustedLinkIn.calledWith("uri", "where", "params"));
 
   sinon.spy(chromeWindowMock.gBrowser, "loadTabs");
   let tabsToOpen = ["uri1", "uri2"];
   component.onOpenTabs(tabsToOpen, "where");
   Assert.ok(getChromeWindowMock.calledWith(windowMock));
   Assert.ok(chromeWindowMock.gBrowser.loadTabs.calledWith(tabsToOpen, {
     inBackground: false,
     replace: false,
--- a/browser/components/translation/Translation.jsm
+++ b/browser/components/translation/Translation.jsm
@@ -70,17 +70,17 @@ var Translation = {
 
     if (trUI.shouldShowInfoBar(aBrowser.currentURI))
       trUI.showTranslationInfoBar();
   },
 
   openProviderAttribution() {
     let attribution = this.supportedEngines[this.translationEngine];
     ChromeUtils.import("resource:///modules/RecentWindow.jsm");
-    RecentWindow.getMostRecentBrowserWindow().openUILinkIn(attribution, "tab");
+    RecentWindow.getMostRecentBrowserWindow().openTrustedLinkIn(attribution, "tab");
   },
 
   /**
    * The list of translation engines and their attributions.
    */
   supportedEngines: {
     "bing": "http://aka.ms/MicrosoftTranslatorAttribution",
     "yandex": "http://translate.yandex.com/"
--- a/browser/components/translation/translation-infobar.xml
+++ b/browser/components/translation/translation-infobar.xml
@@ -26,17 +26,17 @@
                    type="arrow" align="start">
           <xul:image class="translation-welcome-logo"/>
           <xul:vbox flex="1" class="translation-welcome-content">
             <xul:description class="translation-welcome-headline"
                              anonid="welcomeHeadline"/>
             <xul:description class="translation-welcome-body" anonid="welcomeBody"/>
             <xul:hbox align="center">
               <xul:label anonid="learnMore" class="plain text-link"
-                         onclick="openUILinkIn('https://support.mozilla.org/kb/automatic-translation', 'tab'); this.parentNode.parentNode.parentNode.hidePopup();"/>
+                         onclick="openTrustedLinkIn('https://support.mozilla.org/kb/automatic-translation', 'tab'); this.parentNode.parentNode.parentNode.hidePopup();"/>
               <xul:spacer flex="1"/>
               <xul:button class="translate-infobar-element" anonid="thanksButton"
                           onclick="this.parentNode.parentNode.parentNode.hidePopup();"/>
             </xul:hbox>
           </xul:vbox>
         </xul:panel>
         <xul:deck anonid="translationStates" selectedIndex="0">
 
--- a/browser/extensions/pocket/content/Pocket.jsm
+++ b/browser/extensions/pocket/content/Pocket.jsm
@@ -20,17 +20,17 @@ var Pocket = {
 
   openList(event) {
     let win = event.view;
     let where = win.whereToOpenLink(event);
     // Never override the current tab unless it's blank:
     if (where == "current" && !win.isTabEmpty(win.gBrowser.selectedTab)) {
       where = "tab";
     }
-    win.openUILinkIn(this.listURL, where);
+    win.openTrustedLinkIn(this.listURL, where);
   },
 
   /**
    * Functions related to the Pocket panel UI.
    */
   onShownInPhotonPageActionPanel(panel, iframe) {
     let window = panel.ownerGlobal;
     window.pktUI.setPhotonPageActionPanelFrame(iframe);
--- a/browser/extensions/pocket/content/main.js
+++ b/browser/extensions/pocket/content/main.js
@@ -144,17 +144,18 @@ var pktUI = (function() {
 
     /**
      * Show the sign-up panel
      */
     function showSignUp() {
         // AB test: Direct logged-out users to tab vs panel
         if (pktApi.getSignupPanelTabTestVariant() == "v2") {
             let site = Services.prefs.getCharPref("extensions.pocket.site");
-            openTabWithUrl("https://" + site + "/firefox_learnmore?s=ffi&t=autoredirect&tv=page_learnmore&src=ff_ext", true);
+            openTabWithUrl("https://" + site + "/firefox_learnmore?s=ffi&t=autoredirect&tv=page_learnmore&src=ff_ext",
+                           Services.scriptSecurityManager.getSystemPrincipal());
 
             // force the panel closed before it opens
             getPanel().hidePopup();
 
             return;
         }
 
         // Control: Show panel as normal
@@ -372,33 +373,21 @@ var pktUI = (function() {
         // send our own "show" event to the panel's script, so the
         // script can prepare the panel for display.
         var _showMessageId = "show";
         pktUIMessaging.addMessageListener(iframe, _showMessageId, function(panelId, data) {
             // Let panel know that it is ready
             pktUIMessaging.sendMessageToPanel(panelId, _showMessageId);
         });
 
-        // Open a new tab with a given url and activate if
+        // Open a new tab with a given url
         var _openTabWithUrlMessageId = "openTabWithUrl";
         pktUIMessaging.addMessageListener(iframe, _openTabWithUrlMessageId, function(panelId, data, contentPrincipal) {
-            try {
-              urlSecurityCheck(data.url, contentPrincipal, Services.scriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
-            } catch (ex) {
-              return;
-            }
-
-            // Check if the tab should become active after opening
-            var activate = true;
-            if (typeof data.activate !== "undefined") {
-                activate = data.activate;
-            }
-
             var url = data.url;
-            openTabWithUrl(url, activate);
+            openTabWithUrl(url, contentPrincipal);
             pktUIMessaging.sendResponseMessageToPanel(panelId, _openTabWithUrlMessageId, url);
         });
 
         // Close the panel
         var _closeMessageId = "close";
         pktUIMessaging.addMessageListener(iframe, _closeMessageId, function(panelId, data) {
             getPanel().hidePopup();
         });
@@ -509,43 +498,49 @@ var pktUI = (function() {
     }
 
     // -- Browser Navigation -- //
 
     /**
      * Open a new tab with a given url and notify the iframe panel that it was opened
      */
 
-    function openTabWithUrl(url) {
+    function openTabWithUrl(url, aTriggeringPrincipal) {
         let recentWindow = Services.wm.getMostRecentWindow("navigator:browser");
         if (!recentWindow) {
           Cu.reportError("Pocket: No open browser windows to openTabWithUrl");
           return;
         }
 
         // If the user is in permanent private browsing than this is not an issue,
         // since the current window will always share the same cookie jar as the other
         // windows.
         if (!PrivateBrowsingUtils.isWindowPrivate(recentWindow) ||
             PrivateBrowsingUtils.permanentPrivateBrowsing) {
-          recentWindow.openUILinkIn(url, "tab");
+          recentWindow.openWebLinkIn(url, "tab", {
+            triggeringPrincipal: aTriggeringPrincipal
+          });
           return;
         }
 
         let windows = Services.wm.getEnumerator("navigator:browser");
         while (windows.hasMoreElements()) {
           let win = windows.getNext();
           if (!PrivateBrowsingUtils.isWindowPrivate(win)) {
-            win.openUILinkIn(url, "tab");
+            win.openWebLinkIn(url, "tab", {
+              triggeringPrincipal: aTriggeringPrincipal
+            });
             return;
           }
         }
 
         // If there were no non-private windows opened already.
-        recentWindow.openUILinkIn(url, "window");
+        recentWindow.openWebLinkIn(url, "window", {
+          triggeringPrincipal: aTriggeringPrincipal
+        });
     }
 
 
     // -- Helper Functions -- //
 
     function getCurrentUrl() {
         return getBrowser().currentURI.spec;
     }
--- a/browser/extensions/screenshots/bootstrap.js
+++ b/browser/extensions/screenshots/bootstrap.js
@@ -104,17 +104,17 @@ const LibraryButton = {
     // this will be null, and we bail out early.
     if (!libraryViewInsertionPoint) {
       return;
     }
     const parent = libraryViewInsertionPoint.parentNode;
     const {nextSibling} = libraryViewInsertionPoint;
     const item = win.document.createElement("toolbarbutton");
     item.className = "subviewbutton subviewbutton-iconic";
-    item.addEventListener("command", () => win.openUILinkIn(this.PAGE_TO_OPEN, "tab"));
+    item.addEventListener("command", () => win.openTrustedLinkIn(this.PAGE_TO_OPEN, "tab"));
     item.id = this.ITEM_ID;
     const iconURL = this.ICON_URL;
     item.setAttribute("image", iconURL);
     item.setAttribute("label", this.LABEL);
 
     parent.insertBefore(item, nextSibling);
   },
 };
--- a/browser/modules/ContentCrashHandlers.jsm
+++ b/browser/modules/ContentCrashHandlers.jsm
@@ -869,17 +869,17 @@ var UnsubmittedCrashHandler = {
         if (onAction) {
           onAction();
         }
       },
     },
     {
       label: gNavigatorBundle.GetStringFromName("pendingCrashReports.viewAll"),
       callback() {
-        chromeWin.openUILinkIn("about:crashes", "tab");
+        chromeWin.openTrustedLinkIn("about:crashes", "tab");
         return true;
       },
     }];
 
     let eventCallback = (eventType) => {
       if (eventType == "dismissed") {
         // The user intentionally dismissed the notification,
         // which we interpret as meaning that they don't care
--- a/browser/modules/ContentSearch.jsm
+++ b/browser/modules/ContentSearch.jsm
@@ -242,17 +242,17 @@ var ContentSearch = {
       browser.loadURI(submission.uri.spec, {
         postData: submission.postData
       });
     } else {
       let params = {
         postData: submission.postData,
         inBackground: Services.prefs.getBoolPref("browser.tabs.loadInBackground"),
       };
-      win.openUILinkIn(submission.uri.spec, where, params);
+      win.openTrustedLinkIn(submission.uri.spec, where, params);
     }
     win.BrowserSearch.recordSearchInTelemetry(engine, data.healthReportKey,
                                               { selection: data.selection });
   },
 
   async getSuggestions(engineName, searchString, browser) {
     let engine = Services.search.getEngineByName(engineName);
     if (!engine) {
--- a/browser/modules/ExtensionsUI.jsm
+++ b/browser/modules/ExtensionsUI.jsm
@@ -90,17 +90,17 @@ var ExtensionsUI = {
         this.sideloaded.add(addon);
       }
         this._updateNotifications();
     } else {
       // This and all the accompanying about:newaddon code can eventually
       // be removed.  See bug 1331521.
       let win = RecentWindow.getMostRecentBrowserWindow();
       for (let addon of sideloaded) {
-        win.openUILinkIn(`about:newaddon?id=${addon.id}`, "tab");
+        win.openTrustedLinkIn(`about:newaddon?id=${addon.id}`, "tab");
       }
     }
   },
 
   async _checkNewDistroAddons() {
     let newDistroAddons = AddonManagerPrivate.getNewDistroAddons();
     if (!newDistroAddons) {
       return;
--- a/browser/modules/ProcessHangMonitor.jsm
+++ b/browser/modules/ProcessHangMonitor.jsm
@@ -458,17 +458,17 @@ var ProcessHangMonitor = {
                                             [addonName, brandBundle.getString("brandShortName")]);
 
       let linkText = bundle.getString("processHang.add-on.learn-more.text");
       let linkURL = "https://support.mozilla.org/kb/warning-unresponsive-script#w_other-causes";
 
       let link = doc.createElement("label");
       link.setAttribute("class", "text-link");
       link.setAttribute("role", "link");
-      link.setAttribute("onclick", `openUILinkIn(${JSON.stringify(linkURL)}, "tab")`);
+      link.setAttribute("onclick", `openTrustedLinkIn(${JSON.stringify(linkURL)}, "tab")`);
       link.setAttribute("value", linkText);
 
       message = doc.createDocumentFragment();
       message.appendChild(doc.createTextNode(label + " "));
       message.appendChild(link);
 
       buttons.unshift({
         label: bundle.getString("processHang.button_stop_sandbox.label"),
--- a/browser/modules/test/browser/browser.ini
+++ b/browser/modules/test/browser/browser.ini
@@ -2,16 +2,17 @@
 support-files =
   head.js
 
 [browser_BrowserErrorReporter.js]
 support-files =
   browser_BrowserErrorReporter.html
 [browser_BrowserUITelemetry_buckets.js]
 skip-if = !e10s # Bug 1373549
+tags = openUILinkIn
 [browser_BrowserUITelemetry_defaults.js]
 skip-if = !e10s # Bug 1373549
 [browser_BrowserUITelemetry_sidebar.js]
 skip-if = !e10s # Bug 1373549
 [browser_BrowserUITelemetry_syncedtabs.js]
 skip-if = !e10s # Bug 1373549
 [browser_ContentSearch.js]
 support-files =