Backed out 7 changesets (bug 1617500, bug 1617789, bug 1617434) for build bustage in dom/clients/manager/ClientChannelHelper.cpp

Backed out changeset 1a62904bfcb7 (bug 1617500)
Backed out changeset 592a5ddf6acf (bug 1617789)
Backed out changeset 995edb2e7f98 (bug 1617789)
Backed out changeset f3518664d654 (bug 1617789)
Backed out changeset 98ea95f7fe87 (bug 1617789)
Backed out changeset c5f1f70efb88 (bug 1617434)
Backed out changeset 1563faa24d15 (bug 1617434)
This commit is contained in:
Dorel Luca 2020-03-01 05:57:57 +02:00
Родитель d556b5b824
Коммит 109ac83385
19 изменённых файлов: 270 добавлений и 715 удалений

Просмотреть файл

@ -8888,8 +8888,11 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
}
}
bool loadFromExternal = false;
// Before going any further vet loads initiated by external programs.
if (aLoadState->LoadType() == LOAD_NORMAL_EXTERNAL) {
loadFromExternal = true;
// Disallow external chrome: loads targetted at content windows
if (SchemeIsChrome(aLoadState->URI())) {
NS_WARNING("blocked external chrome: url -- use '--chrome' option");
@ -9157,7 +9160,7 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
nsCOMPtr<nsIRequest> req;
rv = DoURILoad(aLoadState, aDocShell, getter_AddRefs(req));
rv = DoURILoad(aLoadState, loadFromExternal, aDocShell, getter_AddRefs(req));
if (req && aRequest) {
NS_ADDREF(*aRequest = req);
}
@ -9358,64 +9361,17 @@ static bool SchemeUsesDocChannel(nsIURI* aURI) {
/* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState(
nsDocShellLoadState* aLoadState, LoadInfo* aLoadInfo,
nsIInterfaceRequestor* aCallbacks, nsDocShell* aDocShell,
const OriginAttributes& aOriginAttributes, nsLoadFlags aLoadFlags,
uint32_t aLoadType, uint32_t aCacheKey, bool aIsActive, bool aIsTopLevelDoc,
bool aHasNonEmptySandboxingFlags, nsresult& aRv, nsIChannel** aChannel) {
nsLoadFlags aLoadFlags, uint32_t aLoadType, uint32_t aCacheKey,
bool aIsActive, bool aIsTopLevelDoc, bool aHasNonEmptySandboxingFlags,
nsresult& aRv, nsIChannel** aChannel) {
MOZ_ASSERT(aLoadInfo);
nsString srcdoc = VoidString();
bool isSrcdoc = aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
if (isSrcdoc) {
srcdoc = aLoadState->SrcdocData();
}
if (aLoadState->PrincipalToInherit()) {
aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit());
}
aLoadInfo->SetLoadTriggeredFromExternal(aLoadState->LoadType() ==
LOAD_NORMAL_EXTERNAL);
aLoadInfo->SetForceAllowDataURI(
aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
aLoadInfo->SetOriginalFrameSrcLoad(
aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC));
bool inheritAttrs = false;
if (aLoadState->PrincipalToInherit()) {
inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
aLoadState->PrincipalToInherit(), aLoadState->URI(),
true, // aInheritForAboutBlank
isSrcdoc);
}
OriginAttributes attrs;
// Inherit origin attributes from PrincipalToInherit if inheritAttrs is
// true. Otherwise we just use the origin attributes from docshell.
if (inheritAttrs) {
MOZ_ASSERT(aLoadState->PrincipalToInherit(),
"We should have PrincipalToInherit here.");
attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef();
// If firstPartyIsolation is not enabled, then PrincipalToInherit should
// have the same origin attributes with docshell.
MOZ_ASSERT_IF(!OriginAttributes::IsFirstPartyEnabled(),
attrs == aOriginAttributes);
} else {
attrs = aOriginAttributes;
attrs.SetFirstPartyDomain(aIsTopLevelDoc, aLoadState->URI());
}
aRv = aLoadInfo->SetOriginAttributes(attrs);
if (NS_WARN_IF(NS_FAILED(aRv))) {
return false;
}
if (aLoadState->GetIsFromProcessingFrameAttributes()) {
aLoadInfo->SetIsFromProcessingFrameAttributes();
}
// Propagate the IsFormSubmission flag to the loadInfo.
if (aLoadState->IsFormSubmission()) {
aLoadInfo->SetIsFormSubmission(true);
}
nsCOMPtr<nsIChannel> channel;
aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(),
aLoadInfo, aCallbacks, aDocShell,
@ -9614,66 +9570,13 @@ static bool SchemeUsesDocChannel(nsIURI* aURI) {
}
}
nsCOMPtr<nsIURI> rpURI;
aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI;
aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI);
if (originalResultPrincipalURI &&
(!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) {
// Unconditionally override, we want the replay to be equal to what has
// been captured.
aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref());
}
if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) {
// The LOAD_REPLACE flag and its handling here will be removed as part
// of bug 1319110. For now preserve its restoration here to not break
// any code expecting it being set specially on redirected channels.
// If the flag has originally been set to change result of
// NS_GetFinalChannelURI it won't have any effect and also won't cause
// any harm.
uint32_t loadFlags;
aRv = channel->GetLoadFlags(&loadFlags);
NS_ENSURE_SUCCESS(aRv, false);
channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
}
nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp();
if (csp) {
// Navigational requests that are same origin need to be upgraded in case
// upgrade-insecure-requests is present.
bool upgradeInsecureRequests = false;
csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
if (upgradeInsecureRequests) {
// only upgrade if the navigation is same origin
nsCOMPtr<nsIPrincipal> resultPrincipal;
aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
channel, getter_AddRefs(resultPrincipal));
NS_ENSURE_SUCCESS(aRv, false);
if (IsConsideredSameOriginForUIR(aLoadState->TriggeringPrincipal(),
resultPrincipal)) {
aLoadInfo->SetUpgradeInsecureRequests();
}
}
// For document loads we store the CSP that potentially needs to
// be inherited by the new document, e.g. in case we are loading
// an opaque origin like a data: URI. The actual inheritance
// check happens within Document::InitCSP().
// Please create an actual copy of the CSP (do not share the same
// reference) otherwise a Meta CSP of an opaque origin will
// incorrectly be propagated to the embedding document.
RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
aLoadInfo->SetCSPToInherit(cspToInherit);
}
channel.forget(aChannel);
return true;
}
nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
nsIDocShell** aDocShell, nsIRequest** aRequest) {
bool aLoadFromExternal, nsIDocShell** aDocShell,
nsIRequest** aRequest) {
// Double-check that we're still around to load this URI.
if (mIsBeingDestroyed) {
// Return NS_OK despite not doing anything to avoid throwing exceptions
@ -9847,11 +9750,11 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
// 1. ChannelShouldInheritPrincipal returns true.
// 2. aLoadState->URI() is not data: URI, or data: URI is not
// configured as unique opaque origin.
bool inheritPrincipal = false;
bool inheritAttrs = false, inheritPrincipal = false;
if (aLoadState->PrincipalToInherit()) {
bool isSrcdoc = aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
aLoadState->PrincipalToInherit(), aLoadState->URI(),
true, // aInheritForAboutBlank
isSrcdoc);
@ -9901,6 +9804,15 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
Maybe<mozilla::dom::ServiceWorkerDescriptor>(),
sandboxFlags);
if (aLoadState->PrincipalToInherit()) {
loadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit());
}
loadInfo->SetLoadTriggeredFromExternal(aLoadFromExternal);
loadInfo->SetForceAllowDataURI(
aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
loadInfo->SetOriginalFrameSrcLoad(
aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC));
// We have to do this in case our OriginAttributes are different from the
// OriginAttributes of the parent document. Or in case there isn't a
// parent document.
@ -9908,6 +9820,37 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
GetIsMozBrowser());
OriginAttributes attrs;
// Inherit origin attributes from PrincipalToInherit if inheritAttrs is
// true. Otherwise we just use the origin attributes from docshell.
if (inheritAttrs) {
MOZ_ASSERT(aLoadState->PrincipalToInherit(),
"We should have PrincipalToInherit here.");
attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef();
// If firstPartyIsolation is not enabled, then PrincipalToInherit should
// have the same origin attributes with docshell.
MOZ_ASSERT_IF(!OriginAttributes::IsFirstPartyEnabled(),
attrs == GetOriginAttributes());
} else {
attrs = GetOriginAttributes();
attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI());
}
rv = loadInfo->SetOriginAttributes(attrs);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (aLoadState->GetIsFromProcessingFrameAttributes()) {
loadInfo->SetIsFromProcessingFrameAttributes();
}
// Propagate the IsFormSubmission flag to the loadInfo.
if (aLoadState->IsFormSubmission()) {
loadInfo->SetIsFormSubmission(true);
}
/* Get the cache Key from SH */
uint32_t cacheKey = 0;
if (mLSHE) {
@ -9935,8 +9878,8 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
isTopLevelDoc, sandboxFlags);
channel->SetNotificationCallbacks(this);
} else if (!CreateAndConfigureRealChannelForLoadState(
aLoadState, loadInfo, this, this, GetOriginAttributes(),
loadFlags, mLoadType, cacheKey, isActive, isTopLevelDoc,
aLoadState, loadInfo, this, this, loadFlags, mLoadType,
cacheKey, isActive, isTopLevelDoc,
mBrowsingContext->GetSandboxFlags(), rv,
getter_AddRefs(channel))) {
return rv;
@ -9948,12 +9891,62 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
NS_ADDREF(*aRequest = channel);
}
nsCOMPtr<nsIURI> rpURI;
loadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI;
aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI);
if (originalResultPrincipalURI &&
(!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) {
// Unconditionally override, we want the replay to be equal to what has
// been captured.
loadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref());
}
if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) {
// The LOAD_REPLACE flag and its handling here will be removed as part
// of bug 1319110. For now preserve its restoration here to not break
// any code expecting it being set specially on redirected channels.
// If the flag has originally been set to change result of
// NS_GetFinalChannelURI it won't have any effect and also won't cause
// any harm.
uint32_t loadFlags;
rv = channel->GetLoadFlags(&loadFlags);
NS_ENSURE_SUCCESS(rv, rv);
channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
}
nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp();
if (csp) {
// Navigational requests that are same origin need to be upgraded in case
// upgrade-insecure-requests is present.
bool upgradeInsecureRequests = false;
csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
if (upgradeInsecureRequests) {
// only upgrade if the navigation is same origin
nsCOMPtr<nsIPrincipal> resultPrincipal;
rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
channel, getter_AddRefs(resultPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
if (IsConsideredSameOriginForUIR(aLoadState->TriggeringPrincipal(),
resultPrincipal)) {
static_cast<LoadInfo*>(loadInfo.get())->SetUpgradeInsecureRequests();
}
}
// For document loads we store the CSP that potentially needs to
// be inherited by the new document, e.g. in case we are loading
// an opaque origin like a data: URI. The actual inheritance
// check happens within Document::InitCSP().
// Please create an actual copy of the CSP (do not share the same
// reference) otherwise a Meta CSP of an opaque origin will
// incorrectly be propagated to the embedding document.
RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
static_cast<LoadInfo*>(loadInfo.get())->SetCSPToInherit(cspToInherit);
// Check CSP navigate-to
bool allowsNavigateTo = false;
rv = csp->GetAllowsNavigateTo(aLoadState->URI(),
aLoadState->IsFormSubmission(),
rv = csp->GetAllowsNavigateTo(aLoadState->URI(), loadInfo,
false, /* aWasRedirected */
false, /* aEnforceWhitelist */
&allowsNavigateTo);
@ -10199,18 +10192,16 @@ nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
MaybeCreateInitialClientSource();
if (aOpenFlags & nsIURILoader::REDIRECTED_CHANNEL) {
nsCOMPtr<nsILoadInfo> loadInfo;
aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
nsCOMPtr<nsILoadInfo> loadInfo;
aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get());
if (loadInfo->GetExternalContentPolicyType() ==
nsIContentPolicy::TYPE_DOCUMENT) {
li->UpdateBrowsingContextID(mBrowsingContext->Id());
} else if (loadInfo->GetExternalContentPolicyType() ==
nsIContentPolicy::TYPE_SUBDOCUMENT) {
li->UpdateFrameBrowsingContextID(mBrowsingContext->Id());
}
LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get());
if (loadInfo->GetExternalContentPolicyType() ==
nsIContentPolicy::TYPE_DOCUMENT) {
li->UpdateBrowsingContextID(mBrowsingContext->Id());
} else if (loadInfo->GetExternalContentPolicyType() ==
nsIContentPolicy::TYPE_SUBDOCUMENT) {
li->UpdateFrameBrowsingContextID(mBrowsingContext->Id());
}
// TODO: more attributes need to be updated on the LoadInfo (bug 1561706)
@ -10233,15 +10224,9 @@ nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
// on redirects. We pass no reserved client here so that the helper will
// create the reserved ClientSource if necessary.
Maybe<ClientInfo> noReservedClient;
if (docChannel) {
rv = AddClientChannelHelperInChild(
aChannel, win->EventTargetFor(TaskCategory::Other));
docChannel->SetInitialClientInfo(GetInitialClientInfo());
} else {
rv = AddClientChannelHelper(aChannel, std::move(noReservedClient),
GetInitialClientInfo(),
win->EventTargetFor(TaskCategory::Other));
}
rv = AddClientChannelHelper(
aChannel, std::move(noReservedClient), GetInitialClientInfo(),
win->EventTargetFor(TaskCategory::Other), !!docChannel);
NS_ENSURE_SUCCESS(rv, rv);
rv = aURILoader->OpenURI(aChannel, aOpenFlags, this);

Просмотреть файл

@ -501,7 +501,6 @@ class nsDocShell final : public nsDocLoader,
static bool CreateAndConfigureRealChannelForLoadState(
nsDocShellLoadState* aLoadState, mozilla::net::LoadInfo* aLoadInfo,
nsIInterfaceRequestor* aCallbacks, nsDocShell* aDocShell,
const mozilla::OriginAttributes& aOriginAttributes,
nsLoadFlags aLoadFlags, uint32_t aLoadType, uint32_t aCacheKey,
bool aIsActive, bool aIsTopLevelDoc, bool aHasNonEmptySandboxingFlags,
nsresult& rv, nsIChannel** aChannel);
@ -679,8 +678,8 @@ class nsDocShell final : public nsDocLoader,
// originalURI on the channel that does the load. If OriginalURI is null, URI
// will be set as the originalURI. If LoadReplace is true, LOAD_REPLACE flag
// will be set on the nsIChannel.
nsresult DoURILoad(nsDocShellLoadState* aLoadState, nsIDocShell** aDocShell,
nsIRequest** aRequest);
nsresult DoURILoad(nsDocShellLoadState* aLoadState, bool aLoadFromExternal,
nsIDocShell** aDocShell, nsIRequest** aRequest);
static nsresult AddHeadersToChannel(nsIInputStream* aHeadersData,
nsIChannel* aChannel);

Просмотреть файл

@ -3140,7 +3140,7 @@ nsresult Document::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
if (cspToInherit) {
bool allowsNavigateTo = false;
rv = cspToInherit->GetAllowsNavigateTo(
mDocumentURI, loadInfo->GetIsFormSubmission(),
mDocumentURI, loadInfo,
!loadInfo->RedirectChain().IsEmpty(), /* aWasRedirected */
true, /* aEnforceWhitelist */
&allowsNavigateTo);

Просмотреть файл

@ -32,14 +32,18 @@ namespace {
// to handle redirects in the parent and one to handle the final channel
// replacement (DocumentChannelChild 'redirects' to the final channel) in the
// child.
enum class Mode {
Mode_Default,
Mode_Child,
Mode_Parent,
};
class ClientChannelHelper : public nsIInterfaceRequestor,
public nsIChannelEventSink {
protected:
class ClientChannelHelper final : public nsIInterfaceRequestor,
public nsIChannelEventSink {
nsCOMPtr<nsIInterfaceRequestor> mOuter;
nsCOMPtr<nsISerialEventTarget> mEventTarget;
virtual ~ClientChannelHelper() = default;
~ClientChannelHelper() = default;
NS_IMETHOD
GetInterface(const nsIID& aIID, void** aResultOut) override {
@ -76,29 +80,48 @@ class ClientChannelHelper : public nsIInterfaceRequestor,
// If its a same-origin redirect we just move our reserved client to the
// new channel.
if (NS_SUCCEEDED(rv)) {
if (reservedClient) {
newLoadInfo->GiveReservedClientSource(std::move(reservedClient));
}
// It seems sometimes necko passes two channels with the same LoadInfo.
// We only need to move the reserved/initial ClientInfo over if we
// actually have a different LoadInfo.
else if (oldLoadInfo != newLoadInfo) {
const Maybe<ClientInfo>& reservedClientInfo =
oldLoadInfo->GetReservedClientInfo();
const Maybe<ClientInfo>& initialClientInfo =
oldLoadInfo->GetInitialClientInfo();
MOZ_DIAGNOSTIC_ASSERT(reservedClientInfo.isNothing() ||
initialClientInfo.isNothing());
if (reservedClientInfo.isSome()) {
newLoadInfo->SetReservedClientInfo(reservedClientInfo.ref());
// If we're running in the child, but redirects are handled by the parent
// then our reserved/initial info should already have been moved to the
// new channel via the parent. If they don't match, then we need to create
// a new reserved client for the specified info, otherwise we can copy our
// reserved client source to the new channel.
if (mMode == Mode::Mode_Child) {
Maybe<ClientInfo> newClientInfo = newLoadInfo->GetReservedClientInfo();
if (newClientInfo) {
if (!reservedClient || reservedClient->Info() != *newClientInfo) {
// clear `reservedClient` first to ensure the same clientInfo ID has
// been removed before adding again.
reservedClient.reset(nullptr);
reservedClient = ClientManager::CreateSourceFromInfo(*newClientInfo,
mEventTarget);
}
newLoadInfo->GiveReservedClientSource(std::move(reservedClient));
}
} else {
if (reservedClient) {
newLoadInfo->GiveReservedClientSource(std::move(reservedClient));
}
if (initialClientInfo.isSome()) {
newLoadInfo->SetInitialClientInfo(initialClientInfo.ref());
// It seems sometimes necko passes two channels with the same LoadInfo.
// We only need to move the reserved/initial ClientInfo over if we
// actually have a different LoadInfo.
else if (oldLoadInfo != newLoadInfo) {
const Maybe<ClientInfo>& reservedClientInfo =
oldLoadInfo->GetReservedClientInfo();
const Maybe<ClientInfo>& initialClientInfo =
oldLoadInfo->GetInitialClientInfo();
MOZ_DIAGNOSTIC_ASSERT(reservedClientInfo.isNothing() ||
initialClientInfo.isNothing());
if (reservedClientInfo.isSome()) {
newLoadInfo->SetReservedClientInfo(reservedClientInfo.ref());
}
if (initialClientInfo.isSome()) {
newLoadInfo->SetInitialClientInfo(initialClientInfo.ref());
}
}
}
}
@ -115,16 +138,40 @@ class ClientChannelHelper : public nsIInterfaceRequestor,
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
reservedClient.reset();
// If we're managing redirects in the parent, then we don't want
// to create a new ClientSource (since those need to live with
// the global), so just allocate a new ClientInfo/id and we can
// create a ClientSource when the final channel propagates back
// to the child.
if (mMode == Mode::Mode_Parent) {
Maybe<ClientInfo> reservedInfo =
ClientManager::CreateInfo(ClientType::Window, principal);
if (reservedInfo) {
newLoadInfo->SetReservedClientInfo(*reservedInfo);
}
} else {
reservedClient.reset();
// Create the new ClientSource. This should only happen for window
// Clients since support cross-origin redirects are blocked by the
// same-origin security policy.
reservedClient = ClientManager::CreateSource(ClientType::Window,
mEventTarget, principal);
MOZ_DIAGNOSTIC_ASSERT(reservedClient);
const Maybe<ClientInfo>& reservedClientInfo =
newLoadInfo->GetReservedClientInfo();
// If we're in the child, but the parent managed redirects for
// us then it might have allocated an id for us already. If
// so, then just create the ClientSource for that existing
// info.
if (reservedClientInfo && mMode == Mode::Mode_Child) {
reservedClient = ClientManager::CreateSourceFromInfo(
*reservedClientInfo, mEventTarget);
} else {
// Create the new ClientSource. This should only happen for window
// Clients since support cross-origin redirects are blocked by the
// same-origin security policy.
reservedClient = ClientManager::CreateSource(ClientType::Window,
mEventTarget, principal);
}
MOZ_DIAGNOSTIC_ASSERT(reservedClient);
newLoadInfo->GiveReservedClientSource(std::move(reservedClient));
newLoadInfo->GiveReservedClientSource(std::move(reservedClient));
}
}
uint32_t redirectMode = nsIHttpChannelInternal::REDIRECT_MODE_MANUAL;
@ -162,248 +209,24 @@ class ClientChannelHelper : public nsIInterfaceRequestor,
public:
ClientChannelHelper(nsIInterfaceRequestor* aOuter,
nsISerialEventTarget* aEventTarget)
: mOuter(aOuter), mEventTarget(aEventTarget) {}
nsISerialEventTarget* aEventTarget, Mode aMode)
: mOuter(aOuter), mEventTarget(aEventTarget), mMode(aMode) {}
NS_DECL_ISUPPORTS
Mode mMode;
};
NS_IMPL_ISUPPORTS(ClientChannelHelper, nsIInterfaceRequestor,
nsIChannelEventSink);
class ClientChannelHelperParent final : public ClientChannelHelper {
~ClientChannelHelperParent() = default;
NS_IMETHOD
AsyncOnChannelRedirect(nsIChannel* aOldChannel, nsIChannel* aNewChannel,
uint32_t aFlags,
nsIAsyncVerifyRedirectCallback* aCallback) override {
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel);
if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_DOM_BAD_URI)) {
return rv;
}
nsCOMPtr<nsILoadInfo> oldLoadInfo = aOldChannel->LoadInfo();
nsCOMPtr<nsILoadInfo> newLoadInfo = aNewChannel->LoadInfo();
UniquePtr<ClientSource> reservedClient =
oldLoadInfo->TakeReservedClientSource();
// If its a same-origin redirect we just move our reserved client to the
// new channel.
if (NS_SUCCEEDED(rv)) {
if (reservedClient) {
newLoadInfo->GiveReservedClientSource(std::move(reservedClient));
}
// It seems sometimes necko passes two channels with the same LoadInfo.
// We only need to move the reserved/initial ClientInfo over if we
// actually have a different LoadInfo.
else if (oldLoadInfo != newLoadInfo) {
const Maybe<ClientInfo>& reservedClientInfo =
oldLoadInfo->GetReservedClientInfo();
const Maybe<ClientInfo>& initialClientInfo =
oldLoadInfo->GetInitialClientInfo();
MOZ_DIAGNOSTIC_ASSERT(reservedClientInfo.isNothing() ||
initialClientInfo.isNothing());
if (reservedClientInfo.isSome()) {
newLoadInfo->SetReservedClientInfo(reservedClientInfo.ref());
}
if (initialClientInfo.isSome()) {
newLoadInfo->SetInitialClientInfo(initialClientInfo.ref());
}
}
}
// If it's a cross-origin redirect then we discard the old reserved client
// and create a new one.
else {
// If CheckSameOrigin() worked, then the security manager must exist.
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
MOZ_DIAGNOSTIC_ASSERT(ssm);
nsCOMPtr<nsIPrincipal> principal;
rv = ssm->GetChannelResultPrincipal(aNewChannel,
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
// If we're managing redirects in the parent, then we don't want
// to create a new ClientSource (since those need to live with
// the global), so just allocate a new ClientInfo/id and we can
// create a ClientSource when the final channel propagates back
// to the child.
Maybe<ClientInfo> reservedInfo =
ClientManager::CreateInfo(ClientType::Window, principal);
if (reservedInfo) {
newLoadInfo->SetReservedClientInfo(*reservedInfo);
}
}
uint32_t redirectMode = nsIHttpChannelInternal::REDIRECT_MODE_MANUAL;
nsCOMPtr<nsIHttpChannelInternal> http = do_QueryInterface(aOldChannel);
if (http) {
MOZ_ALWAYS_SUCCEEDS(http->GetRedirectMode(&redirectMode));
}
// Normally we keep the controller across channel redirects, but we must
// clear it when a document load redirects. Only do this for real
// redirects, however.
//
// This is effectively described in step 4.2 of:
//
// https://fetch.spec.whatwg.org/#http-fetch
//
// The spec sets the service-workers mode to none when the request is
// configured to *not* follow redirects. This prevents any further
// service workers from intercepting. The first service worker that
// had a shot at the FetchEvent remains the controller in this case.
if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
redirectMode != nsIHttpChannelInternal::REDIRECT_MODE_FOLLOW) {
newLoadInfo->ClearController();
}
nsCOMPtr<nsIChannelEventSink> outerSink = do_GetInterface(mOuter);
if (outerSink) {
return outerSink->AsyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags,
aCallback);
}
aCallback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
public:
ClientChannelHelperParent(nsIInterfaceRequestor* aOuter)
: ClientChannelHelper(aOuter, nullptr) {}
};
class ClientChannelHelperChild final : public ClientChannelHelper {
~ClientChannelHelperChild() = default;
NS_IMETHOD
AsyncOnChannelRedirect(nsIChannel* aOldChannel, nsIChannel* aNewChannel,
uint32_t aFlags,
nsIAsyncVerifyRedirectCallback* aCallback) override {
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel);
if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_DOM_BAD_URI)) {
return rv;
}
nsCOMPtr<nsILoadInfo> oldLoadInfo = aOldChannel->LoadInfo();
nsCOMPtr<nsILoadInfo> newLoadInfo = aNewChannel->LoadInfo();
UniquePtr<ClientSource> reservedClient =
oldLoadInfo->TakeReservedClientSource();
// If its a same-origin redirect we just move our reserved client to the
// new channel.
if (NS_SUCCEEDED(rv)) {
// If we're running in the child, but redirects are handled by the parent
// then our reserved/initial info should already have been moved to the
// new channel via the parent. If they don't match, then we need to create
// a new reserved client for the specified info, otherwise we can copy our
// reserved client source to the new channel.
Maybe<ClientInfo> newClientInfo = newLoadInfo->GetReservedClientInfo();
if (newClientInfo) {
if (!reservedClient || reservedClient->Info() != *newClientInfo) {
// clear `reservedClient` first to ensure the same clientInfo ID has
// been removed before adding again.
reservedClient.reset(nullptr);
reservedClient =
ClientManager::CreateSourceFromInfo(*newClientInfo, mEventTarget);
}
newLoadInfo->GiveReservedClientSource(std::move(reservedClient));
}
}
// If it's a cross-origin redirect then we discard the old reserved client
// and create a new one.
else {
// If CheckSameOrigin() worked, then the security manager must exist.
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
MOZ_DIAGNOSTIC_ASSERT(ssm);
nsCOMPtr<nsIPrincipal> principal;
rv = ssm->GetChannelResultPrincipal(aNewChannel,
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
reservedClient.reset();
const Maybe<ClientInfo>& reservedClientInfo =
newLoadInfo->GetReservedClientInfo();
// If we're in the child, but the parent managed redirects for
// us then it might have allocated an id for us already. If
// so, then just create the ClientSource for that existing
// info.
if (reservedClientInfo) {
reservedClient = ClientManager::CreateSourceFromInfo(
*reservedClientInfo, mEventTarget);
} else {
// Create the new ClientSource. This should only happen for window
// Clients since support cross-origin redirects are blocked by the
// same-origin security policy.
reservedClient = ClientManager::CreateSource(ClientType::Window,
mEventTarget, principal);
}
MOZ_DIAGNOSTIC_ASSERT(reservedClient);
newLoadInfo->GiveReservedClientSource(std::move(reservedClient));
}
uint32_t redirectMode = nsIHttpChannelInternal::REDIRECT_MODE_MANUAL;
nsCOMPtr<nsIHttpChannelInternal> http = do_QueryInterface(aOldChannel);
if (http) {
MOZ_ALWAYS_SUCCEEDS(http->GetRedirectMode(&redirectMode));
}
// Normally we keep the controller across channel redirects, but we must
// clear it when a document load redirects. Only do this for real
// redirects, however.
//
// This is effectively described in step 4.2 of:
//
// https://fetch.spec.whatwg.org/#http-fetch
//
// The spec sets the service-workers mode to none when the request is
// configured to *not* follow redirects. This prevents any further
// service workers from intercepting. The first service worker that
// had a shot at the FetchEvent remains the controller in this case.
if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
redirectMode != nsIHttpChannelInternal::REDIRECT_MODE_FOLLOW) {
newLoadInfo->ClearController();
}
nsCOMPtr<nsIChannelEventSink> outerSink = do_GetInterface(mOuter);
if (outerSink) {
return outerSink->AsyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags,
aCallback);
}
aCallback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
public:
ClientChannelHelperChild(nsIInterfaceRequestor* aOuter,
nsISerialEventTarget* aEventTarget)
: ClientChannelHelper(aOuter, aEventTarget) {}
};
} // anonymous namespace
nsresult AddClientChannelHelper(nsIChannel* aChannel,
Maybe<ClientInfo>&& aReservedClientInfo,
Maybe<ClientInfo>&& aInitialClientInfo,
nsISerialEventTarget* aEventTarget) {
nsISerialEventTarget* aEventTarget,
bool aManagedInParent) {
MOZ_ASSERT(NS_IsMainThread());
Maybe<ClientInfo> initialClientInfo(std::move(aInitialClientInfo));
@ -465,8 +288,9 @@ nsresult AddClientChannelHelper(nsIChannel* aChannel,
MOZ_DIAGNOSTIC_ASSERT(reservedClient);
}
RefPtr<ClientChannelHelper> helper =
new ClientChannelHelper(outerCallbacks, aEventTarget);
RefPtr<ClientChannelHelper> helper = new ClientChannelHelper(
outerCallbacks, aEventTarget,
aManagedInParent ? Mode::Mode_Child : Mode::Mode_Default);
// Only set the callbacks helper if we are able to reserve the client
// successfully.
@ -490,74 +314,15 @@ nsresult AddClientChannelHelper(nsIChannel* aChannel,
return NS_OK;
}
nsresult AddClientChannelHelperInChild(nsIChannel* aChannel,
nsISerialEventTarget* aEventTarget) {
MOZ_ASSERT(NS_IsMainThread());
nsresult AddClientChannelHelperInParent(nsIChannel* aChannel,
nsISerialEventTarget* aEventTarget) {
nsCOMPtr<nsIInterfaceRequestor> outerCallbacks;
nsresult rv =
aChannel->GetNotificationCallbacks(getter_AddRefs(outerCallbacks));
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<ClientChannelHelper> helper =
new ClientChannelHelperChild(outerCallbacks, aEventTarget);
// Only set the callbacks helper if we are able to reserve the client
// successfully.
rv = aChannel->SetNotificationCallbacks(helper);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult AddClientChannelHelperInParent(
nsIChannel* aChannel, Maybe<ClientInfo>&& aInitialClientInfo) {
MOZ_ASSERT(NS_IsMainThread());
Maybe<ClientInfo> initialClientInfo(std::move(aInitialClientInfo));
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
NS_ENSURE_TRUE(ssm, NS_ERROR_FAILURE);
nsCOMPtr<nsIPrincipal> channelPrincipal;
nsresult rv = ssm->GetChannelResultPrincipal(
aChannel, getter_AddRefs(channelPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
// Only allow the initial ClientInfo to be set if the current channel
// principal matches.
if (initialClientInfo.isSome()) {
nsCOMPtr<nsIPrincipal> initialPrincipal = PrincipalInfoToPrincipal(
initialClientInfo.ref().PrincipalInfo(), nullptr);
bool equals = false;
rv = initialPrincipal ? initialPrincipal->Equals(channelPrincipal, &equals)
: NS_ERROR_FAILURE;
if (NS_FAILED(rv) || !equals) {
initialClientInfo.reset();
}
}
nsCOMPtr<nsIInterfaceRequestor> outerCallbacks;
rv = aChannel->GetNotificationCallbacks(getter_AddRefs(outerCallbacks));
NS_ENSURE_SUCCESS(rv, rv);
if (initialClientInfo.isNothing()) {
// Wait to reserve the client until we are reasonably sure this method
// will succeed. We should only follow this path for window clients.
// Workers should always provide a reserved ClientInfo since their
// ClientSource object is owned by a different thread.
Maybe<ClientInfo> reservedInfo =
ClientManager::CreateInfo(ClientType::Window, channelPrincipal);
MOZ_DIAGNOSTIC_ASSERT(reservedInfo);
loadInfo->SetReservedClientInfo(reservedInfo.ref());
} else {
loadInfo->SetInitialClientInfo(initialClientInfo.ref());
}
RefPtr<ClientChannelHelper> helper =
new ClientChannelHelperParent(outerCallbacks);
new ClientChannelHelper(outerCallbacks, aEventTarget, Mode::Mode_Parent);
// Only set the callbacks helper if we are able to reserve the client
// successfully.

Просмотреть файл

@ -22,26 +22,18 @@ class ClientInfo;
// properly handle creating a new ClientSource on cross-origin redirect
// and propagate the current reserved/initial client on same-origin
// redirect.
nsresult AddClientChannelHelper(nsIChannel* aChannel,
Maybe<ClientInfo>&& aReservedClientInfo,
Maybe<ClientInfo>&& aInitialClientInfo,
nsISerialEventTarget* aEventTarget);
// Use this variant in the content process if redirects will be handled in the
// Pass true for aManagedInParent if redirects will be handled in the
// parent process (by a channel with AddClientChannelHelperInParent),
// and this process only sees a single switch to the final channel,
// as done by DocumentChannel.
// This variant just handles allocating a ClientSource around an existing
// ClientInfo allocated in the parent process.
nsresult AddClientChannelHelperInChild(nsIChannel* aChannel,
nsISerialEventTarget* aEventTarget);
nsresult AddClientChannelHelper(nsIChannel* aChannel,
Maybe<ClientInfo>&& aReservedClientInfo,
Maybe<ClientInfo>&& aInitialClientInfo,
nsISerialEventTarget* aEventTarget,
bool aManagedInParent);
// Use this variant in the parent process if redirects are handled there.
// Does the same as the default variant, except just allocates a ClientInfo
// and lets the content process create the corresponding ClientSource once
// it becomes available there.
nsresult AddClientChannelHelperInParent(nsIChannel* aChannel,
Maybe<ClientInfo>&& aInitialClientInfo);
nsISerialEventTarget* aEventTarget);
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -150,7 +150,7 @@ interface nsIContentSecurityPolicy : nsISerializable
* Whether this policy allows a navigation subject to the navigate-to
* policy.
* @param aURI The target URI
* @param aIsFormSubmission True if the navigation was initiated by a form submission. This
* @param aLoadInfo used to check if the navigation was initiated by a form submission. This
* is important since the form-action directive overrides navigate-to in that case.
* @param aWasRedirect True if a redirect has happened. Important for path-sensitivity.
* @param aEnforceWhitelist True if the whitelist of allowed targets must be enforced. If
@ -160,7 +160,7 @@ interface nsIContentSecurityPolicy : nsISerializable
* Whether or not the effects of the navigation is allowed
*/
boolean getAllowsNavigateTo(in nsIURI aURI,
in boolean aIsFormSubmission,
in nsILoadInfo aLoadInfo,
in boolean aWasRedirected,
in boolean aEnforceWhitelist);

Просмотреть файл

@ -597,7 +597,7 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
}
NS_IMETHODIMP
nsCSPContext::GetAllowsNavigateTo(nsIURI* aURI, bool aIsFormSubmission,
nsCSPContext::GetAllowsNavigateTo(nsIURI* aURI, nsILoadInfo* aLoadInfo,
bool aWasRedirected, bool aEnforceWhitelist,
bool* outAllowsNavigateTo) {
/*
@ -617,7 +617,7 @@ nsCSPContext::GetAllowsNavigateTo(nsIURI* aURI, bool aIsFormSubmission,
// So in case this is a form submission and the directive 'form-action' is
// present then there is nothing for us to do here, see: 6.3.3.1.2
// https://www.w3.org/TR/CSP3/#navigate-to-pre-navigate
if (aIsFormSubmission) {
if (aLoadInfo->GetIsFormSubmission()) {
for (unsigned long i = 0; i < mPolicies.Length(); i++) {
if (mPolicies[i]->hasDirective(
nsIContentSecurityPolicy::FORM_ACTION_DIRECTIVE)) {

Просмотреть файл

@ -283,8 +283,8 @@ nsresult CSPService::ConsultCSPForRedirect(nsIURI* aOriginalURI,
if (cspToInherit) {
bool allowsNavigateTo = false;
nsresult rv = cspToInherit->GetAllowsNavigateTo(
aNewURI, aLoadInfo->GetIsFormSubmission(), true, /* aWasRedirected */
false, /* aEnforceWhitelist */
aNewURI, aLoadInfo, true, /* aWasRedirected */
false, /* aEnforceWhitelist */
&allowsNavigateTo);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -1026,7 +1026,7 @@ class ScriptLoaderRunnable final : public nsIRunnable, public nsINamed {
MOZ_DIAGNOSTIC_ASSERT(loadInfo.mReservedClientInfo.isSome());
rv = AddClientChannelHelper(
channel, std::move(loadInfo.mReservedClientInfo), Maybe<ClientInfo>(),
mWorkerPrivate->HybridEventTarget());
mWorkerPrivate->HybridEventTarget(), false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

Просмотреть файл

@ -27,13 +27,11 @@
#include "URIUtils.h"
#include "mozilla/dom/nsCSPUtils.h"
#include "mozilla/dom/nsCSPContext.h"
#include "mozilla/dom/BrowsingContext.h"
namespace mozilla {
using mozilla::BasePrincipal;
using mozilla::Maybe;
using mozilla::dom::BrowsingContext;
using mozilla::dom::ServiceWorkerDescriptor;
using namespace mozilla::net;
@ -589,15 +587,16 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo,
nsresult LoadInfoArgsToLoadInfo(
const Maybe<LoadInfoArgs>& aOptionalLoadInfoArgs,
nsILoadInfo** outLoadInfo) {
return LoadInfoArgsToLoadInfo(aOptionalLoadInfoArgs, nullptr, outLoadInfo);
return LoadInfoArgsToLoadInfo(aOptionalLoadInfoArgs, nullptr, nullptr,
outLoadInfo);
}
nsresult LoadInfoArgsToLoadInfo(
const Maybe<LoadInfoArgs>& aOptionalLoadInfoArgs,
const Maybe<LoadInfoArgs>& aOptionalLoadInfoArgs, nsINode* aLoadingContext,
nsINode* aCspToInheritLoadingContext, nsILoadInfo** outLoadInfo) {
RefPtr<LoadInfo> loadInfo;
nsresult rv =
LoadInfoArgsToLoadInfo(aOptionalLoadInfoArgs, aCspToInheritLoadingContext,
getter_AddRefs(loadInfo));
nsresult rv = LoadInfoArgsToLoadInfo(aOptionalLoadInfoArgs, aLoadingContext,
aCspToInheritLoadingContext,
getter_AddRefs(loadInfo));
NS_ENSURE_SUCCESS(rv, rv);
loadInfo.forget(outLoadInfo);
@ -606,10 +605,11 @@ nsresult LoadInfoArgsToLoadInfo(
nsresult LoadInfoArgsToLoadInfo(
const Maybe<LoadInfoArgs>& aOptionalLoadInfoArgs, LoadInfo** outLoadInfo) {
return LoadInfoArgsToLoadInfo(aOptionalLoadInfoArgs, nullptr, outLoadInfo);
return LoadInfoArgsToLoadInfo(aOptionalLoadInfoArgs, nullptr, nullptr,
outLoadInfo);
}
nsresult LoadInfoArgsToLoadInfo(
const Maybe<LoadInfoArgs>& aOptionalLoadInfoArgs,
const Maybe<LoadInfoArgs>& aOptionalLoadInfoArgs, nsINode* aLoadingContext,
nsINode* aCspToInheritLoadingContext, LoadInfo** outLoadInfo) {
if (aOptionalLoadInfoArgs.isNothing()) {
*outLoadInfo = nullptr;
@ -735,16 +735,6 @@ nsresult LoadInfoArgsToLoadInfo(
cspToInherit = CSPInfoToCSP(cspToInheritInfo.ref(), doc);
}
// Restore the loadingContext for frames using the BrowsingContext's
// embedder element. Note that this only works if the embedder is
// same-process, so won't be fission compatible.
nsCOMPtr<nsINode> loadingContext;
RefPtr<BrowsingContext> frameBrowsingContext =
BrowsingContext::Get(loadInfoArgs.frameBrowsingContextID());
if (frameBrowsingContext) {
loadingContext = frameBrowsingContext->GetEmbedderElement();
}
RefPtr<mozilla::LoadInfo> loadInfo = new mozilla::LoadInfo(
loadingPrincipal, triggeringPrincipal, principalToInherit,
sandboxedLoadingPrincipal, topLevelPrincipal,
@ -777,7 +767,7 @@ nsresult LoadInfoArgsToLoadInfo(
loadInfoArgs.documentHasLoaded(),
loadInfoArgs.allowListFutureDocumentsCreatedFromThisRedirectChain(),
loadInfoArgs.cspNonce(), loadInfoArgs.skipContentSniffing(),
loadInfoArgs.requestBlockingReason(), loadingContext);
loadInfoArgs.requestBlockingReason(), aLoadingContext);
if (loadInfoArgs.isFromProcessingFrameAttributes()) {
loadInfo->SetIsFromProcessingFrameAttributes();

Просмотреть файл

@ -136,13 +136,15 @@ nsresult LoadInfoArgsToLoadInfo(
nsILoadInfo** outLoadInfo);
nsresult LoadInfoArgsToLoadInfo(
const Maybe<mozilla::net::LoadInfoArgs>& aOptionalLoadInfoArgs,
nsINode* aCspToInheritLoadingContext, nsILoadInfo** outLoadInfo);
nsINode* aLoadingContext, nsINode* aCspToInheritLoadingContext,
nsILoadInfo** outLoadInfo);
nsresult LoadInfoArgsToLoadInfo(
const Maybe<net::LoadInfoArgs>& aOptionalLoadInfoArgs,
mozilla::net::LoadInfo** outLoadInfo);
nsresult LoadInfoArgsToLoadInfo(
const Maybe<net::LoadInfoArgs>& aOptionalLoadInfoArgs,
nsINode* aCspToInheritLoadingContext, mozilla::net::LoadInfo** outLoadInfo);
nsINode* aLoadingContext, nsINode* aCspToInheritLoadingContext,
mozilla::net::LoadInfo** outLoadInfo);
/**
* Fills ParentLoadInfoForwarderArgs with properties we want to carry to child

Просмотреть файл

@ -9,7 +9,6 @@
#include "js/Array.h" // JS::NewArrayObject
#include "mozilla/Assertions.h"
#include "mozilla/ExpandedPrincipal.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/ClientIPCTypes.h"
#include "mozilla/dom/ClientSource.h"
#include "mozilla/dom/Performance.h"
@ -420,84 +419,6 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
mCookieSettings = CookieSettings::Create();
}
LoadInfo::LoadInfo(dom::CanonicalBrowsingContext* aBrowsingContext,
nsIPrincipal* aTriggeringPrincipal,
const OriginAttributes& aOriginAttributes,
uint64_t aOuterWindowID, nsSecurityFlags aSecurityFlags,
uint32_t aSandboxFlags)
: mLoadingPrincipal(nullptr),
mTriggeringPrincipal(aTriggeringPrincipal),
mPrincipalToInherit(nullptr),
mContextForTopLevelLoad(nullptr),
mSecurityFlags(aSecurityFlags),
mSandboxFlags(aSandboxFlags),
mInternalContentPolicyType(nsIContentPolicy::TYPE_DOCUMENT),
mTainting(LoadTainting::Basic),
mBlockAllMixedContent(false),
mUpgradeInsecureRequests(false),
mBrowserUpgradeInsecureRequests(false),
mBrowserWouldUpgradeInsecureRequests(false),
mForceAllowDataURI(false),
mAllowInsecureRedirectToDataURI(false),
mBypassCORSChecks(false),
mSkipContentPolicyCheckForWebRequest(false),
mOriginalFrameSrcLoad(false),
mForceInheritPrincipalDropped(false),
mInnerWindowID(0),
mOuterWindowID(0),
mParentOuterWindowID(0),
mTopOuterWindowID(0),
mFrameOuterWindowID(0),
mBrowsingContextID(0),
mFrameBrowsingContextID(0),
mInitialSecurityCheckDone(false),
mIsThirdPartyContext(false), // NB: TYPE_DOCUMENT implies !third-party.
mIsFormSubmission(false),
mSendCSPViolationEvents(true),
mRequestBlockingReason(BLOCKING_REASON_NONE),
mForcePreflight(false),
mIsPreflight(false),
mLoadTriggeredFromExternal(false),
mServiceWorkerTaintingSynthesized(false),
mDocumentHasUserInteracted(false),
mDocumentHasLoaded(false),
mAllowListFutureDocumentsCreatedFromThisRedirectChain(false),
mSkipContentSniffing(false),
mIsFromProcessingFrameAttributes(false) {
// Top-level loads are never third-party
// Grab the information we can out of the window.
MOZ_ASSERT(aBrowsingContext);
MOZ_ASSERT(mTriggeringPrincipal);
MOZ_ASSERT(aSecurityFlags !=
nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK);
// if the load is sandboxed, we can not also inherit the principal
if (mSandboxFlags & SANDBOXED_ORIGIN) {
mForceInheritPrincipalDropped =
(mSecurityFlags & nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL);
mSecurityFlags &= ~nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
}
// NB: Ignore the current inner window since we're navigating away from it.
// Since this is a TYPE_DOCUMENT load, we should be the top window, and all
// the outer window IDs are the same.
mOuterWindowID = mParentOuterWindowID = mTopOuterWindowID = aOuterWindowID;
mBrowsingContextID = aBrowsingContext->Id();
mOriginAttributes = aOriginAttributes;
#ifdef DEBUG
if (aBrowsingContext->IsChrome()) {
MOZ_ASSERT(mOriginAttributes.mPrivateBrowsingId == 0,
"chrome docshell shouldn't have mPrivateBrowsingId set.");
}
#endif
// Let's take the current cookie behavior and current cookie permission
// for the documents' loadInfo. Note that for any other loadInfos,
// cookieBehavior will be BEHAVIOR_REJECT for security reasons.
mCookieSettings = CookieSettings::Create();
}
LoadInfo::LoadInfo(const LoadInfo& rhs)
: mLoadingPrincipal(rhs.mLoadingPrincipal),
mTriggeringPrincipal(rhs.mTriggeringPrincipal),

Просмотреть файл

@ -29,7 +29,6 @@ namespace mozilla {
namespace dom {
class PerformanceStorage;
class XMLHttpRequestMainThread;
class CanonicalBrowsingContext;
} // namespace dom
namespace net {
@ -41,7 +40,8 @@ namespace ipc {
// we have to forward declare that function so we can use it as a friend.
nsresult LoadInfoArgsToLoadInfo(
const Maybe<mozilla::net::LoadInfoArgs>& aLoadInfoArgs,
nsINode* aCspToInheritLoadingContext, net::LoadInfo** outLoadInfo);
nsINode* aLoadingContext, nsINode* aCspToInheritLoadingContext,
net::LoadInfo** outLoadInfo);
} // namespace ipc
namespace net {
@ -72,10 +72,6 @@ class LoadInfo final : public nsILoadInfo {
LoadInfo(nsPIDOMWindowOuter* aOuterWindow, nsIPrincipal* aTriggeringPrincipal,
nsISupports* aContextForTopLevelLoad, nsSecurityFlags aSecurityFlags,
uint32_t aSandboxFlags);
LoadInfo(dom::CanonicalBrowsingContext* aBrowsingContext,
nsIPrincipal* aTriggeringPrincipal,
const OriginAttributes& aOriginAttributes, uint64_t aOuterWindowID,
nsSecurityFlags aSecurityFlags, uint32_t aSandboxFlags);
// create an exact copy of the loadinfo
already_AddRefed<nsILoadInfo> Clone() const;
@ -171,7 +167,8 @@ class LoadInfo final : public nsILoadInfo {
friend nsresult mozilla::ipc::LoadInfoArgsToLoadInfo(
const Maybe<mozilla::net::LoadInfoArgs>& aLoadInfoArgs,
nsINode* aCspToInheritLoadingContext, net::LoadInfo** outLoadInfo);
nsINode* aLoadingContext, nsINode* aCspToInheritLoadingContext,
net::LoadInfo** outLoadInfo);
~LoadInfo() = default;

Просмотреть файл

@ -13,7 +13,6 @@
#include "nsIChannel.h"
#include "nsIChildChannel.h"
#include "nsITraceableChannel.h"
#include "mozilla/dom/ClientInfo.h"
#define DOCUMENT_CHANNEL_IID \
{ \
@ -68,10 +67,6 @@ class DocumentChannel : public nsIIdentChannel, public nsITraceableChannel {
mTiming = aTiming;
}
void SetInitialClientInfo(const Maybe<dom::ClientInfo>& aInfo) {
mInitialClientInfo = aInfo;
}
protected:
nsDocShell* GetDocShell();
@ -103,7 +98,6 @@ class DocumentChannel : public nsIIdentChannel, public nsITraceableChannel {
nsCOMPtr<nsISupports> mOwner;
bool mPluginsAllowed = false;
RefPtr<nsDOMNavigationTiming> mTiming;
Maybe<dom::ClientInfo> mInitialClientInfo;
};
NS_DEFINE_STATIC_IID_ACCESSOR(DocumentChannel, DOCUMENT_CHANNEL_IID)

Просмотреть файл

@ -123,14 +123,6 @@ DocumentChannelChild::AsyncOpen(nsIStreamListener* aListener) {
args.asyncOpenTime() = mAsyncOpenTime;
args.documentOpenFlags() = mDocumentOpenFlags;
args.pluginsAllowed() = mPluginsAllowed;
args.outerWindowId() = mLoadInfo->GetOuterWindowID();
Maybe<IPCClientInfo> ipcClientInfo;
if (mInitialClientInfo.isSome()) {
ipcClientInfo.emplace(mInitialClientInfo.ref().ToIPC());
}
args.initialClientInfo() = ipcClientInfo;
if (mTiming) {
args.timing() = Some(mTiming);
}
@ -221,22 +213,20 @@ IPCResult DocumentChannelChild::RecvRedirectToRealChannel(
LOG(("DocumentChannelChild RecvRedirectToRealChannel [this=%p, uri=%s]", this,
aArgs.uri()->GetSpecOrDefault().get()));
// The document that created the cspToInherit.
// This is used when deserializing LoadInfo from the parent
// process, since we can't serialize Documents directly.
// TODO: For a fission OOP iframe this will be unavailable,
// as will the loadingContext computed in LoadInfoArgsToLoadInfo.
// Figure out if we need these for cross-origin subdocs.
RefPtr<dom::Document> loadingDocument;
mLoadInfo->GetLoadingDocument(getter_AddRefs(loadingDocument));
RefPtr<dom::Document> cspToInheritLoadingDocument;
nsCOMPtr<nsIContentSecurityPolicy> policy = mLoadState->Csp();
nsCOMPtr<nsIContentSecurityPolicy> policy = mLoadInfo->GetCspToInherit();
if (policy) {
nsWeakPtr ctx =
static_cast<nsCSPContext*>(policy.get())->GetLoadingContext();
cspToInheritLoadingDocument = do_QueryReferent(ctx);
}
nsCOMPtr<nsILoadInfo> loadInfo;
MOZ_ALWAYS_SUCCEEDS(LoadInfoArgsToLoadInfo(
aArgs.loadInfo(), cspToInheritLoadingDocument, getter_AddRefs(loadInfo)));
MOZ_ALWAYS_SUCCEEDS(LoadInfoArgsToLoadInfo(aArgs.loadInfo(), loadingDocument,
cspToInheritLoadingDocument,
getter_AddRefs(loadInfo)));
mLastVisitInfo = std::move(aArgs.lastVisitInfo());
mRedirects = std::move(aArgs.redirects());
@ -400,23 +390,25 @@ IPCResult DocumentChannelChild::RecvConfirmRedirect(
// not propagating the redirect into this process, we don't have an nsIChannel
// for the redirection and we have to do the checks manually.
// This just checks CSP thus far, hopefully there's not much else needed.
RefPtr<dom::Document> loadingDocument;
mLoadInfo->GetLoadingDocument(getter_AddRefs(loadingDocument));
RefPtr<dom::Document> cspToInheritLoadingDocument;
nsCOMPtr<nsIContentSecurityPolicy> policy = mLoadState->Csp();
nsCOMPtr<nsIContentSecurityPolicy> policy = mLoadInfo->GetCspToInherit();
if (policy) {
nsWeakPtr ctx =
static_cast<nsCSPContext*>(policy.get())->GetLoadingContext();
cspToInheritLoadingDocument = do_QueryReferent(ctx);
}
nsCOMPtr<nsILoadInfo> loadInfo;
MOZ_ALWAYS_SUCCEEDS(LoadInfoArgsToLoadInfo(Some(std::move(aLoadInfo)),
cspToInheritLoadingDocument,
getter_AddRefs(loadInfo)));
MOZ_ALWAYS_SUCCEEDS(LoadInfoArgsToLoadInfo(
Some(std::move(aLoadInfo)), loadingDocument, cspToInheritLoadingDocument,
getter_AddRefs(loadInfo)));
nsCOMPtr<nsIURI> originalUri;
GetOriginalURI(getter_AddRefs(originalUri));
Maybe<nsresult> cancelCode;
nsresult rv = CSPService::ConsultCSPForRedirect(originalUri, aNewUri,
loadInfo, cancelCode);
mLoadInfo, cancelCode);
aResolve(Tuple<const nsresult&, const Maybe<nsresult>&>(rv, cancelCode));
return IPC_OK();
}

Просмотреть файл

@ -7,7 +7,6 @@
#include "DocumentChannelParent.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/ClientInfo.h"
extern mozilla::LazyLogModule gDocumentChannelLog;
#define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)
@ -39,27 +38,17 @@ bool DocumentChannelParent::Init(BrowserParent* aBrowser,
RefPtr<class LoadInfo> loadInfo;
nsresult rv = mozilla::ipc::LoadInfoArgsToLoadInfo(Some(aArgs.loadInfo()),
getter_AddRefs(loadInfo));
Maybe<ClientInfo> clientInfo;
if (aArgs.initialClientInfo().isSome()) {
clientInfo.emplace(ClientInfo(aArgs.initialClientInfo().ref()));
}
RefPtr<BrowsingContext> bc;
loadInfo->GetTargetBrowsingContext(getter_AddRefs(bc));
MOZ_ASSERT(NS_SUCCEEDED(rv));
rv = NS_ERROR_UNEXPECTED;
if (!mParent->Open(bc->Canonical(), aBrowser->GetBrowsingContext(), loadState,
loadInfo, aArgs.loadFlags(), aArgs.loadType(),
aArgs.cacheKey(), aArgs.isActive(), aArgs.isTopLevelDoc(),
if (!mParent->Open(aBrowser->GetBrowsingContext(), loadState, loadInfo,
aArgs.loadFlags(), aArgs.loadType(), aArgs.cacheKey(),
aArgs.isActive(), aArgs.isTopLevelDoc(),
aArgs.hasNonEmptySandboxingFlags(), aArgs.topWindowURI(),
aArgs.contentBlockingAllowListPrincipal(),
aArgs.channelId(), aArgs.asyncOpenTime(),
aArgs.documentOpenFlags(), aArgs.pluginsAllowed(),
aArgs.timing().refOr(nullptr), std::move(clientInfo),
aArgs.outerWindowId(), &rv)) {
aArgs.timing().refOr(nullptr), &rv)) {
return SendFailedAsyncOpen(rv);
}

Просмотреть файл

@ -33,7 +33,6 @@
#include "nsCExternalHandlerService.h"
#include "nsMimeTypes.h"
#include "nsIViewSourceChannel.h"
#include "nsIOService.h"
mozilla::LazyLogModule gDocumentChannelLog("DocumentChannel");
#define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)
@ -249,48 +248,7 @@ DocumentLoadListener::~DocumentLoadListener() {
LOG(("DocumentLoadListener dtor [this=%p]", this));
}
already_AddRefed<LoadInfo> DocumentLoadListener::CreateLoadInfo(
CanonicalBrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState,
uint64_t aOuterWindowId) {
OriginAttributes attrs;
mLoadContext->GetOriginAttributes(attrs);
// TODO: Block copied from nsDocShell::DoURILoad, refactor out somewhere
bool inheritPrincipal = false;
if (aLoadState->PrincipalToInherit()) {
bool isSrcdoc =
aLoadState->HasLoadFlags(nsDocShell::INTERNAL_LOAD_FLAGS_IS_SRCDOC);
bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
aLoadState->PrincipalToInherit(), aLoadState->URI(),
true, // aInheritForAboutBlank
isSrcdoc);
bool isURIUniqueOrigin = nsIOService::IsDataURIUniqueOpaqueOrigin() &&
SchemeIsData(aLoadState->URI());
inheritPrincipal = inheritAttrs && !isURIUniqueOrigin;
}
nsSecurityFlags securityFlags =
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
uint32_t sandboxFlags = aBrowsingContext->GetSandboxFlags();
if (aLoadState->LoadType() == LOAD_ERROR_PAGE) {
securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE;
}
if (inheritPrincipal) {
securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
}
RefPtr<LoadInfo> loadInfo =
new LoadInfo(aBrowsingContext, aLoadState->TriggeringPrincipal(), attrs,
aOuterWindowId, securityFlags, sandboxFlags);
return loadInfo.forget();
}
bool DocumentLoadListener::Open(
CanonicalBrowsingContext* aBrowsingContext,
CanonicalBrowsingContext* aProcessTopBrowsingContext,
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
nsLoadFlags aLoadFlags, uint32_t aLoadType, uint32_t aCacheKey,
@ -299,31 +257,13 @@ bool DocumentLoadListener::Open(
const Maybe<PrincipalInfo>& aContentBlockingAllowListPrincipal,
const uint64_t& aChannelId, const TimeStamp& aAsyncOpenTime,
const Maybe<uint32_t>& aDocumentOpenFlags, bool aPluginsAllowed,
nsDOMNavigationTiming* aTiming, Maybe<ClientInfo>&& aInfo,
uint64_t aOuterWindowId, nsresult* aRv) {
nsDOMNavigationTiming* aTiming, nsresult* aRv) {
LOG(("DocumentLoadListener Open [this=%p, uri=%s]", this,
aLoadState->URI()->GetSpecOrDefault().get()));
OriginAttributes attrs;
mLoadContext->GetOriginAttributes(attrs);
// If this is a top-level load, then rebuild the LoadInfo from scratch,
// since the goal is to be able to initiate loads in the parent, where the
// content process won't have provided us with an existing one.
// TODO: Handle TYPE_SUBDOCUMENT LoadInfo construction, and stop passing
// aLoadInfo across IPC.
RefPtr<LoadInfo> loadInfo = aLoadInfo;
if (!aBrowsingContext->GetParent()) {
// If we're a top level load, then we should have not got an existing
// LoadInfo, or if we did, it should be TYPE_DOCUMENT.
MOZ_ASSERT(!aLoadInfo || aLoadInfo->InternalContentPolicyType() ==
nsIContentPolicy::TYPE_DOCUMENT);
loadInfo = CreateLoadInfo(aBrowsingContext, aLoadState, aOuterWindowId);
}
if (!nsDocShell::CreateAndConfigureRealChannelForLoadState(
aLoadState, loadInfo, mParentChannelListener, nullptr, attrs,
aLoadFlags, aLoadType, aCacheKey, aIsActive, aIsTopLevelDoc,
aLoadState, aLoadInfo, mParentChannelListener, nullptr, aLoadFlags,
aLoadType, aCacheKey, aIsActive, aIsTopLevelDoc,
aHasNonEmptySandboxingFlags, *aRv, getter_AddRefs(mChannel))) {
mParentChannelListener = nullptr;
return false;
@ -378,7 +318,7 @@ bool DocumentLoadListener::Open(
// Setup a ClientChannelHelper to watch for redirects, and copy
// across any serviceworker related data between channels as needed.
AddClientChannelHelperInParent(mChannel, std::move(aInfo));
AddClientChannelHelperInParent(mChannel, GetMainThreadSerialEventTarget());
if (aDocumentOpenFlags) {
RefPtr<ParentProcessDocumentOpenInfo> openInfo =

Просмотреть файл

@ -76,8 +76,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
// Must be the same BrowsingContext as was passed to the constructor, we
// expect Necko to pass it again so that we don't need a member var for
// it.
bool Open(dom::CanonicalBrowsingContext* aBrowsingContext,
dom::CanonicalBrowsingContext* aProcessTopBrowsingContext,
bool Open(dom::CanonicalBrowsingContext* aProcessTopBrowsingContext,
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
nsLoadFlags aLoadFlags, uint32_t aLoadType, uint32_t aCacheKey,
bool aIsActive, bool aIsTopLevelDoc,
@ -86,8 +85,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
const Maybe<ipc::PrincipalInfo>& aContentBlockingAllowListPrincipal,
const uint64_t& aChannelId, const TimeStamp& aAsyncOpenTime,
const Maybe<uint32_t>& aDocumentOpenFlags, bool aPluginsAllowed,
nsDOMNavigationTiming* aTiming, Maybe<dom::ClientInfo>&& aInfo,
uint64_t aOuterWindowId, nsresult* aRv);
nsDOMNavigationTiming* aTiming, nsresult* aRv);
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
@ -202,13 +200,6 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
RedirectToRealChannel(uint32_t aRedirectFlags, uint32_t aLoadFlags,
const Maybe<uint64_t>& aDestinationProcess);
// Construct a LoadInfo object to use for the internal channel.
// TODO: This currently only supports creating top window TYPE_DOCUMENT
// LoadInfos
already_AddRefed<LoadInfo> CreateLoadInfo(
dom::CanonicalBrowsingContext* aBrowsingContext,
nsDocShellLoadState* aLoadState, uint64_t aOuterWindowId);
// This defines a variant that describes all the attribute setters (and their
// parameters) from nsIParentChannel
//

Просмотреть файл

@ -412,8 +412,6 @@ struct DocumentChannelCreationArgs {
bool hasNonEmptySandboxingFlags;
bool pluginsAllowed;
nsDOMNavigationTiming? timing;
IPCClientInfo? initialClientInfo;
uint64_t outerWindowId;
};
struct DocumentChannelRedirect {