Bug 1315143 - Make OCSP use Origin Attribute framework (Necko). r=mayhemer a=jcristau
authorJonathan Hao <jhao@mozilla.com>
Mon, 21 Nov 2016 11:43:06 +0800
changeset 352652 b045ef0bb77cd303ff439be352e349e8dc0c065d
parent 352651 c916ea845d3653d33cfcbcb9441bd4242c7b37de
child 352653 4d95d6b47637e3dd7a484d1a857acb33deba13f5
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer, jcristau
bugs1315143
milestone52.0a2
Bug 1315143 - Make OCSP use Origin Attribute framework (Necko). r=mayhemer a=jcristau
netwerk/base/nsISocketTransport.idl
netwerk/base/nsSocketTransport2.cpp
netwerk/base/nsSocketTransport2.h
netwerk/protocol/http/TunnelUtils.cpp
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/socket/nsISocketProvider.idl
netwerk/socket/nsSOCKSSocketProvider.cpp
netwerk/socket/nsUDPSocketProvider.cpp
--- a/netwerk/base/nsISocketTransport.idl
+++ b/netwerk/base/nsISocketTransport.idl
@@ -4,24 +4,27 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsITransport.idl"
 
 interface nsIInterfaceRequestor;
 interface nsINetAddr;
 
 %{ C++
+#include "mozilla/BasePrincipal.h"
 namespace mozilla {
 namespace net {
 union NetAddr;
 }
 }
 %}
 native NetAddr(mozilla::net::NetAddr);
 [ptr] native NetAddrPtr(mozilla::net::NetAddr);
+native NeckoOriginAttributes(mozilla::NeckoOriginAttributes);
+[ref] native const_OriginAttributesRef(const mozilla::NeckoOriginAttributes);
 
 /**
  * nsISocketTransport
  *
  * NOTE: Connection setup is triggered by opening an input or output stream,
  * it does not start on its own. Completion of the connection setup is
  * indicated by a STATUS_CONNECTED_TO notification to the event sink (if set).
  *
@@ -40,22 +43,30 @@ interface nsISocketTransport : nsITransp
 
     /**
      * Get the port for the underlying socket connection.
      * For Unix domain sockets, this is zero.
      */
     readonly attribute long port;
 
     /**
-     * This is only non-empty when "privacy.firstparty.isolate" is enabled.
-     * It is used to create sockets, and will eventually be used to isolate
-     * OCSP cache. It's the only way to carry it down to NSPR layers which are
-     * final consumers.  It must be set before the socket transport is built.
+     * The origin attributes are used to create sockets.  The first party domain
+     * will eventually be used to isolate OCSP cache and is only non-empty when
+     * "privacy.firstparty.isolate" is enabled.  Setting this is the only way to
+     * carry origin attributes down to NSPR layers which are final consumers.
+     * It must be set before the socket transport is built.
      */
-    attribute AUTF8String firstPartyDomain;
+    [implicit_jscontext, binaryname(ScriptableOriginAttributes)]
+    attribute jsval originAttributes;
+
+    [noscript, nostdcall, binaryname(GetOriginAttributes)]
+    NeckoOriginAttributes binaryGetOriginAttributes();
+
+    [noscript, nostdcall, binaryname(SetOriginAttributes)]
+    void binarySetOriginAttributes(in const_OriginAttributesRef aOriginAttrs);
 
     /**
      * The platform-specific network interface id that this socket
      * associated with. Note that this attribute can be only accessed
      * in the socket thread.
      */
     attribute ACString networkInterfaceId;
 
--- a/netwerk/base/nsSocketTransport2.cpp
+++ b/netwerk/base/nsSocketTransport2.cpp
@@ -17,16 +17,17 @@
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "plstr.h"
 #include "prerr.h"
 #include "NetworkActivityMonitor.h"
 #include "NSSErrorsService.h"
+#include "mozilla/dom/ToJSValue.h"
 #include "mozilla/net/NeckoChild.h"
 #include "nsThreadUtils.h"
 #include "nsISocketProviderService.h"
 #include "nsISocketProvider.h"
 #include "nsISSLSocketControl.h"
 #include "nsIPipe.h"
 #include "nsIClassInfoImpl.h"
 #include "nsURLHelper.h"
