Skip to content

Commit 2aa93e4

Browse files
committed
Bug 1658869 - Propagate the InterceptedHttpChannel information to fetch's channel casued by FetchEvent.request. r=dom-worker-reviewers,dragana,jesup
When a network load needs to be intercepted by ServiceWorker, we extract the Request from the InterceptedHttpChannel, and propagate the Request through FetchEvent.request. However, some needed information is not extracted or is modified during the Request propagation, so getting the wrong result when using the Request to fetch resources in the ServiceWorker script. Differential Revision: https://phabricator.services.mozilla.com/D145969
1 parent b671926 commit 2aa93e4

18 files changed

+496
-56
lines changed

dom/fetch/Fetch.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,27 @@ already_AddRefed<Promise> FetchRequest(nsIGlobalObject* aGlobal,
487487
}
488488

489489
SafeRefPtr<InternalRequest> r = request->GetInternalRequest();
490+
491+
// Restore information of InterceptedHttpChannel if they are passed with the
492+
// Request. Since Request::Constructor would not copy these members.
493+
if (aInput.IsRequest()) {
494+
RefPtr<Request> inputReq = &aInput.GetAsRequest();
495+
SafeRefPtr<InternalRequest> inputInReq = inputReq->GetInternalRequest();
496+
if (inputInReq->GetInterceptionTriggeringPrincipalInfo()) {
497+
r->SetInterceptionContentPolicyType(
498+
inputInReq->InterceptionContentPolicyType());
499+
r->SetInterceptionTriggeringPrincipalInfo(
500+
MakeUnique<mozilla::ipc::PrincipalInfo>(
501+
*(inputInReq->GetInterceptionTriggeringPrincipalInfo().get())));
502+
if (!inputInReq->InterceptionRedirectChain().IsEmpty()) {
503+
r->SetInterceptionRedirectChain(
504+
inputInReq->InterceptionRedirectChain());
505+
}
506+
r->SetInterceptionFromThirdParty(
507+
inputInReq->InterceptionFromThirdParty());
508+
}
509+
}
510+
490511
RefPtr<AbortSignalImpl> signalImpl = request->GetSignalImpl();
491512

