From 3086d13d88cd254c40f3590d548abd5db1e858d7 Mon Sep 17 00:00:00 2001 From: Arthur Edelstein Date: Mon, 6 Jun 2016 00:56:09 -0700 Subject: [PATCH] Bug 16998: Isolate link rel=preconnect to first party --- dom/base/nsDocument.cpp | 8 +++-- netwerk/base/nsIOService.cpp | 41 ++++++++++++++++++++++--- netwerk/base/nsIOService.h | 1 + netwerk/base/nsISpeculativeConnect.idl | 11 ++++++- netwerk/ipc/NeckoParent.cpp | 7 +++-- netwerk/ipc/NeckoParent.h | 3 +- netwerk/ipc/PNecko.ipdl | 2 +- netwerk/protocol/http/nsHttpHandler.cpp | 27 +++++++++++++--- netwerk/protocol/http/nsHttpHandler.h | 1 + 9 files changed, 84 insertions(+), 17 deletions(-) diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index c0c2040dbb311..c450e7df4226a 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -246,6 +246,8 @@ #include "nsISpeculativeConnect.h" +#include "ThirdPartyUtil.h" + #ifdef MOZ_MEDIA_NAVIGATOR #include "mozilla/MediaManager.h" #endif // MOZ_MEDIA_NAVIGATOR @@ -9750,10 +9752,12 @@ nsDocument::MaybePreconnect(nsIURI* aOrigURI, mozilla::CORSMode aCORSMode) return; } + nsCString firstPartyHost; + ThirdPartyUtil::GetFirstPartyHost(this, firstPartyHost); if (aCORSMode == CORS_ANONYMOUS) { - speculator->SpeculativeAnonymousConnect(uri, nullptr); + speculator->SpeculativeAnonymousConnectIsolated(uri, firstPartyHost, nullptr); } else { - speculator->SpeculativeConnect(uri, nullptr); + speculator->SpeculativeConnectIsolated(uri, firstPartyHost, nullptr); } } diff --git a/netwerk/base/nsIOService.cpp b/netwerk/base/nsIOService.cpp index ad86c9524dca6..a864d0e546f96 100644 --- a/netwerk/base/nsIOService.cpp +++ b/netwerk/base/nsIOService.cpp @@ -51,6 +51,7 @@ #include "ClosingService.h" #include "ReferrerPolicy.h" #include "nsContentSecurityManager.h" +#include "ThirdPartyUtil.h" #ifdef MOZ_WIDGET_GONK #include "nsINetworkManager.h" @@ -1822,10 +1823,14 @@ IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIChannel *cha nsLoadFlags loadFlags = 0; channel->GetLoadFlags(&loadFlags); + + nsCString firstPartyHost; + ThirdPartyUtil::GetFirstPartyHost(channel, firstPartyHost); + if (loadFlags & nsIRequest::LOAD_ANONYMOUS) { - speculativeHandler->SpeculativeAnonymousConnect(uri, mCallbacks); + speculativeHandler->SpeculativeAnonymousConnectIsolated(uri, firstPartyHost, mCallbacks); } else { - speculativeHandler->SpeculativeConnect(uri, mCallbacks); + speculativeHandler->SpeculativeConnectIsolated(uri, firstPartyHost, mCallbacks); } return NS_OK; @@ -1833,6 +1838,7 @@ IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIChannel *cha nsresult nsIOService::SpeculativeConnectInternal(nsIURI *aURI, + const nsACString& aIsolationKey, nsIInterfaceRequestor *aCallbacks, bool aAnonymous) { @@ -1867,6 +1873,17 @@ nsIOService::SpeculativeConnectInternal(nsIURI *aURI, getter_AddRefs(channel)); NS_ENSURE_SUCCESS(rv, rv); + // If we have an isolation key, use it as the document URI for this channel. + if (!aIsolationKey.IsEmpty()) { + nsCOMPtr channelInternal(do_QueryInterface(channel)); + if (channelInternal) { + nsCString documentURISpec("https://"); + documentURISpec.Append(aIsolationKey); + nsCOMPtr documentURI; + /* nsresult rv = */ NS_NewURI(getter_AddRefs(documentURI), documentURISpec); + channelInternal->SetDocumentURI(documentURI); + } + } if (aAnonymous) { nsLoadFlags loadFlags = 0; channel->GetLoadFlags(&loadFlags); @@ -1884,18 +1901,34 @@ nsIOService::SpeculativeConnectInternal(nsIURI *aURI, return pps->AsyncResolve(channel, 0, callback, getter_AddRefs(cancelable)); } +NS_IMETHODIMP +nsIOService::SpeculativeConnectIsolated(nsIURI *aURI, + const nsACString& aIsolationKey, + nsIInterfaceRequestor *aCallbacks) +{ + return SpeculativeConnectInternal(aURI, aIsolationKey, aCallbacks, false); +} + NS_IMETHODIMP nsIOService::SpeculativeConnect(nsIURI *aURI, nsIInterfaceRequestor *aCallbacks) { - return SpeculativeConnectInternal(aURI, aCallbacks, false); + return SpeculativeConnectInternal(aURI, EmptyCString(), aCallbacks, false); +} + +NS_IMETHODIMP +nsIOService::SpeculativeAnonymousConnectIsolated(nsIURI *aURI, + const nsACString& aIsolationKey, + nsIInterfaceRequestor *aCallbacks) +{ + return SpeculativeConnectInternal(aURI, aIsolationKey, aCallbacks, true); } NS_IMETHODIMP nsIOService::SpeculativeAnonymousConnect(nsIURI *aURI, nsIInterfaceRequestor *aCallbacks) { - return SpeculativeConnectInternal(aURI, aCallbacks, true); + return SpeculativeConnectInternal(aURI, EmptyCString(), aCallbacks, true); } void diff --git a/netwerk/base/nsIOService.h b/netwerk/base/nsIOService.h index e948ffdfbb2ba..308cee76afcd2 100644 --- a/netwerk/base/nsIOService.h +++ b/netwerk/base/nsIOService.h @@ -133,6 +133,7 @@ private: nsIChannel** result); nsresult SpeculativeConnectInternal(nsIURI *aURI, + const nsACString& aIsolationKey, nsIInterfaceRequestor *aCallbacks, bool aAnonymous); diff --git a/netwerk/base/nsISpeculativeConnect.idl b/netwerk/base/nsISpeculativeConnect.idl index 15d63e1071470..eed95703ba8f3 100644 --- a/netwerk/base/nsISpeculativeConnect.idl +++ b/netwerk/base/nsISpeculativeConnect.idl @@ -8,7 +8,7 @@ interface nsIURI; interface nsIInterfaceRequestor; -[scriptable, uuid(d74a17ac-5b8a-4824-a309-b1f04a3c4aed)] +[scriptable, uuid(60cf321d-9f09-403a-b8b6-db221e6ca3a1)] interface nsISpeculativeConnect : nsISupports { /** @@ -21,6 +21,7 @@ interface nsISpeculativeConnect : nsISupports * to actually open the new channel. * * @param aURI the URI of the hinted transaction + * @param aIsolationKey the isolation key for the connection * @param aCallbacks any security callbacks for use with SSL for interfaces * such as nsIBadCertListener. May be null. * @@ -30,6 +31,14 @@ interface nsISpeculativeConnect : nsISupports void speculativeAnonymousConnect(in nsIURI aURI, in nsIInterfaceRequestor aCallbacks); + + void speculativeConnectIsolated(in nsIURI aURI, + in AUTF8String aIsolationKey, + in nsIInterfaceRequestor aCallbacks); + + void speculativeAnonymousConnectIsolated(in nsIURI aURI, + in AUTF8String aIsolationKey, + in nsIInterfaceRequestor aCallbacks); }; /** diff --git a/netwerk/ipc/NeckoParent.cpp b/netwerk/ipc/NeckoParent.cpp index 796e78f82c17b..fa4911b7a7d27 100644 --- a/netwerk/ipc/NeckoParent.cpp +++ b/netwerk/ipc/NeckoParent.cpp @@ -728,15 +728,16 @@ NeckoParent::DeallocPRemoteOpenFileParent(PRemoteOpenFileParent* actor) } bool -NeckoParent::RecvSpeculativeConnect(const URIParams& aURI, const bool& aAnonymous) +NeckoParent::RecvSpeculativeConnect(const URIParams& aURI, const bool& aAnonymous, + const nsCString& aIsolationKey) { nsCOMPtr speculator(gIOService); nsCOMPtr uri = DeserializeURI(aURI); if (uri && speculator) { if (aAnonymous) { - speculator->SpeculativeAnonymousConnect(uri, nullptr); + speculator->SpeculativeAnonymousConnectIsolated(uri, aIsolationKey, nullptr); } else { - speculator->SpeculativeConnect(uri, nullptr); + speculator->SpeculativeConnectIsolated(uri, aIsolationKey, nullptr); } } diff --git a/netwerk/ipc/NeckoParent.h b/netwerk/ipc/NeckoParent.h index 508ab6fcb39bf..900328c78d7c2 100644 --- a/netwerk/ipc/NeckoParent.h +++ b/netwerk/ipc/NeckoParent.h @@ -167,7 +167,8 @@ protected: 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 bool& aAnonymous, + const nsCString& aFirstPartyHost) override; virtual bool RecvHTMLDNSPrefetch(const nsString& hostname, const uint16_t& flags) override; virtual bool RecvCancelHTMLDNSPrefetch(const nsString& hostname, diff --git a/netwerk/ipc/PNecko.ipdl b/netwerk/ipc/PNecko.ipdl index 2e1f2f5182978..0d0c7f8aca66e 100644 --- a/netwerk/ipc/PNecko.ipdl +++ b/netwerk/ipc/PNecko.ipdl @@ -89,7 +89,7 @@ parent: URIParams fileuri, OptionalURIParams appuri); - SpeculativeConnect(URIParams uri, bool anonymous); + SpeculativeConnect(URIParams uri, bool anonymous, nsCString isolationKey); HTMLDNSPrefetch(nsString hostname, uint16_t flags); CancelHTMLDNSPrefetch(nsString hostname, uint16_t flags, nsresult reason); diff --git a/netwerk/protocol/http/nsHttpHandler.cpp b/netwerk/protocol/http/nsHttpHandler.cpp index e425c2281181a..97461fee50edb 100644 --- a/netwerk/protocol/http/nsHttpHandler.cpp +++ b/netwerk/protocol/http/nsHttpHandler.cpp @@ -2126,13 +2126,15 @@ nsHttpHandler::Observe(nsISupports *subject, nsresult nsHttpHandler::SpeculativeConnectInternal(nsIURI *aURI, + const nsACString& aIsolationKey, nsIInterfaceRequestor *aCallbacks, bool anonymous) { + nsCString isolationKey(aIsolationKey); if (IsNeckoChild()) { ipc::URIParams params; SerializeURI(aURI, params); - gNeckoChild->SendSpeculativeConnect(params, anonymous); + gNeckoChild->SendSpeculativeConnect(params, anonymous, isolationKey); return NS_OK; } @@ -2205,26 +2207,41 @@ nsHttpHandler::SpeculativeConnectInternal(nsIURI *aURI, nsAutoCString username; aURI->GetUsername(username); - // TODO: Fix isolation for speculative connect. nsHttpConnectionInfo *ci = - new nsHttpConnectionInfo(host, port, EmptyCString(), username, nullptr, EmptyCString(), usingSSL); + new nsHttpConnectionInfo(host, port, EmptyCString(), username, nullptr, aIsolationKey, usingSSL); ci->SetAnonymous(anonymous); return SpeculativeConnect(ci, aCallbacks); } +NS_IMETHODIMP +nsHttpHandler::SpeculativeConnectIsolated(nsIURI *aURI, + const nsACString& aIsolationKey, + nsIInterfaceRequestor *aCallbacks) +{ + return SpeculativeConnectInternal(aURI, aIsolationKey, aCallbacks, false); +} + NS_IMETHODIMP nsHttpHandler::SpeculativeConnect(nsIURI *aURI, nsIInterfaceRequestor *aCallbacks) { - return SpeculativeConnectInternal(aURI, aCallbacks, false); + return SpeculativeConnectInternal(aURI, EmptyCString(), aCallbacks, false); +} + +NS_IMETHODIMP +nsHttpHandler::SpeculativeAnonymousConnectIsolated(nsIURI *aURI, + const nsACString& aIsolationKey, + nsIInterfaceRequestor *aCallbacks) +{ + return SpeculativeConnectInternal(aURI, aIsolationKey, aCallbacks, true); } NS_IMETHODIMP nsHttpHandler::SpeculativeAnonymousConnect(nsIURI *aURI, nsIInterfaceRequestor *aCallbacks) { - return SpeculativeConnectInternal(aURI, aCallbacks, true); + return SpeculativeConnectInternal(aURI, EmptyCString(), aCallbacks, true); } void diff --git a/netwerk/protocol/http/nsHttpHandler.h b/netwerk/protocol/http/nsHttpHandler.h index 1205dadea72b4..cf15775a47218 100644 --- a/netwerk/protocol/http/nsHttpHandler.h +++ b/netwerk/protocol/http/nsHttpHandler.h @@ -596,6 +596,7 @@ private: private: nsresult SpeculativeConnectInternal(nsIURI *aURI, + const nsACString& aIsolationKey, nsIInterfaceRequestor *aCallbacks, bool anonymous); }; -- GitLab