Bug 1113898 Support for <a rel="noreferrer"> functionality r=IanN
authorNeil Rashbrook <neil@parkwaycc.co.uk>
Wed, 07 Jan 2015 21:52:34 +0000
changeset 25605 fb2e2de7d112de2c930024deaf2084eb2fc7962b
parent 25604 d891cfe1516a46e5532add5255b993a50adf2ffb
child 25606 437b4fb66f87a61ca63acde3a6d302033fdbf300
push id1850
push userclokep@gmail.com
push dateWed, 08 Mar 2017 19:29:12 +0000
treeherdercomm-esr52@028df196b2d9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersIanN
bugs1113898
Bug 1113898 Support for <a rel="noreferrer"> functionality r=IanN a=IanN for comm-release CLOSED TREE
suite/common/contentAreaClick.js
suite/common/nsContextMenu.js
suite/common/utilityOverlay.js
--- a/suite/common/contentAreaClick.js
+++ b/suite/common/contentAreaClick.js
@@ -52,17 +52,17 @@
       return true;
     }
 
     var isKeyCommand = (event.type == "command");
     var ceParams = hrefAndLinkNodeForClickEvent(event);
     if (ceParams) {
       var href = ceParams.href;
       if (isKeyCommand) {
-        openNewTabWith(href, event.target.ownerDocument, event.altKey);
+        openNewTabWith(href, event.target, event.altKey);
         event.stopPropagation();
       }
       else {
         // if in mailnews block the link left click if we determine
         // that this URL is phishy (i.e. a potential email scam) 
         if ("gMessengerBundle" in this && event.button < 2 &&
             isPhishingURL(ceParams.linkNode, false, href))
           return false;
@@ -83,64 +83,64 @@
         Services.prefs.getBoolPref("middlemouse.contentLoadURL") &&
         !Services.prefs.getBoolPref("general.autoScroll")) {
       middleMousePaste(event);
     }
 
     return true;
   }
 
-  function openNewTabOrWindow(event, href, doc)
+  function openNewTabOrWindow(event, href, node)
   {
     // should we open it in a new tab?
     if (Services.prefs.getBoolPref("browser.tabs.opentabfor.middleclick")) {
-      openNewTabWith(href, doc, null, event);
+      openNewTabWith(href, node, null, event);
       event.stopPropagation();
       return true;
     }
 
     // should we open it in a new window?
     if (Services.prefs.getBoolPref("middlemouse.openNewWindow")) {
       if (gPrivate)
-        openNewPrivateWith(href, doc);
+        openNewPrivateWith(href, node);
       else
-        openNewWindowWith(href, doc);
+        openNewWindowWith(href, node);
       event.stopPropagation();
       return true;
     }
 
     // let someone else deal with it
     return false;
   }
 
   function handleLinkClick(event, href, linkNode)
   {
     // Checking to make sure we are allowed to open this URL
     // (call to urlSecurityCheck) is now done within openNew... functions
 
-    var doc = linkNode.ownerDocument;
     switch (event.button) {
       case 0:                                                         // if left button clicked
         if (event.metaKey || event.ctrlKey) {                         // and meta or ctrl are down
-          if (openNewTabOrWindow(event, href, doc))
+          if (openNewTabOrWindow(event, href, linkNode))
             return true;
         }
         var saveModifier = GetBoolPref("ui.key.saveLink.shift", true);
         saveModifier = saveModifier ? event.shiftKey : event.altKey;
 
         if (saveModifier) {                                           // if saveModifier is down
+          var doc = linkNode.ownerDocument;
           saveURL(href, gatherTextUnder(linkNode), "SaveLinkTitle",
                   false, true, doc.documentURIObject, doc);
           return true;
         }
         if (event.altKey)                                             // if alt is down
           return true;                                                // do nothing
         return false;
       case 1:                                                         // if middle button clicked
-        if (openNewTabOrWindow(event, href, doc))
+        if (openNewTabOrWindow(event, href, linkNode))
           return true;
         break;
     }
     return false;
   }
 
   var gURIFixup = null;
 
--- a/suite/common/nsContextMenu.js
+++ b/suite/common/nsContextMenu.js
@@ -740,33 +740,31 @@ nsContextMenu.prototype = {
     Services.perms.add(uri, "image", Services.perms.DENY_ACTION);
   else
     Services.perms.remove(uri.host, "image");
   },
 
   // Open linked-to URL in a new tab.
   openLinkInTab: function(aEvent) {
     // Determine linked-to URL.
-    return openNewTabWith(this.linkURL, this.target.ownerDocument, null,
-                          aEvent);
+    return openNewTabWith(this.linkURL, this.link, null, aEvent);
   },
 
   // Open linked-to URL in a new window.
   openLinkInWindow: function() {
-    return openNewWindowWith(this.linkURL, this.target.ownerDocument);
+    return openNewWindowWith(this.linkURL, this.link);
   },
 
   // Open linked-to URL in a private window.
   openLinkInPrivateWindow: function() {
-    return openNewPrivateWith(this.linkURL, this.target.ownerDocument);
+    return openNewPrivateWith(this.linkURL, this.link);
   },
 
   // Open frame in a new tab.
   openFrameInTab: function(aEvent) {
-    // Determine linked-to URL.
     return openNewTabWith(this.target.ownerDocument.location.href,
                           this.target.ownerDocument, null, aEvent);
   },
 
   // Reload clicked-in frame.
   reloadFrame: function() {
     this.target.ownerDocument.location.reload();
   },
