Bug 1304219 - Part 1: Add a nsISpeculativeConnect.speculativeConnect2() interface which takes a principal as an additional argument. r=mayhemer, sr=mcmanus
authorTim Huang <tihuang@mozilla.com>
Mon, 24 Oct 2016 12:18:25 +0800
changeset 321279 b03f99accc585b2c850307398cc2500028e6bd8e
parent 321278 8d27bc400b98b035c5ee7614b732fb1001a21308
child 321280 89c941e929e33f40e380f20e20058bd962d1c299
push id30920
push userphilringnalda@gmail.com
push dateSat, 05 Nov 2016 20:41:02 +0000
treeherdermozilla-central@c44c01dfd264 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer, mcmanus
bugs1304219
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1304219 - Part 1: Add a nsISpeculativeConnect.speculativeConnect2() interface which takes a principal as an additional argument. r=mayhemer, sr=mcmanus
netwerk/base/nsIOService.cpp
netwerk/base/nsIOService.h
netwerk/base/nsISpeculativeConnect.idl
netwerk/ipc/NeckoParent.cpp
netwerk/ipc/NeckoParent.h
netwerk/ipc/PNecko.ipdl
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -47,16 +47,17 @@
 #include "nsThreadUtils.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/net/NeckoCommon.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/net/DNS.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/net/NeckoChild.h"
+#include "mozilla/dom/ContentParent.h"
 #include "CaptivePortalService.h"
 #include "ReferrerPolicy.h"
 #include "nsContentSecurityManager.h"
 #include "nsContentUtils.h"
 #include "xpcpublic.h"
 
 #ifdef MOZ_WIDGET_GONK
 #include "nsINetworkManager.h"
