Bug 1607984 - P12-3. Let DocumentChannel decides when it can be used. r=mattwoodrow

Depends on D72272

Differential Revision: https://phabricator.services.mozilla.com/D72273
This commit is contained in:
Jean-Yves Avenard
2020-04-24 02:22:58 +00:00
parent ebef59ef6d
commit 5ed9e02da8
3 changed files with 65 additions and 38 deletions

View File

@@ -73,9 +73,8 @@
#include "mozilla/dom/nsCSPContext.h"
#include "mozilla/dom/LoadURIOptionsBinding.h"
#include "mozilla/dom/JSWindowActorChild.h"
#include "mozilla/net/DocumentChannel.h"
#include "nsSHEntry.h"
#include "mozilla/net/DocumentChannelChild.h"
#include "mozilla/net/DocumentChannel.h"
#include "mozilla/net/UrlClassifierFeatureFactory.h"
#include "ReferrerInfo.h"
@@ -9180,23 +9179,6 @@ static bool IsConsideredSameOriginForUIR(nsIPrincipal* aTriggeringPrincipal,
return NS_OK;
}
// Changes here should also be made in
// E10SUtils.documentChannelPermittedForURI().
static bool URIUsesDocChannel(nsIURI* aURI) {
if (SchemeIsJavascript(aURI) || NS_IsAboutBlank(aURI)) {
return false;
}
nsCString spec = aURI->GetSpecOrDefault();
if (spec.EqualsLiteral("about:printpreview") ||
spec.EqualsLiteral("about:crashcontent")) {
return false;
}
return true;
}
/* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState(
BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState,
LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks,
@@ -9597,8 +9579,9 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
// If we have a pending channel, use the channel we've already created here.
// We don't need to set up load flags for our channel, as it has already been
// created.
nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel();
if (channel) {
if (nsCOMPtr<nsIChannel> channel =
aLoadState->GetPendingRedirectedChannel()) {
MOZ_ASSERT(!aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC),
"pending channel for srcdoc load?");
@@ -9767,20 +9750,11 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
cacheKey = mOSHE->GetCacheKey();
}
// We want to use DocumentChannel if we're using a supported scheme. Sandboxed
// srcdoc loads break due to failing assertions after changing processes, and
// non-sandboxed srcdoc loads need to share the same principal object as their
// outer document (and must load in the same process), which breaks if we
// serialize to the parent process.
bool canUseDocumentChannel =
!aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC) &&
URIUsesDocChannel(aLoadState->URI());
if (StaticPrefs::browser_tabs_documentchannel() && XRE_IsContentProcess() &&
canUseDocumentChannel) {
channel =
new DocumentChannelChild(aLoadState, loadInfo, loadFlags, cacheKey);
channel->SetNotificationCallbacks(this);
nsCOMPtr<nsIChannel> channel;
if (DocumentChannel::CanUseDocumentChannel(aLoadState)) {
channel = DocumentChannel::CreateDocumentChannel(aLoadState, loadInfo,
loadFlags, this, cacheKey);
MOZ_ASSERT(channel);
} else if (!CreateAndConfigureRealChannelForLoadState(
mBrowsingContext, aLoadState, loadInfo, this, this,
GetOriginAttributes(), loadFlags, cacheKey, rv,

View File

@@ -10,12 +10,14 @@
#include "SerializedLoadContext.h"
#include "mozIThirdPartyUtil.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/StaticPrefs_browser.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/nsCSPContext.h"
#include "mozilla/extensions/StreamFilterParent.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/URIUtils.h"
#include "mozilla/net/DocumentChannelChild.h"
#include "mozilla/net/HttpChannelChild.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/net/UrlClassifierCommon.h"
@@ -24,6 +26,7 @@
#include "nsDocShellLoadState.h"
#include "nsHttpHandler.h"
#include "nsIInputStreamChannel.h"
#include "nsNetUtil.h"
#include "nsQueryObject.h"
#include "nsSerializationHelper.h"
#include "nsStreamListenerWrapper.h"
@@ -135,6 +138,43 @@ nsDocShell* DocumentChannel::GetDocShell() {
return nsDocShell::Cast(docshell);
}
// Changes here should also be made in
// E10SUtils.documentChannelPermittedForURI().
static bool URIUsesDocChannel(nsIURI* aURI) {
if (SchemeIsJavascript(aURI) || NS_IsAboutBlank(aURI)) {
return false;
}
nsCString spec = aURI->GetSpecOrDefault();
return !spec.EqualsLiteral("about:printpreview") &&
!spec.EqualsLiteral("about:crashcontent");
}
bool DocumentChannel::CanUseDocumentChannel(nsDocShellLoadState* aLoadState) {
MOZ_ASSERT(aLoadState);
// We want to use DocumentChannel if we're using a supported scheme. Sandboxed
// srcdoc loads break due to failing assertions after changing processes, and
// non-sandboxed srcdoc loads need to share the same principal object as their
// outer document (and must load in the same process), which breaks if we
// serialize to the parent process.
return StaticPrefs::browser_tabs_documentchannel() &&
XRE_IsContentProcess() &&
!aLoadState->HasLoadFlags(nsDocShell::INTERNAL_LOAD_FLAGS_IS_SRCDOC) &&
URIUsesDocChannel(aLoadState->URI());
}
/* static */
already_AddRefed<DocumentChannel> DocumentChannel::CreateDocumentChannel(
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks,
uint32_t aCacheKey) {
MOZ_ASSERT(XRE_IsContentProcess());
RefPtr<DocumentChannel> channel =
new DocumentChannelChild(aLoadState, aLoadInfo, aLoadFlags, aCacheKey);
channel->SetNotificationCallbacks(aNotificationCallbacks);
return channel.forget();
}
//-----------------------------------------------------------------------------
// DocumentChannel::nsITraceableChannel
//-----------------------------------------------------------------------------

View File

@@ -45,9 +45,6 @@ class DocumentChannel : public nsIIdentChannel, public nsITraceableChannel {
NS_DECLARE_STATIC_IID_ACCESSOR(DOCUMENT_CHANNEL_IID)
DocumentChannel(nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
nsLoadFlags aLoadFlags, uint32_t aCacheKey);
const nsTArray<DocumentChannelRedirect>& GetRedirectChain() const {
return mRedirects;
}
@@ -65,7 +62,23 @@ class DocumentChannel : public nsIIdentChannel, public nsITraceableChannel {
mInitialClientInfo = aInfo;
}
/**
* Will create the appropriate document channel:
* Either a DocumentChannelChild if called from the content process or
* a ParentProcessDocumentChannel if called from the parent process.
* This operation is infallible.
*/
static already_AddRefed<DocumentChannel> CreateDocumentChannel(
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks,
uint32_t aCacheKey);
static bool CanUseDocumentChannel(nsDocShellLoadState* aLoadState);
protected:
DocumentChannel(nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
nsLoadFlags aLoadFlags, uint32_t aCacheKey);
void ShutdownListeners(nsresult aStatusCode);
void DisconnectChildListeners(const nsresult& aStatus,
const nsresult& aLoadGroupStatus);