From 8e535f846093fc273c6cd3f2cda0d66e97cce82f Mon Sep 17 00:00:00 2001 From: Ben Kelly Date: Tue, 23 Jan 2018 10:38:52 -0500 Subject: [PATCH] Bug 1231211 P2 Pass the controller ServiceWorkerDescriptor on the channel LoadInfo and back in PHttpChannel's OnStartRequest message. r=valentin --- dom/workers/IPCServiceWorkerDescriptor.ipdlh | 6 +++ ipc/glue/BackgroundUtils.cpp | 16 ++++++++ netwerk/base/LoadInfo.cpp | 2 + netwerk/base/LoadInfo.h | 1 + netwerk/ipc/NeckoChannelParams.ipdlh | 8 ++++ netwerk/protocol/http/HttpChannelChild.cpp | 42 +++++++++++++++++--- netwerk/protocol/http/HttpChannelChild.h | 6 ++- netwerk/protocol/http/HttpChannelParent.cpp | 20 +++++++++- netwerk/protocol/http/PHttpChannel.ipdl | 4 +- 9 files changed, 96 insertions(+), 9 deletions(-) diff --git a/dom/workers/IPCServiceWorkerDescriptor.ipdlh b/dom/workers/IPCServiceWorkerDescriptor.ipdlh index 1b9569ad7239..e01ba1465581 100644 --- a/dom/workers/IPCServiceWorkerDescriptor.ipdlh +++ b/dom/workers/IPCServiceWorkerDescriptor.ipdlh @@ -20,5 +20,11 @@ struct IPCServiceWorkerDescriptor ServiceWorkerState state; }; +union OptionalIPCServiceWorkerDescriptor +{ + IPCServiceWorkerDescriptor; + void_t; +}; + } // namespace dom } // namespace mozilla diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index 6706d5844ccb..ade5d1235bf3 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -31,6 +31,8 @@ class OptionalLoadInfoArgs; } using mozilla::BasePrincipal; +using mozilla::Maybe; +using mozilla::dom::ServiceWorkerDescriptor; using namespace mozilla::net; namespace ipc { @@ -366,6 +368,12 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, NS_ENSURE_SUCCESS(rv, rv); } + OptionalIPCServiceWorkerDescriptor ipcController = mozilla::void_t(); + const Maybe& controller = aLoadInfo->GetController(); + if (controller.isSome()) { + ipcController = controller.ref().ToIPC(); + } + *aOptionalLoadInfoArgs = LoadInfoArgs( loadingPrincipalInfo, @@ -395,6 +403,7 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, redirectChain, ancestorPrincipals, aLoadInfo->AncestorOuterWindowIDs(), + ipcController, aLoadInfo->CorsUnsafeHeaders(), aLoadInfo->GetForcePreflight(), aLoadInfo->GetIsPreflight(), @@ -474,12 +483,19 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs, ancestorPrincipals.AppendElement(ancestorPrincipal.forget()); } + Maybe controller; + if (loadInfoArgs.controller().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) { + controller.emplace(ServiceWorkerDescriptor( + loadInfoArgs.controller().get_IPCServiceWorkerDescriptor())); + } + nsCOMPtr loadInfo = new mozilla::LoadInfo(loadingPrincipal, triggeringPrincipal, principalToInherit, sandboxedLoadingPrincipal, resultPrincipalURI, + controller, loadInfoArgs.securityFlags(), loadInfoArgs.contentPolicyType(), static_cast(loadInfoArgs.tainting()), diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index f7fd3b4ee74b..0108e63f0b23 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -352,6 +352,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aPrincipalToInherit, nsIPrincipal* aSandboxedLoadingPrincipal, nsIURI* aResultPrincipalURI, + const Maybe& aController, nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType, LoadTainting aTainting, @@ -383,6 +384,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mTriggeringPrincipal(aTriggeringPrincipal) , mPrincipalToInherit(aPrincipalToInherit) , mResultPrincipalURI(aResultPrincipalURI) + , mController(aController) , mSecurityFlags(aSecurityFlags) , mInternalContentPolicyType(aContentPolicyType) , mTainting(aTainting) diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index 023ad8b12670..53e0eae5bbe6 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -99,6 +99,7 @@ private: nsIPrincipal* aPrincipalToInherit, nsIPrincipal* aSandboxedLoadingPrincipal, nsIURI* aResultPrincipalURI, + const Maybe& aController, nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType, LoadTainting aTainting, diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index ab6a8b48c1d0..e7ab048e6172 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -10,6 +10,7 @@ include protocol PFTPChannel; include protocol PChildToParentStream; include BlobTypes; include URIParams; +include IPCServiceWorkerDescriptor; include IPCStream; include PBackgroundSharedTypes; @@ -69,6 +70,13 @@ struct LoadInfoArgs PrincipalInfo[] ancestorPrincipals; uint64_t[] ancestorOuterWindowIDs; + /** + * Subresource loads may have a controller set based on their owning + * window/worker client. We must send this across IPC to support + * performing interception in the parent. + */ + OptionalIPCServiceWorkerDescriptor controller; + nsCString[] corsUnsafeHeaders; bool forcePreflight; bool isPreflight; diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index 714235565ddc..141a3fee1b33 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -434,7 +434,8 @@ class StartRequestEvent : public NeckoTargetChannelEvent const NetAddr& aPeerAddr, const uint32_t& aCacheKey, const nsCString& altDataType, - const int64_t& altDataLen) + const int64_t& altDataLen, + Maybe&& aController) : NeckoTargetChannelEvent(aChild) , mChannelStatus(aChannelStatus) , mResponseHead(aResponseHead) @@ -452,6 +453,7 @@ class StartRequestEvent : public NeckoTargetChannelEvent , mCacheKey(aCacheKey) , mAltDataType(altDataType) , mAltDataLen(altDataLen) + , mController(Move(aController)) {} void Run() override @@ -462,7 +464,8 @@ class StartRequestEvent : public NeckoTargetChannelEvent mCacheEntryId, mCacheFetchCount, mCacheExpirationTime, mCachedCharset, mSecurityInfoSerialization, mSelfAddr, mPeerAddr, - mCacheKey, mAltDataType, mAltDataLen); + mCacheKey, mAltDataType, mAltDataLen, + mController); } private: @@ -482,6 +485,7 @@ class StartRequestEvent : public NeckoTargetChannelEvent uint32_t mCacheKey; nsCString mAltDataType; int64_t mAltDataLen; + Maybe mController; }; mozilla::ipc::IPCResult @@ -501,7 +505,8 @@ HttpChannelChild::RecvOnStartRequest(const nsresult& channelStatus, const int16_t& redirectCount, const uint32_t& cacheKey, const nsCString& altDataType, - const int64_t& altDataLen) + const int64_t& altDataLen, + const OptionalIPCServiceWorkerDescriptor& aController) { LOG(("HttpChannelChild::RecvOnStartRequest [this=%p]\n", this)); // mFlushedForDiversion and mDivertingToParent should NEVER be set at this @@ -513,6 +518,11 @@ HttpChannelChild::RecvOnStartRequest(const nsresult& channelStatus, mRedirectCount = redirectCount; + Maybe controller; + if (aController.type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) { + controller.emplace(ServiceWorkerDescriptor( + aController.get_IPCServiceWorkerDescriptor())); + } mEventQ->RunOrEnqueue(new StartRequestEvent(this, channelStatus, responseHead, useResponseHead, requestHeaders, @@ -521,7 +531,8 @@ HttpChannelChild::RecvOnStartRequest(const nsresult& channelStatus, cacheExpirationTime, cachedCharset, securityInfoSerialization, selfAddr, peerAddr, cacheKey, - altDataType, altDataLen)); + altDataType, altDataLen, + Move(controller))); { // Child's mEventQ is to control the execution order of the IPC messages @@ -561,7 +572,8 @@ HttpChannelChild::OnStartRequest(const nsresult& channelStatus, const NetAddr& peerAddr, const uint32_t& cacheKey, const nsCString& altDataType, - const int64_t& altDataLen) + const int64_t& altDataLen, + const Maybe& aController) { LOG(("HttpChannelChild::OnStartRequest [this=%p]\n", this)); @@ -596,6 +608,26 @@ HttpChannelChild::OnStartRequest(const nsresult& channelStatus, mAvailableCachedAltDataType = altDataType; mAltDataLength = altDataLen; + const Maybe& prevController = + mLoadInfo->GetController(); + + // If we got a service worker controller from the parent, then note + // it on the LoadInfo. This may indicate that a non-subresource request + // was intercepted and the resulting window/worker should be controlled. + if (aController.isSome() && prevController.isNothing()) { + mLoadInfo->SetController(aController.ref()); + } + + // If we did not set a controller, then verify it was either because: + // 1. Neither the parent or child know about a controlling service worker. + // 2. The parent and child both have the same controlling service worker. + else { + MOZ_DIAGNOSTIC_ASSERT((prevController.isNothing() && aController.isNothing()) || + (prevController.ref().Id() == aController.ref().Id() && + prevController.ref().Scope() == aController.ref().Scope() && + prevController.ref().PrincipalInfo() == aController.ref().PrincipalInfo())); + } + mAfterOnStartRequestBegun = true; AutoEventEnqueuer ensureSerialDispatch(mEventQ); diff --git a/netwerk/protocol/http/HttpChannelChild.h b/netwerk/protocol/http/HttpChannelChild.h index f7dbca10c549..3ed3b0ee50e6 100644 --- a/netwerk/protocol/http/HttpChannelChild.h +++ b/netwerk/protocol/http/HttpChannelChild.h @@ -144,7 +144,8 @@ protected: const int16_t& redirectCount, const uint32_t& cacheKey, const nsCString& altDataType, - const int64_t& altDataLen) override; + const int64_t& altDataLen, + const OptionalIPCServiceWorkerDescriptor& aController) override; mozilla::ipc::IPCResult RecvFailedAsyncOpen(const nsresult& status) override; mozilla::ipc::IPCResult RecvRedirect1Begin(const uint32_t& registrarId, const URIParams& newURI, @@ -410,7 +411,8 @@ private: const NetAddr& peerAddr, const uint32_t& cacheKey, const nsCString& altDataType, - const int64_t& altDataLen); + const int64_t& altDataLen, + const Maybe& aController); void MaybeDivertOnData(const nsCString& data, const uint64_t& offset, const uint32_t& count); diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index 064c5659e9ed..bac8df4b9330 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -1523,6 +1523,23 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) int64_t altDataLen = chan->GetAltDataLength(); + // Maybe pass back the ServiceWorkerDescriptor controller for this channel. + // For subresource loads the controller is already known when the channel + // is first open and comes down to us via the LoadInfo. For non-subresource + // loads, however, the controller is selected based on the URL by the + // ServiceWorkerManager. In these cases we need to communicate the controller + // back to the child process so the resulting window/worker can set its + // navigator.serviceWorker.controller correctly immediately. + OptionalIPCServiceWorkerDescriptor ipcController = void_t(); + nsCOMPtr loadInfo; + Unused << chan->GetLoadInfo(getter_AddRefs(loadInfo)); + if (loadInfo) { + const Maybe& controller = loadInfo->GetController(); + if (controller.isSome()) { + ipcController = controller.ref().ToIPC(); + } + } + // !!! We need to lock headers and please don't forget to unlock them !!! requestHead->Enter(); nsresult rv = NS_OK; @@ -1540,7 +1557,8 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) redirectCount, cacheKeyValue, altDataType, - altDataLen)) + altDataLen, + ipcController)) { rv = NS_ERROR_UNEXPECTED; } diff --git a/netwerk/protocol/http/PHttpChannel.ipdl b/netwerk/protocol/http/PHttpChannel.ipdl index a07131161b9a..3cbf32c1b9ea 100644 --- a/netwerk/protocol/http/PHttpChannel.ipdl +++ b/netwerk/protocol/http/PHttpChannel.ipdl @@ -11,6 +11,7 @@ include InputStreamParams; include URIParams; include PBackgroundSharedTypes; include NeckoChannelParams; +include IPCServiceWorkerDescriptor; include "mozilla/net/NeckoMessageUtils.h"; @@ -108,7 +109,8 @@ child: int16_t redirectCount, uint32_t cacheKey, nsCString altDataType, - int64_t altDataLength); + int64_t altDataLength, + OptionalIPCServiceWorkerDescriptor controller); // Used to cancel child channel if we hit errors during creating and // AsyncOpen of nsHttpChannel on the parent.