--- a/suite/common/utilityOverlay.js
+++ b/suite/common/utilityOverlay.js
@@ -974,85 +974,90 @@ function openAsExternal(aURL)
 
 /**
  * openNewTabWith: opens a new tab with the given URL.
  * openNewWindowWith: opens a new window with the given URL.
  * openNewPrivateWith: opens a private window with the given URL.
  *
  * @param aURL
  *        The URL to open (as a string).
- * @param aDocument
- *        The document from which the URL came, or null. This is used to set
+ * @param aNode
+ *        The node from which the URL came, or null. This is used to set
  *        the referrer header and to do a security check of whether the
- *        document is allowed to reference the URL. If null, there will be no
+ *        node is allowed to reference the URL. If null, there will be no
  *        referrer header and no security check.
  * @param aPostData
  *        Form POST data, or null.
  * @param aEvent
  *        The triggering event (for the purpose of determining whether to open
  *        in the background), or null.
  *        Legacy callers may use a boolean (aReverseBackgroundPref) here to
  *        reverse the background behaviour.
  * @param aAllowThirdPartyFixup
  *        If true, then we allow the URL text to be sent to third party
  *        services (e.g., Google's I Feel Lucky) for interpretation. This
  *        parameter may be undefined in which case it is treated as false.
  * @param [optional] aReferrer
- *        If aDocument is null, then this will be used as the referrer.
+ *        If aNode is null, then this will be used as the referrer.
  *        There will be no security check.
  */
-function openNewPrivateWith(aURL, aDoc, aPostData, aAllowThirdPartyFixup,
+function openNewPrivateWith(aURL, aNode, aPostData, aAllowThirdPartyFixup,
                             aReferrer)
 {
-  return openNewTabWindowOrExistingWith(kNewPrivate, aURL, aDoc, false,
+  return openNewTabWindowOrExistingWith(kNewPrivate, aURL, aNode, false,
                                         aPostData, aAllowThirdPartyFixup,
                                         aReferrer);
 }
 
-function openNewWindowWith(aURL, aDoc, aPostData, aAllowThirdPartyFixup,
+function openNewWindowWith(aURL, aNode, aPostData, aAllowThirdPartyFixup,
                            aReferrer)
 {
-  return openNewTabWindowOrExistingWith(kNewWindow, aURL, aDoc, false,
+  return openNewTabWindowOrExistingWith(kNewWindow, aURL, aNode, false,
                                         aPostData, aAllowThirdPartyFixup,
                                         aReferrer);
 }
 
-function openNewTabWith(aURL, aDoc, aPostData, aEvent,
+function openNewTabWith(aURL, aNode, aPostData, aEvent,
                         aAllowThirdPartyFixup, aReferrer)
 {
   var loadInBackground = Services.prefs.getBoolPref("browser.tabs.loadInBackground");
   if (arguments.length == 3 && typeof aPostData == "boolean")
   {
     // Handle legacy boolean parameter.
     if (aPostData)
     {
       loadInBackground = !loadInBackground;
     }
     aPostData = null;
   }
   else if (aEvent && aEvent.shiftKey)
   {
     loadInBackground = !loadInBackground;
   }
-  return openNewTabWindowOrExistingWith(kNewTab, aURL, aDoc, loadInBackground,
+  return openNewTabWindowOrExistingWith(kNewTab, aURL, aNode, loadInBackground,
                                         aPostData, aAllowThirdPartyFixup,
                                         aReferrer);
 }
 
-function openNewTabWindowOrExistingWith(aType, aURL, aDoc, aLoadInBackground,
+function openNewTabWindowOrExistingWith(aType, aURL, aNode, aLoadInBackground,
                                         aPostData, aAllowThirdPartyFixup,
                                         aReferrer)
 {
   // Make sure we are allowed to open this url
-  if (aDoc)
-    urlSecurityCheck(aURL, aDoc.nodePrincipal,
+  if (aNode)
+    urlSecurityCheck(aURL, aNode.nodePrincipal,
                      Components.interfaces.nsIScriptSecurityManager.STANDARD);
 
   // get referrer, if as external should be null
-  var referrerURI = aDoc ? aDoc.documentURIObject : aReferrer;
+  var referrerURI = aReferrer;
+  if (aNode instanceof Document)
+    referrerURI = aNode.documentURIObject;
+  else if (aNode instanceof Element &&
+           !/(?:^|\s)noreferrer(?:\s|$)/i.test(aNode.getAttribute("rel")))
+    referrerURI = aNode.ownerDocument.documentURIObject;
 
   var browserWin;
   // if we're not opening a new window, try and find existing window
   if (aType != kNewWindow && aType != kNewPrivate)
     browserWin = getTopWin();
 
   // Where appropriate we want to pass the charset of the
   // current document over to a new tab / window.
@@ -1087,17 +1092,18 @@ function openNewTabWindowOrExistingWith(
   }
 
   // open link in new tab
   var tab = browser.loadOneTab(aURL, {
               referrerURI: referrerURI,
               charset: originCharset,
               postData: aPostData,
               inBackground: aLoadInBackground,
-              allowThirdPartyFixup: aAllowThirdPartyFixup
+              allowThirdPartyFixup: aAllowThirdPartyFixup,
+              relatedToCurrent: !!aNode
             });
   if (!aLoadInBackground)
     browserWin.content.focus();
   return tab;
 }
 
 /**
  * Handle command events bubbling up from error page content