492513
if (signalImpl && signalImpl->Aborted()) {

dom/fetch/FetchDriver.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "nsICookieJarSettings.h"
1313
#include "nsIFile.h"
1414
#include "nsIInputStream.h"
15+
#include "nsIInterceptionInfo.h"
1516
#include "nsIOutputStream.h"
1617
#include "nsIFileChannel.h"
1718
#include "nsIHttpChannel.h"
@@ -21,6 +22,7 @@
2122
#include "nsIUploadChannel2.h"
2223
#include "nsIInterfaceRequestorUtils.h"
2324
#include "nsIPipe.h"
25+
#include "nsIRedirectHistoryEntry.h"
2426

2527
#include "nsContentPolicyUtils.h"
2628
#include "nsDataHandler.h"
@@ -38,6 +40,7 @@
3840
#include "mozilla/dom/UserActivation.h"
3941
#include "mozilla/dom/WorkerCommon.h"
4042
#include "mozilla/PreloaderBase.h"
43+
#include "mozilla/net/InterceptionInfo.h"
4144
#include "mozilla/net/NeckoChannelParams.h"
4245
#include "mozilla/ipc/PBackgroundSharedTypes.h"
4346
#include "mozilla/StaticPrefs_browser.h"
@@ -647,6 +650,33 @@ nsresult FetchDriver::HttpFetch(
647650
NS_ENSURE_SUCCESS(rv, rv);
648651
}
649652

653+
// If the fetch is created by FetchEvent.request or NavigationPreload request,
654+
// corresponding InterceptedHttpChannel information need to propagte to the
655+
// channel of the fetch.
656+
if (mRequest->GetInterceptionTriggeringPrincipalInfo()) {
657+
auto principalOrErr = mozilla::ipc::PrincipalInfoToPrincipal(
658+
*(mRequest->GetInterceptionTriggeringPrincipalInfo().get()));
659+
if (!principalOrErr.isErr()) {
660+
nsCOMPtr<nsIPrincipal> principal = principalOrErr.unwrap();
661+
662+
nsTArray<nsCOMPtr<nsIRedirectHistoryEntry>> redirectChain;
663+
if (!mRequest->InterceptionRedirectChain().IsEmpty()) {
664+
for (const RedirectHistoryEntryInfo& entryInfo :
665+
mRequest->InterceptionRedirectChain()) {
666+
nsCOMPtr<nsIRedirectHistoryEntry> entry =
667+
mozilla::ipc::RHEntryInfoToRHEntry(entryInfo);
668+
redirectChain.AppendElement(entry);
669+
}
670+
}
671+
672+
nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo();
673+
MOZ_ASSERT(loadInfo);
674+
loadInfo->SetInterceptionInfo(new mozilla::net::InterceptionInfo(
675+
principal, mRequest->InterceptionContentPolicyType(), redirectChain,
676+
mRequest->InterceptionFromThirdParty()));
677+
}
678+
}
679+
650680
if (mDocument && mDocument->GetEmbedderElement() &&
651681
mDocument->GetEmbedderElement()->IsAnyOfHTMLElements(nsGkAtoms::object,
652682
nsGkAtoms::embed)) {

dom/fetch/FetchTypes.ipdlh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
include IPCStream;
66
include PBackgroundSharedTypes;
77
include PerformanceTimingTypes;
8+
include NeckoChannelParams;
89

910
include "mozilla/dom/FetchIPCTypes.h";
1011
include "mozilla/ipc/TransportSecurityInfoUtils.h";
@@ -13,7 +14,6 @@ using HeadersGuardEnum from "mozilla/dom/HeadersBinding.h";
1314
using ReferrerPolicy from "mozilla/dom/ReferrerPolicyBinding.h";
1415
using RequestCache from "mozilla/dom/RequestBinding.h";
1516
using RequestCredentials from "mozilla/dom/RequestBinding.h";
16-
using RequestMode from "mozilla/dom/RequestBinding.h";
1717
using RequestRedirect from "mozilla/dom/RequestBinding.h";
1818
using ResponseType from "mozilla/dom/ResponseBinding.h";
1919
using struct nsID from "nsID.h";
@@ -66,6 +66,10 @@ struct IPCInternalRequest {
6666
nsString integrity;
6767
nsCString fragment;
6868
PrincipalInfo? principalInfo;
69+
PrincipalInfo? interceptionTriggeringPrincipalInfo;
70+
uint32_t interceptionContentPolicyType;
71+
RedirectHistoryEntryInfo[] interceptionRedirectChain;
72+
bool interceptionFromThirdParty;
6973
};
7074

7175
struct InternalResponseMetadata {

dom/fetch/InternalRequest.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,17 @@ InternalRequest::InternalRequest(const InternalRequest& aOther,
139139
mSynchronous(aOther.mSynchronous),
140140
mUnsafeRequest(aOther.mUnsafeRequest),
141141
mUseURLCredentials(aOther.mUseURLCredentials),
142-
mContentPolicyTypeOverridden(aOther.mContentPolicyTypeOverridden) {
142+
mContentPolicyTypeOverridden(aOther.mContentPolicyTypeOverridden),
143+
mInterceptionContentPolicyType(aOther.mInterceptionContentPolicyType),
144+
mInterceptionRedirectChain(aOther.mInterceptionRedirectChain),
145+
mInterceptionFromThirdParty(aOther.mInterceptionFromThirdParty) {
143146
// NOTE: does not copy body stream... use the fallible Clone() for that
147+
148+
if (aOther.GetInterceptionTriggeringPrincipalInfo()) {
149+
mInterceptionTriggeringPrincipalInfo =
150+
MakeUnique<mozilla::ipc::PrincipalInfo>(
151+
*(aOther.GetInterceptionTriggeringPrincipalInfo().get()));
152+
}
144153
}
145154

146155
InternalRequest::InternalRequest(const IPCInternalRequest& aIPCRequest)
@@ -159,12 +168,22 @@ InternalRequest::InternalRequest(const IPCInternalRequest& aIPCRequest)
159168
mCacheMode(aIPCRequest.cacheMode()),
160169
mRedirectMode(aIPCRequest.requestRedirect()),
161170
mIntegrity(aIPCRequest.integrity()),
162-
mFragment(aIPCRequest.fragment()) {
171+
mFragment(aIPCRequest.fragment()),
172+
mInterceptionContentPolicyType(static_cast<nsContentPolicyType>(
173+
aIPCRequest.interceptionContentPolicyType())),
174+
mInterceptionRedirectChain(aIPCRequest.interceptionRedirectChain()),
175+
mInterceptionFromThirdParty(aIPCRequest.interceptionFromThirdParty()) {
163176
if (aIPCRequest.principalInfo()) {
164177
mPrincipalInfo = MakeUnique<mozilla::ipc::PrincipalInfo>(
165178
aIPCRequest.principalInfo().ref());
166179
}
167180

181+
if (aIPCRequest.interceptionTriggeringPrincipalInfo()) {
182+
mInterceptionTriggeringPrincipalInfo =
183+
MakeUnique<mozilla::ipc::PrincipalInfo>(
184+
aIPCRequest.interceptionTriggeringPrincipalInfo().ref());
185+
}
186+
168187
const Maybe<BodyStreamVariant>& body = aIPCRequest.body();
169188

170189
// This constructor is (currently) only used for parent -> child communication
@@ -188,6 +207,11 @@ void InternalRequest::OverrideContentPolicyType(
188207
mContentPolicyTypeOverridden = true;
189208
}
190209

210+
void InternalRequest::SetInterceptionContentPolicyType(
211+
nsContentPolicyType aContentPolicyType) {
212+
mInterceptionContentPolicyType = aContentPolicyType;
213+
}
214+
191215
/* static */
192216
RequestDestination InternalRequest::MapContentPolicyTypeToRequestDestination(
193217
nsContentPolicyType aContentPolicyType) {
@@ -399,4 +423,8 @@ void InternalRequest::SetPrincipalInfo(
399423
mPrincipalInfo = std::move(aPrincipalInfo);
400424
}
401425

426+
void InternalRequest::SetInterceptionTriggeringPrincipalInfo(
427+
UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo) {
428+
mInterceptionTriggeringPrincipalInfo = std::move(aPrincipalInfo);
429+
}
402430
} // namespace mozilla::dom

dom/fetch/InternalRequest.h

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@
1717
#include "nsIChannelEventSink.h"
1818
#include "nsIInputStream.h"
1919
#include "nsISupportsImpl.h"
20+
#include "mozilla/net/NeckoChannelParams.h"
2021
#ifdef DEBUG
2122
# include "nsIURLParser.h"
2223
# include "nsNetCID.h"
2324
# include "nsServiceManagerUtils.h"
2425
#endif
2526

27+
using mozilla::net::RedirectHistoryEntryInfo;
28+
2629
namespace mozilla {
2730

2831
namespace ipc {
@@ -326,7 +329,6 @@ class InternalRequest final : public AtomicSafeRefCounted<InternalRequest> {
326329

327330
// Takes ownership of the principal info.
328331
void SetPrincipalInfo(UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo);
329-
330332
const UniquePtr<mozilla::ipc::PrincipalInfo>& GetPrincipalInfo() const {
331333
return mPrincipalInfo;
332334
}
@@ -351,6 +353,36 @@ class InternalRequest final : public AtomicSafeRefCounted<InternalRequest> {
351353
return mEmbedderPolicy;
352354
}
353355

356+
void SetInterceptionTriggeringPrincipalInfo(
357+
UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo);
358+
359+
const UniquePtr<mozilla::ipc::PrincipalInfo>&
360+
GetInterceptionTriggeringPrincipalInfo() const {
361+
return mInterceptionTriggeringPrincipalInfo;
362+
}
363+
364+
nsContentPolicyType InterceptionContentPolicyType() const {
365+
return mInterceptionContentPolicyType;
366+
}
367+
void SetInterceptionContentPolicyType(nsContentPolicyType aContentPolicyType);
368+
369+
const nsTArray<RedirectHistoryEntryInfo>& InterceptionRedirectChain() const {
370+
return mInterceptionRedirectChain;
371+
}
372+
373+
void SetInterceptionRedirectChain(
374+
const nsTArray<RedirectHistoryEntryInfo>& aRedirectChain) {
375+
mInterceptionRedirectChain = aRedirectChain;
376+
}
377+
378+
const bool& InterceptionFromThirdParty() const {
379+
return mInterceptionFromThirdParty;
380+
}
381+
382+
void SetInterceptionFromThirdParty(bool aFromThirdParty) {
383+
mInterceptionFromThirdParty = aFromThirdParty;
384+
}
385+
354386
private:
355387
struct ConstructorGuard {};
356388

@@ -425,6 +457,26 @@ class InternalRequest final : public AtomicSafeRefCounted<InternalRequest> {
425457
nsILoadInfo::EMBEDDER_POLICY_NULL;
426458

427459
UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
460+
461+
// Following members are specific for the FetchEvent.request or
462+
// NavigationPreload request which is extracted from the
463+
// InterceptedHttpChannel.
464+
// Notice that these members would not be copied when calling
465+
// InternalRequest::GetRequestConstructorCopy() since these information should
466+
// not be propagated when copying the Request in ServiceWorker script.
467+
468+
// This is the trigging principalInfo of the InterceptedHttpChannel.
469+
UniquePtr<mozilla::ipc::PrincipalInfo> mInterceptionTriggeringPrincipalInfo;
470+
471+
// This is the contentPolicyType of the InterceptedHttpChannel.
472+
nsContentPolicyType mInterceptionContentPolicyType{
473+
nsIContentPolicy::TYPE_INVALID};
474+
475+
// This is the redirect history of the InterceptedHttpChannel.
476+
CopyableTArray<RedirectHistoryEntryInfo> mInterceptionRedirectChain;
477+
478+
// This indicates that the InterceptedHttpChannel is a third party channel.
479+
bool mInterceptionFromThirdParty{false};
428480
};
429481

430482
} // namespace dom

dom/serviceworkers/ServiceWorkerPrivate.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "ServiceWorkerRegistrationInfo.h"
1515
#include "ServiceWorkerUtils.h"
1616
#include "js/ErrorReport.h"
17+
#include "mozIThirdPartyUtil.h"
1718
#include "mozilla/Assertions.h"
1819
#include "mozilla/CycleCollectedJSContext.h" // for MicroTaskRunnable
1920
#include "mozilla/ErrorResult.h"
@@ -56,7 +57,9 @@
5657
#include "nsINetworkInterceptController.h"
5758
#include "nsINamed.h"
5859
#include "nsIObserverService.h"
60+
#include "nsIRedirectHistoryEntry.h"
5961
#include "nsIScriptError.h"
62+
#include "nsIScriptSecurityManager.h"
6063
#include "nsISupportsImpl.h"
6164
#include "nsIURI.h"
6265
#include "nsIUploadChannel2.h"
@@ -362,11 +365,32 @@ Result<IPCInternalRequest, nsresult> GetIPCInternalRequest(
362365
}
363366

364367
Maybe<PrincipalInfo> principalInfo;
365-
368+
Maybe<PrincipalInfo> interceptionPrincipalInfo;
366369
if (loadInfo->TriggeringPrincipal()) {
367370
principalInfo.emplace();
371+
interceptionPrincipalInfo.emplace();
368372
MOZ_ALWAYS_SUCCEEDS(PrincipalToPrincipalInfo(
369373
loadInfo->TriggeringPrincipal(), principalInfo.ptr()));
374+
MOZ_ALWAYS_SUCCEEDS(PrincipalToPrincipalInfo(
375+
loadInfo->TriggeringPrincipal(), interceptionPrincipalInfo.ptr()));
376+
}
377+
378+
nsTArray<RedirectHistoryEntryInfo> redirectChain;
379+
for (const nsCOMPtr<nsIRedirectHistoryEntry>& redirectEntry :
380+
loadInfo->RedirectChain()) {
381+
RedirectHistoryEntryInfo* entry = redirectChain.AppendElement();
382+
MOZ_ALWAYS_SUCCEEDS(RHEntryToRHEntryInfo(redirectEntry, entry));
383+
}
384+
385+
bool isThirdPartyChannel;
386+
// ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
387+
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
388+
do_GetService(THIRDPARTYUTIL_CONTRACTID);
389+
if (thirdPartyUtil) {
390+
nsCOMPtr<nsIURI> uri;
391+
MOZ_TRY(underlyingChannel->GetURI(getter_AddRefs(uri)));
392+
MOZ_TRY(thirdPartyUtil->IsThirdPartyChannel(underlyingChannel, uri,
393+
&isThirdPartyChannel));
370394
}
371395

372396
// Note: all the arguments are copied rather than moved, which would be more
@@ -375,7 +399,8 @@ Result<IPCInternalRequest, nsresult> GetIPCInternalRequest(
375399
method, {spec}, ipcHeadersGuard, ipcHeaders, Nothing(), -1,
376400
alternativeDataType, contentPolicyType, referrer, referrerPolicy,
377401
requestMode, requestCredentials, cacheMode, requestRedirect, integrity,
378-
fragment, principalInfo);
402+
fragment, principalInfo, interceptionPrincipalInfo, contentPolicyType,
403+
redirectChain, isThirdPartyChannel);
379404
}
380405

381406
nsresult MaybeStoreStreamForBackgroundThread(nsIInterceptedChannel* aChannel,

0 commit comments

Comments
 (0)