@@ -1164,32 +1165,32 @@ nsSocketTransport::BuildSocket(PRFileDes
                 // service to allocate a new socket
 
                 // when https proxying we want to just connect to the proxy as if
                 // it were the end host (i.e. expect the proxy's cert)
 
                 rv = provider->NewSocket(mNetAddr.raw.family,
                                          mHttpsProxy ? mProxyHost.get() : host,
                                          mHttpsProxy ? mProxyPort : port,
-                                         proxyInfo, mFirstPartyDomain,
+                                         proxyInfo, mOriginAttributes,
                                          controlFlags, &fd,
                                          getter_AddRefs(secinfo));
 
                 if (NS_SUCCEEDED(rv) && !fd) {
                     NS_NOTREACHED("NewSocket succeeded but failed to create a PRFileDesc");
                     rv = NS_ERROR_UNEXPECTED;
                 }
             }
             else {
                 // the socket has already been allocated, 
                 // so we just want the service to add itself
                 // to the stack (such as pushing an io layer)
                 rv = provider->AddToSocket(mNetAddr.raw.family,
                                            host, port, proxyInfo,
-                                           mFirstPartyDomain, controlFlags, fd,
+                                           mOriginAttributes, controlFlags, fd,
                                            getter_AddRefs(secinfo));
             }
 
             // controlFlags = 0; not used below this point...
             if (NS_FAILED(rv))
                 break;
 
             // if the service was ssl or starttls, we want to hold onto the socket info
@@ -2386,29 +2387,56 @@ NS_IMETHODIMP
 nsSocketTransport::SetNetworkInterfaceId(const nsACString_internal &aNetworkInterfaceId)
 {
     MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "wrong thread");
     mNetworkInterfaceId = aNetworkInterfaceId;
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSocketTransport::GetFirstPartyDomain(nsACString &value)
+nsSocketTransport::GetScriptableOriginAttributes(JSContext* aCx,
+    JS::MutableHandle<JS::Value> aOriginAttributes)
 {
-    value = mFirstPartyDomain;
+    if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aOriginAttributes))) {
+        return NS_ERROR_FAILURE;
+    }
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSocketTransport::SetFirstPartyDomain(const nsACString &value)
+nsSocketTransport::SetScriptableOriginAttributes(JSContext* aCx,
+    JS::Handle<JS::Value> aOriginAttributes)
 {
     MutexAutoLock lock(mLock);
     NS_ENSURE_FALSE(mFD.IsInitialized(), NS_ERROR_FAILURE);
 
-    mFirstPartyDomain = value;
+    NeckoOriginAttributes attrs;
+    if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    mOriginAttributes = attrs;
+    return NS_OK;
+}
+
+nsresult
+nsSocketTransport::GetOriginAttributes(NeckoOriginAttributes* aOriginAttributes)
+{
+    NS_ENSURE_ARG(aOriginAttributes);
+    *aOriginAttributes = mOriginAttributes;
+    return NS_OK;
+}
+
+nsresult
+nsSocketTransport::SetOriginAttributes(const NeckoOriginAttributes& aOriginAttributes)
+{
+    MutexAutoLock lock(mLock);
+    NS_ENSURE_FALSE(mFD.IsInitialized(), NS_ERROR_FAILURE);
+
+    mOriginAttributes = aOriginAttributes;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSocketTransport::GetPeerAddr(NetAddr *addr)
 {
     // once we are in the connected state, mNetAddr will not change.
     // so if we can verify that we are in the connected state, then
--- a/netwerk/base/nsSocketTransport2.h
+++ b/netwerk/base/nsSocketTransport2.h
@@ -298,21 +298,22 @@ private:
     nsCOMPtr<nsIProxyInfo> mProxyInfo;
     uint16_t     mProxyPort;
     uint16_t     mOriginPort;
     bool mProxyTransparent;
     bool mProxyTransparentResolvesHost;
     bool mHttpsProxy;
     uint32_t     mConnectionFlags;
 
-    // This is only non-empty when "privacy.firstparty.isolate" is enabled.
-    // It is used to create sockets. It's the only way to carry it down to NSPR
-    // layers which are final consumers.  It must be set before the socket
-    // transport is built.
-    nsCString    mFirstPartyDomain;
+    // The origin attributes are used to create sockets.  The first party domain
+    // will eventually be used to isolate OCSP cache and is only non-empty when
+    // "privacy.firstparty.isolate" is enabled.  Setting this is the only way to
+    // carry origin attributes down to NSPR layers which are final consumers.
+    // It must be set before the socket transport is built.
+    NeckoOriginAttributes mOriginAttributes;
     
     uint16_t         SocketPort() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyPort : mPort; }
     const nsCString &SocketHost() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyHost : mHost; }
 
     //-------------------------------------------------------------------------
     // members accessible only on the socket transport thread:
     //  (the exception being initialization/shutdown time)
     //-------------------------------------------------------------------------
