bug 1126065 - Update newChannelFromURI JavaScript callers. r=sicking
☠☠ backed out by 8de0c3602c7a ☠ ☠
authoraus@mozilla.com
Fri, 20 Feb 2015 11:56:09 -0800
changeset 230012 096a27bb1f8e5e4e3c90bfdb524c96aaf72a0d17
parent 230011 c8a4dfd89479921f7c5a5283ba9a28b480b012bf
child 230013 ab3f35ef16e2e79567a311e3095e6958a8fa49ff
push id14008
push userglacroix@mozilla.com
push dateFri, 20 Feb 2015 19:56:36 +0000
treeherderb2g-inbound@096a27bb1f8e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs1126065
milestone38.0a1
bug 1126065 - Update newChannelFromURI JavaScript callers. r=sicking
dom/browser-element/BrowserElementChildPreload.js
dom/browser-element/BrowserElementParent.js
dom/webidl/BrowserElement.webidl
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -811,47 +811,52 @@ BrowserElementChild.prototype = {
     if (sendSyncMsg('contextmenu', menuData)[0]) {
       e.preventDefault();
     } else {
       this._ctxHandlers = {};
     }
   },
 
   _getSystemCtxMenuData: function(elem) {
+    let documentURI = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
     if ((elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) ||
         (elem instanceof Ci.nsIDOMHTMLAreaElement && elem.href)) {
       return {uri: elem.href,
+              documentURI: documentURI,
               text: elem.textContent.substring(0, kLongestReturnedString)};
     }
     if (elem instanceof Ci.nsIImageLoadingContent && elem.currentURI) {
-      return {uri: elem.currentURI.spec};
+      return {uri: elem.currentURI.spec, documentURI: documentURI};
     }
     if (elem instanceof Ci.nsIDOMHTMLImageElement) {
-      return {uri: elem.src};
+      return {uri: elem.src, documentURI: documentURI};
     }
     if (elem instanceof Ci.nsIDOMHTMLMediaElement) {
       let hasVideo = !(elem.readyState >= elem.HAVE_METADATA &&
                        (elem.videoWidth == 0 || elem.videoHeight == 0));
-      return {uri: elem.currentSrc || elem.src, hasVideo: hasVideo};
+      return {uri: elem.currentSrc || elem.src,
+              hasVideo: hasVideo,
+              documentURI: documentURI};
     }
     if (elem instanceof Ci.nsIDOMHTMLInputElement &&
         elem.hasAttribute("name")) {
       // For input elements, we look for a parent <form> and if there is
       // one we return the form's method and action uri.
       let parent = elem.parentNode;
       while (parent) {
         if (parent instanceof Ci.nsIDOMHTMLFormElement &&
             parent.hasAttribute("action")) {
           let actionHref = docShell.QueryInterface(Ci.nsIWebNavigation)
                                    .currentURI
                                    .resolve(parent.getAttribute("action"));
           let method = parent.hasAttribute("method")
             ? parent.getAttribute("method").toLowerCase()
             : "get";
           return {
+            documentURI: documentURI,
             action: actionHref,
             method: method,
             name: elem.getAttribute("name"),
           }
         }
         parent = parent.parentNode;
       }
     }
--- a/dom/browser-element/BrowserElementParent.js
+++ b/dom/browser-element/BrowserElementParent.js
@@ -638,28 +638,29 @@ BrowserElementParent.prototype = {
 
   purgeHistory: defineDOMRequestMethod('purge-history'),
 
 
   download: function(_url, _options) {
     if (!this._isAlive()) {
       return null;
     }
-    let ioService =
-      Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
-    let uri = ioService.newURI(_url, null, null);
+    
+    let uri = Services.io.newURI(_url, null, null);
     let url = uri.QueryInterface(Ci.nsIURL);
 
+    debug('original _options = ' + uneval(_options));
+
     // Ensure we have _options, we always use it to send the filename.
     _options = _options || {};
     if (!_options.filename) {
       _options.filename = url.fileName;
     }
 
-    debug('_options = ' + uneval(_options));
+    debug('final _options = ' + uneval(_options));
 
     // Ensure we have a filename.
     if (!_options.filename) {
       throw Components.Exception("Invalid argument", Cr.NS_ERROR_INVALID_ARG);
     }
 
     let interfaceRequestor =
       this._frameLoader.loadContext.QueryInterface(Ci.nsIInterfaceRequestor);
@@ -727,35 +728,65 @@ BrowserElementParent.prototype = {
                                 aOffset, aCount) {
         this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
                                          aOffset, aCount);
       },
       QueryInterface: XPCOMUtils.generateQI([Ci.nsIStreamListener,
                                              Ci.nsIRequestObserver])
     };
 
-    let channel = ioService.newChannelFromURI(url);
+    // If we have a URI we'll use it to get the triggering principal to use, 
+    // if not available a null principal is acceptable.
+    let referrer = null;
+    let principal = null;
+    if (_options.referrer) {
+      // newURI can throw on malformed URIs.
+      try {
+        referrer = Services.io.newURI(_options.referrer, null, null);
+      }
+      catch(e) {
+        debug('Malformed referrer -- ' + e);
+      }
+      // This simply returns null if there is no principal available
+      // for the requested uri. This is an acceptable fallback when
+      // calling newChannelFromURI2.
+      principal = 
+        Services.scriptSecurityManager.getAppCodebasePrincipal(
+          referrer, 
+          this._frameLoader.loadContext.appId, 
+          this._frameLoader.loadContext.isInBrowserElement);
+    }
+
+    debug('Using principal? ' + !!principal);
+
+    let channel = 
+      Services.io.newChannelFromURI2(url,
+                                     null,       // No document. 
+                                     principal,  // Loading principal
+                                     principal,  // Triggering principal
+                                     Ci.nsILoadInfo.SEC_NORMAL,
+                                     Ci.nsIContentPolicy.TYPE_OTHER);
 
     // XXX We would set private browsing information prior to calling this.
     channel.notificationCallbacks = interfaceRequestor;
 
     // Since we're downloading our own local copy we'll want to bypass the
     // cache and local cache if the channel let's us specify this.
     let flags = Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS |
                 Ci.nsIChannel.LOAD_BYPASS_CACHE;
     if (channel instanceof Ci.nsICachingChannel) {
       debug('This is a caching channel. Forcing bypass.');
       flags |= Ci.nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE_IF_BUSY;
     }
 
     channel.loadFlags |= flags;
 
     if (channel instanceof Ci.nsIHttpChannel) {
-      debug('Setting HTTP referrer = ' + this._window.document.documentURIObject);
-      channel.referrer = this._window.document.documentURIObject;
+      debug('Setting HTTP referrer = ' + (referrer && referrer.spec)); 
+      channel.referrer = referrer;
       if (channel instanceof Ci.nsIHttpChannelInternal) {
         channel.forceAllowThirdPartyCookie = true;
       }
     }
 
     // Set-up complete, let's get things started.
     channel.asyncOpen(new DownloadListener(), null);
 
--- a/dom/webidl/BrowserElement.webidl
+++ b/dom/webidl/BrowserElement.webidl
@@ -3,16 +3,17 @@
  * 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/.
  */
 
 callback BrowserElementNextPaintEventCallback = void ();
 
 dictionary BrowserElementDownloadOptions {
   DOMString? filename;
+  DOMString? referrer;
 };
 
 [NoInterfaceObject]
 interface BrowserElement {
 };
 
 BrowserElement implements BrowserElementCommon;
 BrowserElement implements BrowserElementPrivileged;