@@ -1759,51 +1760,59 @@ IOServiceProxyCallback::OnProxyAvailable
         speculativeHandler->SpeculativeConnect(uri, mCallbacks);
     }
 
     return NS_OK;
 }
 
 nsresult
 nsIOService::SpeculativeConnectInternal(nsIURI *aURI,
+                                        nsIPrincipal *aPrincipal,
                                         nsIInterfaceRequestor *aCallbacks,
                                         bool aAnonymous)
 {
     if (IsNeckoChild()) {
         ipc::URIParams params;
         SerializeURI(aURI, params);
-        gNeckoChild->SendSpeculativeConnect(params, aAnonymous);
+        gNeckoChild->SendSpeculativeConnect(params,
+                                            IPC::Principal(aPrincipal),
+                                            aAnonymous);
         return NS_OK;
     }
 
     // Check for proxy information. If there is a proxy configured then a
     // speculative connect should not be performed because the potential
     // reward is slim with tcp peers closely located to the browser.
     nsresult rv;
     nsCOMPtr<nsIProtocolProxyService> pps =
             do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsCOMPtr<nsIScriptSecurityManager> secMan(
-        do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
-    NS_ENSURE_SUCCESS(rv, rv);
-    nsCOMPtr<nsIPrincipal> systemPrincipal;
-    rv = secMan->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsIPrincipal> loadingPrincipal = aPrincipal;
+
+    // If the principal is given, we use this prinicpal directly. Otherwise,
+    // we fallback to use the system principal.
+    if (!aPrincipal) {
+        nsCOMPtr<nsIScriptSecurityManager> secMan(
+            do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
+        NS_ENSURE_SUCCESS(rv, rv);
+        rv = secMan->GetSystemPrincipal(getter_AddRefs(loadingPrincipal));
+        NS_ENSURE_SUCCESS(rv, rv);
+    }
 
     // dummy channel used to create a TCP connection.
     // we perform security checks on the *real* channel, responsible
     // for any network loads. this real channel just checks the TCP
     // pool if there is an available connection created by the
     // channel we create underneath - hence it's safe to use
     // the systemPrincipal as the loadingPrincipal for this channel.
     nsCOMPtr<nsIChannel> channel;
     rv = NewChannelFromURI2(aURI,
                             nullptr, // aLoadingNode,
-                            systemPrincipal,
+                            loadingPrincipal,
                             nullptr, //aTriggeringPrincipal,
                             nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                             nsIContentPolicy::TYPE_OTHER,
                             getter_AddRefs(channel));
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (aAnonymous) {
         nsLoadFlags loadFlags = 0;
@@ -1821,20 +1830,36 @@ nsIOService::SpeculativeConnectInternal(
     }
     return pps->AsyncResolve(channel, 0, callback, getter_AddRefs(cancelable));
 }
 
 NS_IMETHODIMP
 nsIOService::SpeculativeConnect(nsIURI *aURI,
                                 nsIInterfaceRequestor *aCallbacks)
 {
-    return SpeculativeConnectInternal(aURI, aCallbacks, false);
+    return SpeculativeConnectInternal(aURI, nullptr, aCallbacks, false);
+}
+
+NS_IMETHODIMP
+nsIOService::SpeculativeConnect2(nsIURI *aURI,
+                                 nsIPrincipal *aPrincipal,
+                                 nsIInterfaceRequestor *aCallbacks)
+{
+    return SpeculativeConnectInternal(aURI, aPrincipal, aCallbacks, false);
 }
 
 NS_IMETHODIMP
 nsIOService::SpeculativeAnonymousConnect(nsIURI *aURI,
                                          nsIInterfaceRequestor *aCallbacks)
 {
-    return SpeculativeConnectInternal(aURI, aCallbacks, true);
+    return SpeculativeConnectInternal(aURI, nullptr, aCallbacks, true);
+}
+
+NS_IMETHODIMP
+nsIOService::SpeculativeAnonymousConnect2(nsIURI *aURI,
+                                          nsIPrincipal *aPrincipal,
+                                          nsIInterfaceRequestor *aCallbacks)
+{
+    return SpeculativeConnectInternal(aURI, aPrincipal, aCallbacks, true);
 }
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/base/nsIOService.h
+++ b/netwerk/base/nsIOService.h
@@ -131,16 +131,17 @@ private:
 
     nsresult NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI,
                                                      nsIURI* aProxyURI,
                                                      uint32_t aProxyFlags,
                                                      nsILoadInfo* aLoadInfo,
                                                      nsIChannel** result);
 
     nsresult SpeculativeConnectInternal(nsIURI *aURI,
+                                        nsIPrincipal *aPrincipal,
                                         nsIInterfaceRequestor *aCallbacks,
                                         bool aAnonymous);
 
 private:
     bool                                 mOffline;
     mozilla::Atomic<bool, mozilla::Relaxed>  mOfflineForProfileChange;
     bool                                 mManageLinkStatus;
     bool                                 mConnectivity;
--- a/netwerk/base/nsISpeculativeConnect.idl
+++ b/netwerk/base/nsISpeculativeConnect.idl
@@ -1,40 +1,51 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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"
 
+interface nsIPrincipal;
 interface nsIURI;
 interface nsIInterfaceRequestor;
 
 [scriptable, uuid(d74a17ac-5b8a-4824-a309-b1f04a3c4aed)]
 interface nsISpeculativeConnect : nsISupports
 {
     /**
      * Called as a hint to indicate a new transaction for the URI is likely coming
      * soon. The implementer may use this information to start a TCP
      * and/or SSL level handshake for that resource immediately so that it is
      * ready and/or progressed when the transaction is actually submitted.
      *
      * No obligation is taken on by the implementer, nor is the submitter obligated
      * to actually open the new channel. 
      *
      * @param aURI the URI of the hinted transaction
+     * @param aPrincipal the principal that will be used for opening the
+     *        channel of the hinted transaction.
      * @param aCallbacks any security callbacks for use with SSL for interfaces
      *        such as nsIBadCertListener. May be null.
      *
      */
     void speculativeConnect(in nsIURI aURI,
                             in nsIInterfaceRequestor aCallbacks);
 
+    void speculativeConnect2(in nsIURI aURI,
+                             in nsIPrincipal aPrincipal,
+                             in nsIInterfaceRequestor aCallbacks);
+
     void speculativeAnonymousConnect(in nsIURI aURI,
                                      in nsIInterfaceRequestor aCallbacks);
+
+    void speculativeAnonymousConnect2(in nsIURI aURI,
+                                      in nsIPrincipal aPrincipal,
+                                      in nsIInterfaceRequestor aCallbacks);
 };
 
 /**
  * This is used to override the default values for various values (documented
  * inline) to determine whether or not to actually make a speculative
  * connection.
  */
 [builtinclass, uuid(1040ebe3-6ed1-45a6-8587-995e082518d7)]
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -674,25 +674,28 @@ bool
 NeckoParent::DeallocPDNSRequestParent(PDNSRequestParent* aParent)
 {
   DNSRequestParent *p = static_cast<DNSRequestParent*>(aParent);
   p->Release();
   return true;
 }
 
 bool
-NeckoParent::RecvSpeculativeConnect(const URIParams& aURI, const bool& aAnonymous)
+NeckoParent::RecvSpeculativeConnect(const URIParams& aURI,
+                                    const Principal& aPrincipal,
+                                    const bool& aAnonymous)
 {
   nsCOMPtr<nsISpeculativeConnect> speculator(gIOService);
   nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
+  nsCOMPtr<nsIPrincipal> principal(aPrincipal);
   if (uri && speculator) {
     if (aAnonymous) {
-      speculator->SpeculativeAnonymousConnect(uri, nullptr);
+      speculator->SpeculativeAnonymousConnect2(uri, principal, nullptr);
     } else {
-      speculator->SpeculativeConnect(uri, nullptr);
+      speculator->SpeculativeConnect2(uri, principal, nullptr);
     }
 
   }
   return true;
 }
 
 bool
 NeckoParent::RecvHTMLDNSPrefetch(const nsString& hostname,
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -150,17 +150,19 @@ protected:
   virtual PDNSRequestParent* AllocPDNSRequestParent(const nsCString& aHost,
                                                     const uint32_t& aFlags,
                                                     const nsCString& aNetworkInterface) override;
   virtual bool RecvPDNSRequestConstructor(PDNSRequestParent* actor,
                                           const nsCString& hostName,
                                           const uint32_t& flags,
                                           const nsCString& aNetworkInterface) override;
   virtual bool DeallocPDNSRequestParent(PDNSRequestParent*) override;
-  virtual bool RecvSpeculativeConnect(const URIParams& aURI, const bool& aAnonymous) override;
+  virtual bool RecvSpeculativeConnect(const URIParams& aURI,
+                                      const Principal& aPrincipal,
+                                      const bool& aAnonymous) override;
   virtual bool RecvHTMLDNSPrefetch(const nsString& hostname,
                                    const uint16_t& flags) override;
   virtual bool RecvCancelHTMLDNSPrefetch(const nsString& hostname,
                                          const uint16_t& flags,
                                          const nsresult& reason) override;
   virtual PWebSocketEventListenerParent*
     AllocPWebSocketEventListenerParent(const uint64_t& aInnerWindowID) override;
   virtual bool DeallocPWebSocketEventListenerParent(PWebSocketEventListenerParent*) override;
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -83,17 +83,17 @@ parent:
   /* Predictor Methods */
   async PredPredict(OptionalURIParams targetURI, OptionalURIParams sourceURI,
                     uint32_t reason, SerializedLoadContext loadContext,
                     bool hasVerifier);
   async PredLearn(URIParams targetURI, OptionalURIParams sourceURI,
                   uint32_t reason, SerializedLoadContext loadContext);
   async PredReset();
 
-  async SpeculativeConnect(URIParams uri, bool anonymous);
+  async SpeculativeConnect(URIParams uri, Principal principal, bool anonymous);
   async HTMLDNSPrefetch(nsString hostname, uint16_t flags);
   async CancelHTMLDNSPrefetch(nsString hostname, uint16_t flags, nsresult reason);
 
   /**
    * channelId is used to establish a connection between redirect channels in
    * the parent and the child when we're redirecting to a data: URI.
    */
   async PDataChannel(uint32_t channelId);
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -2203,23 +2203,26 @@ nsHttpHandler::Observe(nsISupports *subj
 
     return NS_OK;
 }
 
 // nsISpeculativeConnect
 
 nsresult
 nsHttpHandler::SpeculativeConnectInternal(nsIURI *aURI,
+                                          nsIPrincipal *aPrincipal,
                                           nsIInterfaceRequestor *aCallbacks,
                                           bool anonymous)
 {
     if (IsNeckoChild()) {
         ipc::URIParams params;
         SerializeURI(aURI, params);
-        gNeckoChild->SendSpeculativeConnect(params, anonymous);
+        gNeckoChild->SendSpeculativeConnect(params,
+                                            IPC::Principal(aPrincipal),
+                                            anonymous);
         return NS_OK;
     }
 
     if (!mHandlerActive)
         return NS_OK;
 
     MOZ_ASSERT(NS_IsMainThread());
     nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
@@ -2292,42 +2295,64 @@ nsHttpHandler::SpeculativeConnectInterna
     rv = aURI->GetPort(&port);
     if (NS_FAILED(rv))
         return rv;
 
     nsAutoCString username;
     aURI->GetUsername(username);
 
     NeckoOriginAttributes neckoOriginAttributes;
-    if (loadContext) {
-      DocShellOriginAttributes docshellOriginAttributes;
-      loadContext->GetOriginAttributes(docshellOriginAttributes);
-      neckoOriginAttributes.InheritFromDocShellToNecko(docshellOriginAttributes);
+    // If the principal is given, we use the originAttributes from this
+    // principal. Otherwise, we use the originAttributes from the
+    // loadContext.
+    if (aPrincipal) {
+        neckoOriginAttributes.InheritFromDocToNecko(
+            BasePrincipal::Cast(aPrincipal)->OriginAttributesRef());
+    } else if (loadContext) {
+        DocShellOriginAttributes docshellOriginAttributes;
+        loadContext->GetOriginAttributes(docshellOriginAttributes);
+        neckoOriginAttributes.InheritFromDocShellToNecko(docshellOriginAttributes);
     }
 
     auto *ci =
         new nsHttpConnectionInfo(host, port, EmptyCString(), username, nullptr,
                                  neckoOriginAttributes, usingSSL);
     ci->SetAnonymous(anonymous);
 
     return SpeculativeConnect(ci, aCallbacks);
 }
 
 NS_IMETHODIMP
 nsHttpHandler::SpeculativeConnect(nsIURI *aURI,
                                   nsIInterfaceRequestor *aCallbacks)
 {
-    return SpeculativeConnectInternal(aURI, aCallbacks, false);
+    return SpeculativeConnectInternal(aURI, nullptr, aCallbacks, false);
+}
+
+NS_IMETHODIMP
+nsHttpHandler::SpeculativeConnect2(nsIURI *aURI,
+                                   nsIPrincipal *aPrincipal,
+                                   nsIInterfaceRequestor *aCallbacks)
+{
+    return SpeculativeConnectInternal(aURI, aPrincipal, aCallbacks, false);
 }
 
 NS_IMETHODIMP
 nsHttpHandler::SpeculativeAnonymousConnect(nsIURI *aURI,
                                            nsIInterfaceRequestor *aCallbacks)
 {
-    return SpeculativeConnectInternal(aURI, aCallbacks, true);
+    return SpeculativeConnectInternal(aURI, nullptr, aCallbacks, true);
+}
+
+NS_IMETHODIMP
+nsHttpHandler::SpeculativeAnonymousConnect2(nsIURI *aURI,
+                                            nsIPrincipal *aPrincipal,
+                                            nsIInterfaceRequestor *aCallbacks)
+{
+    return SpeculativeConnectInternal(aURI, aPrincipal, aCallbacks, true);
 }
 
 void
 nsHttpHandler::TickleWifi(nsIInterfaceRequestor *cb)
 {
     if (!cb || !mWifiTickler)
         return;
 
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -634,16 +634,17 @@ public:
     }
 
 private:
     RefPtr<Tickler> mWifiTickler;
     void TickleWifi(nsIInterfaceRequestor *cb);
 
 private:
     nsresult SpeculativeConnectInternal(nsIURI *aURI,
+                                        nsIPrincipal *aPrincipal,
                                         nsIInterfaceRequestor *aCallbacks,
                                         bool anonymous);
 
     // UUID generator for channelIds
     nsCOMPtr<nsIUUIDGenerator> mUUIDGen;
 
 public:
     nsresult NewChannelId(nsID *channelId);