--- a/netwerk/protocol/http/TunnelUtils.cpp
+++ b/netwerk/protocol/http/TunnelUtils.cpp
@@ -72,18 +72,19 @@ TLSFilterTransaction::TLSFilterTransacti
     sLayerMethods.close = FilterClose;
     sLayerMethodsPtr = &sLayerMethods;
   }
 
   mFD = PR_CreateIOLayerStub(sLayerIdentity, &sLayerMethods);
 
   if (provider && mFD) {
     mFD->secret = reinterpret_cast<PRFilePrivate *>(this);
-    provider->AddToSocket(PR_AF_INET, aTLSHost, aTLSPort, nullptr, EmptyCString(),
-                          0, mFD, getter_AddRefs(mSecInfo));
+    provider->AddToSocket(PR_AF_INET, aTLSHost, aTLSPort, nullptr,
+                          NeckoOriginAttributes(), 0, mFD,
+                          getter_AddRefs(mSecInfo));
   }
 
   if (mTransaction) {
     nsCOMPtr<nsIInterfaceRequestor> callbacks;
     mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks));
     nsCOMPtr<nsISSLSocketControl> secCtrl(do_QueryInterface(mSecInfo));
     if (secCtrl) {
       secCtrl->SetNotificationCallbacks(callbacks);
@@ -1588,18 +1589,42 @@ FWD_TS_ADDREF(GetScriptablePeerAddr, nsI
 FWD_TS_ADDREF(GetScriptableSelfAddr, nsINetAddr);
 FWD_TS_ADDREF(GetSecurityInfo, nsISupports);
 FWD_TS_ADDREF(GetSecurityCallbacks, nsIInterfaceRequestor);
 FWD_TS_PTR(IsAlive, bool);
 FWD_TS_PTR(GetConnectionFlags, uint32_t);
 FWD_TS(SetConnectionFlags, uint32_t);
 FWD_TS_PTR(GetRecvBufferSize, uint32_t);
 FWD_TS(SetRecvBufferSize, uint32_t);
-FWD_TS(SetFirstPartyDomain, const nsACString&);
-FWD_TS(GetFirstPartyDomain, nsACString&);
+
+nsresult
+SocketTransportShim::GetOriginAttributes(mozilla::NeckoOriginAttributes* aOriginAttributes)
+{
+  return mWrapped->GetOriginAttributes(aOriginAttributes);
+}
+
+nsresult
+SocketTransportShim::SetOriginAttributes(const mozilla::NeckoOriginAttributes& aOriginAttributes)
+{
+  return mWrapped->SetOriginAttributes(aOriginAttributes);
+}
+
+NS_IMETHODIMP
+SocketTransportShim::GetScriptableOriginAttributes(JSContext* aCx,
+  JS::MutableHandle<JS::Value> aOriginAttributes)
+{
+  return mWrapped->GetScriptableOriginAttributes(aCx, aOriginAttributes);
+}
+
+NS_IMETHODIMP
+SocketTransportShim::SetScriptableOriginAttributes(JSContext* aCx,
+  JS::Handle<JS::Value> aOriginAttributes)
+{
+  return mWrapped->SetScriptableOriginAttributes(aCx, aOriginAttributes);
+}
 
 NS_IMETHODIMP
 SocketTransportShim::GetHost(nsACString & aHost)
 {
   return mWrapped->GetHost(aHost);
 }
 
 NS_IMETHODIMP
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -3076,20 +3076,20 @@ nsHalfOpenSocket::SetupStreams(nsISocket
     }
 
     if (!Allow1918()) {
         tmpFlags |= nsISocketTransport::DISABLE_RFC1918;
     }
 
     socketTransport->SetConnectionFlags(tmpFlags);
 
-    nsAutoCString firstPartyDomain =
-      NS_ConvertUTF16toUTF8(mEnt->mConnInfo->GetOriginAttributes().mFirstPartyDomain);
-    if (!firstPartyDomain.IsEmpty()) {
-        socketTransport->SetFirstPartyDomain(firstPartyDomain);
+    NeckoOriginAttributes originAttributes =
+        mEnt->mConnInfo->GetOriginAttributes();
+    if (originAttributes != NeckoOriginAttributes()) {
+        socketTransport->SetOriginAttributes(originAttributes);
     }
 
     socketTransport->SetQoSBits(gHttpHandler->GetQoSBits());
 
     if (!ci->GetNetworkInterfaceId().IsEmpty()) {
         socketTransport->SetNetworkInterfaceId(ci->GetNetworkInterfaceId());
     }
 
--- a/netwerk/socket/nsISocketProvider.idl
+++ b/netwerk/socket/nsISocketProvider.idl
@@ -2,16 +2,22 @@
 /* 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 nsIProxyInfo;
 [ptr] native PRFileDescStar(struct PRFileDesc);
+native NeckoOriginAttributes(mozilla::NeckoOriginAttributes);
+[ref] native const_OriginAttributesRef(const mozilla::NeckoOriginAttributes);
+
+%{ C++
+#include "mozilla/BasePrincipal.h"
+%}
 
 /**
  * nsISocketProvider
  */
 [scriptable, uuid(508d5469-9e1e-4a08-b5b0-7cfebba1e51a)]
 interface nsISocketProvider : nsISupports
 {
     /**
@@ -31,44 +37,44 @@ interface nsISocketProvider : nsISupport
      *        Control flags that govern this connection (see below.)
      * @param aFileDesc
      *        The resulting PRFileDesc.
      * @param aSecurityInfo
      *        Any security info that should be associated with aFileDesc.  This
      *        object typically implements nsITransportSecurityInfo.
      */
     [noscript]
-    void newSocket(in long            aFamily,
-                   in string          aHost, 
-                   in long            aPort,
-                   in nsIProxyInfo    aProxy,
-                   in ACString        aFirstPartyDomain,
-                   in unsigned long   aFlags,
-                   out PRFileDescStar aFileDesc, 
-                   out nsISupports    aSecurityInfo);
+    void newSocket(in long                      aFamily,
+                   in string                    aHost, 
+                   in long                      aPort,
+                   in nsIProxyInfo              aProxy,
+                   in const_OriginAttributesRef aOriginAttributes,
+                   in unsigned long             aFlags,
+                   out PRFileDescStar           aFileDesc, 
+                   out nsISupports              aSecurityInfo);
 
     /**
      * addToSocket
      *
      * This function is called to allow the socket provider to layer a
      * PRFileDesc on top of another PRFileDesc.  For example, SSL via a SOCKS
      * proxy.
      *
      * Parameters are the same as newSocket with the exception of aFileDesc,
      * which is an in-param instead.
      */
     [noscript]
-    void addToSocket(in long           aFamily,
-                     in string         aHost, 
-                     in long           aPort,
-                     in nsIProxyInfo   aProxy,
-                     in ACString       aFirstPartyDomain,
-                     in unsigned long  aFlags,
-                     in PRFileDescStar aFileDesc, 
-                     out nsISupports   aSecurityInfo);
+    void addToSocket(in long                      aFamily,
+                     in string                    aHost, 
+                     in long                      aPort,
+                     in nsIProxyInfo              aProxy,
+                     in const_OriginAttributesRef aOriginAttributes,
+                     in unsigned long             aFlags,
+                     in PRFileDescStar            aFileDesc, 
+                     out nsISupports              aSecurityInfo);
 
     /**
      * PROXY_RESOLVES_HOST
      *
      * This flag is set if the proxy is to perform hostname resolution instead
      * of the client.  When set, the hostname parameter passed when in this
      * interface will be used instead of the address structure passed for a
      * later connect et al. request.
--- a/netwerk/socket/nsSOCKSSocketProvider.cpp
+++ b/netwerk/socket/nsSOCKSSocketProvider.cpp
@@ -6,16 +6,18 @@
 
 #include "nsIServiceManager.h"
 #include "nsNamedPipeIOLayer.h"
 #include "nsSOCKSSocketProvider.h"
 #include "nsSOCKSIOLayer.h"
 #include "nsCOMPtr.h"
 #include "nsError.h"
 
+using mozilla::NeckoOriginAttributes;
+
 //////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS(nsSOCKSSocketProvider, nsISocketProvider)
 
 nsresult
 nsSOCKSSocketProvider::CreateV4(nsISupports *aOuter, REFNSIID aIID, void **aResult)
 {
     nsresult rv;
@@ -41,17 +43,17 @@ nsSOCKSSocketProvider::CreateV5(nsISuppo
     return rv;
 }
 
 NS_IMETHODIMP
 nsSOCKSSocketProvider::NewSocket(int32_t family,
                                  const char *host, 
                                  int32_t port,
                                  nsIProxyInfo *proxy,
-                                 const nsACString &firstPartyDomain,
+                                 const NeckoOriginAttributes &originAttributes,
                                  uint32_t flags,
                                  PRFileDesc **result,
                                  nsISupports **socksInfo)
 {
     PRFileDesc *sock;
 
 #if defined(XP_WIN)
     nsAutoCString proxyHost;
@@ -83,17 +85,17 @@ nsSOCKSSocketProvider::NewSocket(int32_t
     return NS_ERROR_SOCKET_CREATE_FAILED;
 }
 
 NS_IMETHODIMP
 nsSOCKSSocketProvider::AddToSocket(int32_t family,
                                    const char *host,
                                    int32_t port,
                                    nsIProxyInfo *proxy,
-                                   const nsACString &firstPartyDomain,
+                                   const NeckoOriginAttributes &originAttributes,
                                    uint32_t flags,
                                    PRFileDesc *sock,
                                    nsISupports **socksInfo)
 {
     nsresult rv = nsSOCKSIOLayerAddToSocket(family,
                                             host, 
                                             port,
                                             proxy,
--- a/netwerk/socket/nsUDPSocketProvider.cpp
+++ b/netwerk/socket/nsUDPSocketProvider.cpp
@@ -1,28 +1,30 @@
 /* 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 "nsUDPSocketProvider.h"
 
 #include "nspr.h"
 
+using mozilla::NeckoOriginAttributes;
+
 NS_IMPL_ISUPPORTS(nsUDPSocketProvider, nsISocketProvider)
 
 nsUDPSocketProvider::~nsUDPSocketProvider()
 {
 }
 
 NS_IMETHODIMP 
 nsUDPSocketProvider::NewSocket(int32_t aFamily,
                                const char *aHost, 
                                int32_t aPort, 
                                nsIProxyInfo *aProxy,
-                               const nsACString &firstPartyDomain,
+                               const NeckoOriginAttributes &originAttributes,
                                uint32_t aFlags,
                                PRFileDesc * *aFileDesc, 
                                nsISupports **aSecurityInfo)
 {
     NS_ENSURE_ARG_POINTER(aFileDesc);
   
     PRFileDesc* udpFD = PR_OpenUDPSocket(aFamily);
     if (!udpFD)
@@ -32,17 +34,17 @@ nsUDPSocketProvider::NewSocket(int32_t a
     return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsUDPSocketProvider::AddToSocket(int32_t aFamily,
                                  const char *aHost,
                                  int32_t aPort,
                                  nsIProxyInfo *aProxy,
-                                 const nsACString &firstPartyDomain,
+                                 const NeckoOriginAttributes &originAttributes,
                                  uint32_t aFlags,
                                  struct PRFileDesc * aFileDesc,
                                  nsISupports **aSecurityInfo)
 {
     // does not make sense to strap a UDP socket onto an existing socket
     NS_NOTREACHED("Cannot layer UDP socket on an existing socket");
     return NS_ERROR_UNEXPECTED;
 }