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 759752 e2463048aa8d56ff47dc1285448919fefcac797d
parent 759663 02aa9c921aedfd0e768a92a6a8c5cba1b14191c1
child 759753 8c4a987d6d8d3b8639ef53d36bfa92060f65de8a
push id100453
push userbmo:jkt@mozilla.com
push dateMon, 26 Feb 2018 15:22:58 +0000
reviewersgijs
bugs1374741
milestone60.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
@@ -316,17 +316,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"),
@@ -346,17 +346,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
@@ -740,17 +740,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
@@ -299,17 +299,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
@@ -922,17 +922,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);
@@ -2194,17 +2194,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("|");
@@ -2317,17 +2317,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",
@@ -2366,17 +2368,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);
@@ -3150,31 +3152,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") {
@@ -3857,17 +3859,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))
@@ -4055,17 +4057,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);
 
@@ -4225,17 +4227,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.
  */
@@ -6056,17 +6058,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,
+                 });
     }
   });
 
   event.stopPropagation();
 }
 
 function stripUnsafeProtocolOnPaste(pasteData) {
   // Don't allow pasting javascript URIs since we don't support
@@ -6858,17 +6862,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();
@@ -7034,17 +7038,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));
         }
@@ -8357,18 +8361,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.
@@ -8484,19 +8488,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() {
     let browser_tabs_restorebutton_pref = Services.prefs.getIntPref("browser.tabs.restorebutton");
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -777,30 +777,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) {
@@ -817,17 +814,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,
@@ -846,23 +842,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) {
@@ -905,33 +900,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 });
@@ -950,22 +940,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 = "";
@@ -995,21 +984,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 });
 
@@ -1194,18 +1182,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);
   },
 
@@ -1229,17 +1215,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() {
@@ -1399,17 +1384,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(Components.utils.reportError);
   },
 
@@ -1469,17 +1454,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
@@ -642,21 +642,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"/>
         <body><![CDATA[
@@ -865,17 +865,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
@@ -103,16 +103,25 @@ function openUILink(url, event, aIgnoreB
       allowThirdPartyFixup: aAllowThirdPartyFixup,
       postData: aPostData,
       referrerURI: aReferrerURI,
       referrerPolicy: Components.interfaces.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.scriptSecurityManger.createNullPrincipal({});
+    }
+  }
+
   let where = whereToOpenLink(event, aIgnoreButton, aIgnoreAlt);
   openUILinkIn(url, where, params);
 }
 
 
 /* whereToOpenLink() looks at an event to decide where to open a link.
  *
  * The event may be a mouse event (click, double-click, middle-click) or keypress event (enter).
@@ -158,53 +167,94 @@ 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
+ * Instead of allowThirdPartyFixup, you may also pass an object with any of
  * these properties:
  *   allowThirdPartyFixup (boolean)
  *   postData             (nsIInputStream)
  *   referrerURI          (nsIURI)
  *   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, aParamsOrAllowThirdPartyFixup, aPostData, aReferrerURI) {
   var params;
 
   if (arguments.length == 3 && typeof arguments[2] == "object") {
-    params = aAllowThirdPartyFixup;
+    params = aParamsOrAllowThirdPartyFixup;
   } else {
-    params = {
-      allowThirdPartyFixup: aAllowThirdPartyFixup,
-      postData: aPostData,
-      referrerURI: aReferrerURI,
-      referrerPolicy: Components.interfaces.nsIHttpChannel.REFERRER_POLICY_UNSET,
-    };
+    throw new Error("Required argument triggeringPrincipal missing within openUILinkIn");
   }
 
   params.fromChrome = true;
 
   openLinkIn(url, where, params);
 }
 
 /* eslint-disable complexity */
@@ -806,31 +856,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() {
   // Enable/disable the "Report Web Forgery" menu item.
   if (typeof gSafeBrowsing != "undefined") {
     gSafeBrowsing.setReportPhishingMenu();
   }
 }
@@ -918,17 +968,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
@@ -445,17 +445,19 @@ const CustomizableWidgets = [
       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.openUILink(tabInfo.url, e, {
+          triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({})
+        });
         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
@@ -210,17 +210,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;
     }
 
@@ -1235,17 +1235,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
@@ -576,17 +576,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
@@ -669,17 +669,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
@@ -503,17 +503,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.
@@ -828,17 +828,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);
         }
@@ -1470,17 +1470,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);
     }
@@ -1497,17 +1497,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) {
@@ -1757,17 +1757,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);
@@ -2772,17 +2772,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
@@ -784,17 +784,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
@@ -438,17 +438,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
@@ -720,17 +720,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
@@ -337,17 +337,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
@@ -469,17 +469,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
@@ -109,17 +109,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 (!PlacesUIUtils.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;
     }
     let parent = libraryViewInsertionPoint.parentNode;
     let {nextSibling} = libraryViewInsertionPoint;
     let 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;
     let iconURL = win.devicePixelRatio >= 1.1 ? this.ICON_URL_2X : 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
@@ -871,17 +871,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.loadURIWithFlags(submission.uri.spec,
                                Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null,
                                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
@@ -87,17 +87,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");
       }
     }
   },
 
   _updateNotifications() {
     if (this.sideloaded.size + this.updates.size == 0) {
       AppMenuNotifications.removeNotification("addon-alert");
     } else {
--- 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 =