Bug 1231211 P2 Pass the controller ServiceWorkerDescriptor on the channel LoadInfo and back in PHttpChannel's OnStartRequest message. r=valentin

This commit is contained in:
Ben Kelly 2018-01-23 10:38:52 -05:00
parent 8d4bfc7c66
commit 8e535f8460
9 changed files with 96 additions and 9 deletions

View File

@ -20,5 +20,11 @@ struct IPCServiceWorkerDescriptor
ServiceWorkerState state;
};
union OptionalIPCServiceWorkerDescriptor
{
IPCServiceWorkerDescriptor;
void_t;
};
} // namespace dom
} // namespace mozilla

View File

@ -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<ServiceWorkerDescriptor>& 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<ServiceWorkerDescriptor> controller;
if (loadInfoArgs.controller().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
controller.emplace(ServiceWorkerDescriptor(
loadInfoArgs.controller().get_IPCServiceWorkerDescriptor()));
}
nsCOMPtr<nsILoadInfo> loadInfo =
new mozilla::LoadInfo(loadingPrincipal,
triggeringPrincipal,
principalToInherit,
sandboxedLoadingPrincipal,
resultPrincipalURI,
controller,
loadInfoArgs.securityFlags(),
loadInfoArgs.contentPolicyType(),
static_cast<LoadTainting>(loadInfoArgs.tainting()),

View File

@ -352,6 +352,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
nsIPrincipal* aPrincipalToInherit,
nsIPrincipal* aSandboxedLoadingPrincipal,
nsIURI* aResultPrincipalURI,
const Maybe<ServiceWorkerDescriptor>& 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)

View File

@ -99,6 +99,7 @@ private:
nsIPrincipal* aPrincipalToInherit,
nsIPrincipal* aSandboxedLoadingPrincipal,
nsIURI* aResultPrincipalURI,
const Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController,
nsSecurityFlags aSecurityFlags,
nsContentPolicyType aContentPolicyType,
LoadTainting aTainting,

View File

@ -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;

View File

@ -434,7 +434,8 @@ class StartRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild>
const NetAddr& aPeerAddr,
const uint32_t& aCacheKey,
const nsCString& altDataType,
const int64_t& altDataLen)
const int64_t& altDataLen,
Maybe<ServiceWorkerDescriptor>&& aController)
: NeckoTargetChannelEvent<HttpChannelChild>(aChild)
, mChannelStatus(aChannelStatus)
, mResponseHead(aResponseHead)
@ -452,6 +453,7 @@ class StartRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild>
, mCacheKey(aCacheKey)
, mAltDataType(altDataType)
, mAltDataLen(altDataLen)
, mController(Move(aController))
{}
void Run() override
@ -462,7 +464,8 @@ class StartRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild>
mCacheEntryId, mCacheFetchCount,
mCacheExpirationTime, mCachedCharset,
mSecurityInfoSerialization, mSelfAddr, mPeerAddr,
mCacheKey, mAltDataType, mAltDataLen);
mCacheKey, mAltDataType, mAltDataLen,
mController);
}
private:
@ -482,6 +485,7 @@ class StartRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild>
uint32_t mCacheKey;
nsCString mAltDataType;
int64_t mAltDataLen;
Maybe<ServiceWorkerDescriptor> 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<ServiceWorkerDescriptor> 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<ServiceWorkerDescriptor>& aController)
{
LOG(("HttpChannelChild::OnStartRequest [this=%p]\n", this));
@ -596,6 +608,26 @@ HttpChannelChild::OnStartRequest(const nsresult& channelStatus,
mAvailableCachedAltDataType = altDataType;
mAltDataLength = altDataLen;
const Maybe<ServiceWorkerDescriptor>& 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);

View File

@ -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<mozilla::dom::ServiceWorkerDescriptor>& aController);
void MaybeDivertOnData(const nsCString& data,
const uint64_t& offset,
const uint32_t& count);

View File

@ -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<nsILoadInfo> loadInfo;
Unused << chan->GetLoadInfo(getter_AddRefs(loadInfo));
if (loadInfo) {
const Maybe<ServiceWorkerDescriptor>& 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;
}

View File

@ -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.