Bug 1379842 - Check content principal when dragging and dropping from browser. r=smaug, a=gchang
authorTooru Fujisawa <arai_a@mac.com>
Thu, 10 Aug 2017 09:43:35 +0900
changeset 423586 dc46fc892938e6b8d449af75a129603ef55035c5
parent 423585 df818e102acdcce0430cd0d782b2fb46921f2f95
child 423587 efabe9b3a88e0cb1bcb092b34e0291ac99759471
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, gchang
bugs1379842
milestone56.0
Bug 1379842 - Check content principal when dragging and dropping from browser. r=smaug, a=gchang
browser/base/content/browser.js
browser/base/content/tabbrowser.xml
dom/base/contentAreaDropListener.js
dom/base/nsIDroppedLinkHandler.idl
toolkit/content/widgets/browser.xml
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3616,16 +3616,20 @@ var browserDragAndDrop = {
   canDropLink: aEvent => Services.droppedLinkHandler.canDropLink(aEvent, true),
 
   dragOver(aEvent) {
     if (this.canDropLink(aEvent)) {
       aEvent.preventDefault();
     }
   },
 
+  getTriggeringPrincipal(aEvent) {
+    return Services.droppedLinkHandler.getTriggeringPrincipal(aEvent);
+  },
+
   dropLinks(aEvent, aDisallowInherit) {
     return Services.droppedLinkHandler.dropLinks(aEvent, aDisallowInherit);
   }
 };
 
 var homeButtonObserver = {
   onDrop(aEvent) {
       // disallow setting home pages that inherit the principal
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -7284,22 +7284,17 @@
             inBackground = !inBackground;
 
           let targetTab = this._getDragTargetTab(event, true);
           let userContextId = this.selectedItem.getAttribute("usercontextid");
           let replace = !!targetTab;
           let newIndex = this._getDropIndex(event, true);
           let urls = links.map(link => link.url);
 
-
-          // Bug 1367038: mozSourceNode is null if the drag event originated
-          // in an external application - needs better fallback!
-          let triggeringPrincipal = dt.mozSourceNode
-            ? dt.mozSourceNode.nodePrincipal
-            : Services.scriptSecurityManager.getSystemPrincipal();
+          let triggeringPrincipal = browserDragAndDrop.getTriggeringPrincipal(event);
           this.tabbrowser.loadTabs(urls, {
             inBackground,
             replace,
             allowThirdPartyFixup: true,
             targetTab,
             newIndex,
             userContextId,
             triggeringPrincipal,
--- a/dom/base/contentAreaDropListener.js
+++ b/dom/base/contentAreaDropListener.js
@@ -117,25 +117,52 @@ ContentAreaDropListener.prototype =
     // uriString is a valid URI, so do the security check.
     let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].
                    getService(Ci.nsIScriptSecurityManager);
     let sourceNode = dataTransfer.mozSourceNode;
     let flags = secMan.STANDARD;
     if (disallowInherit)
       flags |= secMan.DISALLOW_INHERIT_PRINCIPAL;
 
-    // Use file:/// as the default uri so that drops of file URIs are always allowed
-    let principal = sourceNode ? sourceNode.nodePrincipal
-                               : secMan.createCodebasePrincipal(ioService.newURI("file:///"), {});
-
+    let principal;
+    if (sourceNode) {
+      principal = this._getTriggeringPrincipalFromSourceNode(sourceNode);
+    } else {
+      // Use file:/// as the default uri so that drops of file URIs are always
+      // allowed.
+      principal = secMan.createCodebasePrincipal(ioService.newURI("file:///"), {});
+    }
     secMan.checkLoadURIStrWithPrincipal(principal, uriString, flags);
 
     return uriString;
   },
 
+  _getTriggeringPrincipalFromSourceNode: function(aSourceNode)
+  {
+    if (aSourceNode.localName == "browser" &&
+        aSourceNode.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul") {
+      return aSourceNode.contentPrincipal;
+    }
+    return aSourceNode.nodePrincipal;
+  },
+
+  getTriggeringPrincipal: function(aEvent)
+  {
+    let dataTransfer = aEvent.dataTransfer;
+    let sourceNode = dataTransfer.mozSourceNode;
+    if (sourceNode) {
+      return this._getTriggeringPrincipalFromSourceNode(sourceNode, false);
+    }
+    // Bug 1367038: mozSourceNode is null if the drag event originated
+    // in an external application - needs better fallback!
+    let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].
+                   getService(Ci.nsIScriptSecurityManager);
+    return secMan.getSystemPrincipal();
+  },
+
   canDropLink: function(aEvent, aAllowSameDocument)
   {
     if (this._eventTargetIsDisabled(aEvent))
       return false;
 
     let dataTransfer = aEvent.dataTransfer;
     let types = dataTransfer.types;
     if (!types.includes("application/x-moz-file") &&
--- a/dom/base/nsIDroppedLinkHandler.idl
+++ b/dom/base/nsIDroppedLinkHandler.idl
@@ -1,13 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
+#include "nsIPrincipal.idl"
 
 interface nsIDOMDragEvent;
 
 [scriptable, uuid(69E14F91-2E09-4CA6-A511-A715C99A2804)]
 interface nsIDroppedLinkItem : nsISupports
 {
   /**
    * Returns the URL of the link.
@@ -72,9 +73,15 @@ interface nsIDroppedLinkHandler : nsISup
    *    the user into a dragging a chrome url, for example.
    *  - aDisallowInherit is true, and the URI being dropped would inherit the
    *    current document's security context (URI_INHERITS_SECURITY_CONTEXT).
    */
   void dropLinks(in nsIDOMDragEvent aEvent,
                  [optional] in boolean aDisallowInherit,
                  [optional] out unsigned long aCount,
                  [retval, array, size_is(aCount)] out nsIDroppedLinkItem aLinks);
+
+  /**
+   * Given a drop event aEvent, determines the triggering principal for the
+   * event and returns it.
+   */
+  nsIPrincipal getTriggeringPrincipal(in nsIDOMDragEvent aEvent);
 };
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -1667,27 +1667,17 @@
         try {
           // Pass true to prevent the dropping of javascript:/data: URIs
           var links = linkHandler.dropLinks(event, true);
         } catch (ex) {
           return;
         }
 
         if (links.length) {
-          // Bug 1368481: mozSourceNode is null if the drag event originated
-          // in an external application - needs better fallback!
-          let triggeringPrincipal;
-          let sourceNode = event.dataTransfer.mozSourceNode;
-          if (sourceNode) {
-            triggeringPrincipal = sourceNode.nodePrincipal;
-          } else {
-            var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"].
-              getService(Components.interfaces.nsIScriptSecurityManager);
-            triggeringPrincipal = secMan.getSystemPrincipal();
-          }
+          let triggeringPrincipal = linkHandler.getTriggeringPrincipal(event);
           this.droppedLinkHandler(event, links, triggeringPrincipal);
         }
       ]]>
       </handler>
     </handlers>
 
   </binding>