зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1646899 - P4: Handle object & embed via DocumentChannel. r=mattwoodrow,jya
Pass internal content policy type to DLL and switch behavior depending on type being loaded. This implementation immediately redirects channel back to the content process for further handling. Differential Revision: https://phabricator.services.mozilla.com/D80407
This commit is contained in:
Родитель
8847465b59
Коммит
f5fd7b3d97
|
@ -9253,9 +9253,26 @@ nsIPrincipal* nsDocShell::GetInheritedPrincipal(
|
|||
if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) {
|
||||
timedChannel->SetTimingEnabled(true);
|
||||
|
||||
auto& embedderElementType = aBrowsingContext->GetEmbedderElementType();
|
||||
if (embedderElementType) {
|
||||
timedChannel->SetInitiatorType(*embedderElementType);
|
||||
nsString initiatorType;
|
||||
switch (aLoadInfo->InternalContentPolicyType()) {
|
||||
case nsIContentPolicy::TYPE_INTERNAL_EMBED:
|
||||
initiatorType = u"embed"_ns;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
|
||||
initiatorType = u"object"_ns;
|
||||
break;
|
||||
default: {
|
||||
const auto& embedderElementType =
|
||||
aBrowsingContext->GetEmbedderElementType();
|
||||
if (embedderElementType) {
|
||||
initiatorType = *embedderElementType;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!initiatorType.IsEmpty()) {
|
||||
timedChannel->SetInitiatorType(initiatorType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9574,9 +9591,9 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
|
|||
nsCOMPtr<nsIChannel> channel;
|
||||
if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI(),
|
||||
aLoadState->LoadFlags())) {
|
||||
channel = DocumentChannel::CreateDocumentChannel(aLoadState, loadInfo,
|
||||
loadFlags, this, cacheKey,
|
||||
uriModified, isXFOError);
|
||||
channel = DocumentChannel::CreateForDocument(aLoadState, loadInfo,
|
||||
loadFlags, this, cacheKey,
|
||||
uriModified, isXFOError);
|
||||
MOZ_ASSERT(channel);
|
||||
|
||||
// Disable keyword fixup when using DocumentChannel, since
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDocShellCID.h"
|
||||
#include "nsDocShellLoadState.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
@ -88,6 +89,7 @@
|
|||
#include "mozilla/dom/HTMLObjectElement.h"
|
||||
#include "mozilla/dom/UserActivation.h"
|
||||
#include "mozilla/dom/nsCSPContext.h"
|
||||
#include "mozilla/net/DocumentChannel.h"
|
||||
#include "mozilla/net/UrlClassifierFeatureFactory.h"
|
||||
#include "mozilla/LoadInfo.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
|
@ -2267,38 +2269,28 @@ nsresult nsObjectLoadingContent::OpenChannel() {
|
|||
RefPtr<ObjectInterfaceRequestorShim> shim =
|
||||
new ObjectInterfaceRequestorShim(this);
|
||||
|
||||
bool inherit = nsContentUtils::ChannelShouldInheritPrincipal(
|
||||
thisContent->NodePrincipal(), mURI,
|
||||
true, // aInheritForAboutBlank
|
||||
false); // aForceInherit
|
||||
nsSecurityFlags securityFlags =
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
|
||||
bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
|
||||
thisContent->NodePrincipal(), // aLoadState->PrincipalToInherit()
|
||||
mURI, // aLoadState->URI()
|
||||
true, // aInheritForAboutBlank
|
||||
false); // aForceInherit
|
||||
|
||||
bool isURIUniqueOrigin =
|
||||
StaticPrefs::security_data_uri_unique_opaque_origin() &&
|
||||
mURI->SchemeIs("data");
|
||||
SchemeIsData(mURI);
|
||||
bool inheritPrincipal = inheritAttrs && !isURIUniqueOrigin;
|
||||
|
||||
if (inherit && !isURIUniqueOrigin) {
|
||||
nsSecurityFlags securityFlags =
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
|
||||
if (inheritPrincipal) {
|
||||
securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
|
||||
}
|
||||
|
||||
nsContentPolicyType contentPolicyType = GetContentPolicyType();
|
||||
|
||||
rv = NS_NewChannel(getter_AddRefs(chan), mURI, thisContent, securityFlags,
|
||||
contentPolicyType,
|
||||
nullptr, // aPerformanceStorage
|
||||
group, // aLoadGroup
|
||||
shim, // aCallbacks
|
||||
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
|
||||
nsIChannel::LOAD_BYPASS_SERVICE_WORKER |
|
||||
nsIRequest::LOAD_HTML_OBJECT_DATA,
|
||||
nullptr, // aIoService
|
||||
doc->GetSandboxFlags());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (inherit) {
|
||||
nsCOMPtr<nsILoadInfo> loadinfo = chan->LoadInfo();
|
||||
loadinfo->SetPrincipalToInherit(thisContent->NodePrincipal());
|
||||
}
|
||||
nsLoadFlags loadFlags = nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
|
||||
nsIChannel::LOAD_BYPASS_SERVICE_WORKER |
|
||||
nsIRequest::LOAD_HTML_OBJECT_DATA;
|
||||
uint32_t sandboxFlags = doc->GetSandboxFlags();
|
||||
|
||||
// For object loads we store the CSP that potentially needs to
|
||||
// be inherited, e.g. in case we are loading an opaque origin
|
||||
|
@ -2307,14 +2299,80 @@ nsresult nsObjectLoadingContent::OpenChannel() {
|
|||
// (do not share the same reference) otherwise a Meta CSP of an
|
||||
// opaque origin will incorrectly be propagated to the embedding
|
||||
// document.
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = doc->GetCsp();
|
||||
if (csp) {
|
||||
RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
|
||||
RefPtr<nsCSPContext> cspToInherit;
|
||||
if (nsCOMPtr<nsIContentSecurityPolicy> csp = doc->GetCsp()) {
|
||||
cspToInherit = new nsCSPContext();
|
||||
cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
|
||||
nsCOMPtr<nsILoadInfo> loadinfo = chan->LoadInfo();
|
||||
static_cast<LoadInfo*>(loadinfo.get())->SetCSPToInherit(cspToInherit);
|
||||
}
|
||||
|
||||
// --- Create LoadInfo
|
||||
RefPtr<LoadInfo> loadInfo = new LoadInfo(
|
||||
/*aLoadingPrincipal = aLoadingContext->NodePrincipal() */ nullptr,
|
||||
/*aTriggeringPrincipal = aLoadingPrincipal */ nullptr,
|
||||
/*aLoadingContext = */ thisContent,
|
||||
/*aSecurityFlags = */ securityFlags,
|
||||
/*aContentPolicyType = */ contentPolicyType,
|
||||
/*aLoadingClientInfo = */ Nothing(),
|
||||
/*aController = */ Nothing(),
|
||||
/*aSandboxFlags = */ sandboxFlags);
|
||||
|
||||
if (inheritAttrs) {
|
||||
loadInfo->SetPrincipalToInherit(thisContent->NodePrincipal());
|
||||
}
|
||||
|
||||
if (cspToInherit) {
|
||||
loadInfo->SetCSPToInherit(cspToInherit);
|
||||
}
|
||||
|
||||
if (DocumentChannel::CanUseDocumentChannel(
|
||||
mURI, nsIWebNavigation::LOAD_FLAGS_NONE)) {
|
||||
// --- Create LoadState
|
||||
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(mURI);
|
||||
loadState->SetPrincipalToInherit(thisContent->NodePrincipal());
|
||||
loadState->SetTriggeringPrincipal(loadInfo->TriggeringPrincipal());
|
||||
if (cspToInherit) {
|
||||
loadState->SetCsp(cspToInherit);
|
||||
}
|
||||
// TODO(djg): This was httpChan->SetReferrerInfoWithoutClone(referrerInfo);
|
||||
// Is the ...WithoutClone(...) important?
|
||||
auto referrerInfo = MakeRefPtr<ReferrerInfo>(*doc);
|
||||
loadState->SetReferrerInfo(referrerInfo);
|
||||
|
||||
chan =
|
||||
DocumentChannel::CreateForObject(loadState, loadInfo, loadFlags, shim);
|
||||
MOZ_ASSERT(chan);
|
||||
// NS_NewChannel sets the group on the channel. CreateDocumentChannel does
|
||||
// not.
|
||||
chan->SetLoadGroup(group);
|
||||
} else {
|
||||
rv = NS_NewChannelInternal(getter_AddRefs(chan), // outChannel
|
||||
mURI, // aUri
|
||||
loadInfo, // aLoadInfo
|
||||
nullptr, // aPerformanceStorage
|
||||
group, // aLoadGroup
|
||||
shim, // aCallbacks
|
||||
loadFlags, // aLoadFlags
|
||||
nullptr); // aIoService
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (inheritAttrs) {
|
||||
nsCOMPtr<nsILoadInfo> loadinfo = chan->LoadInfo();
|
||||
loadinfo->SetPrincipalToInherit(thisContent->NodePrincipal());
|
||||
}
|
||||
|
||||
// For object loads we store the CSP that potentially needs to
|
||||
// be inherited, 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.
|
||||
if (cspToInherit) {
|
||||
nsCOMPtr<nsILoadInfo> loadinfo = chan->LoadInfo();
|
||||
static_cast<LoadInfo*>(loadinfo.get())->SetCSPToInherit(cspToInherit);
|
||||
}
|
||||
};
|
||||
|
||||
// Referrer
|
||||
nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
|
||||
if (httpChan) {
|
||||
|
|
|
@ -88,6 +88,15 @@ static nsContentPolicyType InternalContentPolicyTypeForFrame(
|
|||
aSandboxFlags);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<LoadInfo> LoadInfo::CreateForNonDocument(
|
||||
dom::WindowGlobalParent* aParentWGP, nsIPrincipal* aTriggeringPrincipal,
|
||||
uint64_t aFrameOuterWindowID, nsContentPolicyType aContentPolicyType,
|
||||
nsSecurityFlags aSecurityFlags, uint32_t aSandboxFlags) {
|
||||
return MakeAndAddRef<LoadInfo>(aParentWGP, aTriggeringPrincipal,
|
||||
aFrameOuterWindowID, aContentPolicyType,
|
||||
aSecurityFlags, aSandboxFlags);
|
||||
}
|
||||
|
||||
LoadInfo::LoadInfo(
|
||||
nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal,
|
||||
nsINode* aLoadingContext, nsSecurityFlags aSecurityFlags,
|
||||
|
@ -1816,13 +1825,12 @@ PerformanceStorage* LoadInfo::GetPerformanceStorage() {
|
|||
return mPerformanceStorage;
|
||||
}
|
||||
|
||||
RefPtr<dom::Document> loadingDocument;
|
||||
GetLoadingDocument(getter_AddRefs(loadingDocument));
|
||||
if (!loadingDocument) {
|
||||
auto* innerWindow = nsGlobalWindowInner::GetInnerWindowWithId(mInnerWindowID);
|
||||
if (!innerWindow) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!TriggeringPrincipal()->Equals(loadingDocument->NodePrincipal())) {
|
||||
if (!TriggeringPrincipal()->Equals(innerWindow->GetPrincipal())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1834,11 +1842,6 @@ PerformanceStorage* LoadInfo::GetPerformanceStorage() {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> innerWindow = loadingDocument->GetInnerWindow();
|
||||
if (!innerWindow) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mozilla::dom::Performance* performance = innerWindow->GetPerformance();
|
||||
if (!performance) {
|
||||
return nullptr;
|
||||
|
|
|
@ -73,6 +73,12 @@ class LoadInfo final : public nsILoadInfo {
|
|||
nsIPrincipal* aTriggeringPrincipal, uint64_t aFrameOuterWindowID,
|
||||
nsSecurityFlags aSecurityFlags, uint32_t aSandboxFlags);
|
||||
|
||||
// Use for non-{TYPE_DOCUMENT|TYPE_FRAME|TYPE_IFRAME} load.
|
||||
static already_AddRefed<LoadInfo> CreateForNonDocument(
|
||||
dom::WindowGlobalParent* aParentWGP, nsIPrincipal* aTriggeringPrincipal,
|
||||
uint64_t aFrameOuterWindowID, nsContentPolicyType aContentPolicyType,
|
||||
nsSecurityFlags aSecurityFlags, uint32_t aSandboxFlags);
|
||||
|
||||
// aLoadingPrincipal MUST NOT BE NULL.
|
||||
LoadInfo(nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal,
|
||||
nsINode* aLoadingContext, nsSecurityFlags aSecurityFlags,
|
||||
|
@ -90,12 +96,6 @@ class LoadInfo final : public nsILoadInfo {
|
|||
nsISupports* aContextForTopLevelLoad, nsSecurityFlags aSecurityFlags,
|
||||
uint32_t aSandboxFlags);
|
||||
|
||||
// Used for loads initiated by DocumentLoadListener.
|
||||
LoadInfo(dom::WindowGlobalParent* aParentWGP,
|
||||
nsIPrincipal* aTriggeringPrincipal, uint64_t aFrameOuterWindowID,
|
||||
nsContentPolicyType aContentPolicyType,
|
||||
nsSecurityFlags aSecurityFlags, uint32_t aSandboxFlags);
|
||||
|
||||
private:
|
||||
// Use factory function CreateForDocument
|
||||
// Used for TYPE_DOCUMENT load.
|
||||
|
@ -110,6 +110,13 @@ class LoadInfo final : public nsILoadInfo {
|
|||
nsIPrincipal* aTriggeringPrincipal, uint64_t aFrameOuterWindowID,
|
||||
nsSecurityFlags aSecurityFlags, uint32_t aSandboxFlags);
|
||||
|
||||
// Used for loads initiated by DocumentLoadListener that are not TYPE_DOCUMENT
|
||||
// | TYPE_FRAME | TYPE_FRAME.
|
||||
LoadInfo(dom::WindowGlobalParent* aParentWGP,
|
||||
nsIPrincipal* aTriggeringPrincipal, uint64_t aFrameOuterWindowID,
|
||||
nsContentPolicyType aContentPolicyType,
|
||||
nsSecurityFlags aSecurityFlags, uint32_t aSandboxFlags);
|
||||
|
||||
public:
|
||||
// Compute a list of ancestor principals and BrowsingContext IDs.
|
||||
// See methods AncestorPrincipals and AncestorBrowsingContextIDs
|
||||
|
@ -132,6 +139,12 @@ class LoadInfo final : public nsILoadInfo {
|
|||
// when a separate request is made with the same security properties.
|
||||
already_AddRefed<nsILoadInfo> CloneForNewRequest() const;
|
||||
|
||||
// The `nsContentPolicyType GetExternalContentPolicyType()` version in the
|
||||
// base class is hidden by the implementation of
|
||||
// `GetExternalContentPolicyType(nsContentPolicyType* aResult)` in
|
||||
// LoadInfo.cpp. Explicit mark it visible.
|
||||
using nsILoadInfo::GetExternalContentPolicyType;
|
||||
|
||||
void SetIsPreflight();
|
||||
void SetUpgradeInsecureRequests(bool aValue);
|
||||
void SetBrowserUpgradeInsecureRequests();
|
||||
|
|
|
@ -97,16 +97,22 @@ void DocumentChannel::ShutdownListeners(nsresult aStatusCode) {
|
|||
mIsPending = false;
|
||||
|
||||
listener = mListener; // it might have changed!
|
||||
if (listener) {
|
||||
listener->OnStopRequest(this, aStatusCode);
|
||||
}
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = mLoadGroup;
|
||||
|
||||
mListener = nullptr;
|
||||
mLoadGroup = nullptr;
|
||||
mCallbacks = nullptr;
|
||||
|
||||
if (mLoadGroup) {
|
||||
mLoadGroup->RemoveRequest(this, nullptr, aStatusCode);
|
||||
mLoadGroup = nullptr;
|
||||
}
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"DocumentChannel::ShutdownListeners", [=, self = RefPtr{this}] {
|
||||
if (listener) {
|
||||
listener->OnStopRequest(self, aStatusCode);
|
||||
}
|
||||
|
||||
if (loadGroup) {
|
||||
loadGroup->RemoveRequest(self, nullptr, aStatusCode);
|
||||
}
|
||||
}));
|
||||
|
||||
DeleteIPDL();
|
||||
}
|
||||
|
@ -171,7 +177,7 @@ bool DocumentChannel::CanUseDocumentChannel(nsIURI* aURI, uint32_t aLoadFlags) {
|
|||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<DocumentChannel> DocumentChannel::CreateDocumentChannel(
|
||||
already_AddRefed<DocumentChannel> DocumentChannel::CreateForDocument(
|
||||
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks,
|
||||
uint32_t aCacheKey, bool aUriModified, bool aIsXFOError) {
|
||||
|
@ -188,6 +194,14 @@ already_AddRefed<DocumentChannel> DocumentChannel::CreateDocumentChannel(
|
|||
return channel.forget();
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<DocumentChannel> DocumentChannel::CreateForObject(
|
||||
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks) {
|
||||
return CreateForDocument(aLoadState, aLoadInfo, aLoadFlags,
|
||||
aNotificationCallbacks, 0, false, false);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DocumentChannel::nsITraceableChannel
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -290,9 +304,17 @@ DocumentChannel::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
|
|||
}
|
||||
|
||||
NS_IMETHODIMP DocumentChannel::SetLoadFlags(nsLoadFlags aLoadFlags) {
|
||||
NS_ERROR(
|
||||
"DocumentChannel::SetLoadFlags: "
|
||||
"Don't set flags after creation");
|
||||
auto contentPolicy = mLoadInfo->GetExternalContentPolicyType();
|
||||
// Setting load flags for TYPE_OBJECT is permissible before channel to parent
|
||||
// is opened.
|
||||
if (contentPolicy != nsIContentPolicy::TYPE_OBJECT || mWasOpened) {
|
||||
MOZ_CRASH("DocumentChannel::SetLoadFlags: Don't set flags after creation");
|
||||
NS_ERROR(
|
||||
"DocumentChannel::SetLoadFlags: "
|
||||
"Don't set flags after creation");
|
||||
} else {
|
||||
mLoadFlags = aLoadFlags;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -432,6 +454,23 @@ DocumentChannel::SetChannelId(uint64_t aChannelId) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
uint64_t InnerWindowIDForExtantDoc(nsDocShell* docShell) {
|
||||
if (!docShell) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Document* doc = docShell->GetExtantDocument();
|
||||
if (!doc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return doc->InnerWindowID();
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "nsIChildChannel.h"
|
||||
#include "nsITraceableChannel.h"
|
||||
|
||||
class nsDocShell;
|
||||
|
||||
#define DOCUMENT_CHANNEL_IID \
|
||||
{ \
|
||||
0x6977bc44, 0xb1db, 0x41b7, { \
|
||||
|
@ -25,6 +27,8 @@
|
|||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
uint64_t InnerWindowIDForExtantDoc(nsDocShell* docShell);
|
||||
|
||||
/**
|
||||
* DocumentChannel is a protocol agnostic placeholder nsIChannel implementation
|
||||
* that we use so that nsDocShell knows about a connecting load. It transfers
|
||||
|
@ -59,10 +63,13 @@ class DocumentChannel : public nsIIdentChannel, public nsITraceableChannel {
|
|||
* a ParentProcessDocumentChannel if called from the parent process.
|
||||
* This operation is infallible.
|
||||
*/
|
||||
static already_AddRefed<DocumentChannel> CreateDocumentChannel(
|
||||
static already_AddRefed<DocumentChannel> CreateForDocument(
|
||||
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks,
|
||||
uint32_t aCacheKey, bool aUriModified, bool aIsXFOError);
|
||||
static already_AddRefed<DocumentChannel> CreateForObject(
|
||||
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks);
|
||||
|
||||
static bool CanUseDocumentChannel(nsIURI* aURI, uint32_t aLoadFlags);
|
||||
|
||||
|
|
|
@ -73,8 +73,16 @@ DocumentChannelChild::AsyncOpen(nsIStreamListener* aListener) {
|
|||
|
||||
gHttpHandler->OnOpeningDocumentRequest(this);
|
||||
|
||||
if (!GetDocShell() || !GetDocShell()->GetBrowsingContext() ||
|
||||
GetDocShell()->GetBrowsingContext()->IsDiscarded()) {
|
||||
RefPtr<nsDocShell> docShell = GetDocShell();
|
||||
if (!docShell) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// `loadingContext` is the BC that is initiating the resource load.
|
||||
// For normal subdocument loads, the BC is the one that the subdoc will load
|
||||
// into. For <object>/<embed> it's the embedder doc's BC.
|
||||
RefPtr<BrowsingContext> loadingContext = docShell->GetBrowsingContext();
|
||||
if (!loadingContext || loadingContext->IsDiscarded()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -84,9 +92,6 @@ DocumentChannelChild::AsyncOpen(nsIStreamListener* aListener) {
|
|||
args.cacheKey() = mCacheKey;
|
||||
args.channelId() = mChannelId;
|
||||
args.asyncOpenTime() = mAsyncOpenTime;
|
||||
args.outerWindowId() = GetDocShell()->GetOuterWindowID();
|
||||
args.uriModified() = mUriModified;
|
||||
args.isXFOError() = mIsXFOError;
|
||||
|
||||
Maybe<IPCClientInfo> ipcClientInfo;
|
||||
if (mInitialClientInfo.isSome()) {
|
||||
|
@ -99,15 +104,44 @@ DocumentChannelChild::AsyncOpen(nsIStreamListener* aListener) {
|
|||
}
|
||||
|
||||
args.hasValidTransientUserAction() =
|
||||
GetDocShell()
|
||||
->GetBrowsingContext()
|
||||
->HasValidTransientUserGestureActivation();
|
||||
loadingContext->HasValidTransientUserGestureActivation();
|
||||
|
||||
GetDocShell()->GetBrowsingContext()->SetCurrentLoadIdentifier(
|
||||
Some(mLoadState->GetLoadIdentifier()));
|
||||
switch (mLoadInfo->GetExternalContentPolicyType()) {
|
||||
case nsIContentPolicy::TYPE_DOCUMENT:
|
||||
case nsIContentPolicy::TYPE_SUBDOCUMENT: {
|
||||
DocumentCreationArgs docArgs;
|
||||
docArgs.outerWindowId() = docShell->GetOuterWindowID();
|
||||
docArgs.uriModified() = mUriModified;
|
||||
docArgs.isXFOError() = mIsXFOError;
|
||||
|
||||
gNeckoChild->SendPDocumentChannelConstructor(
|
||||
this, GetDocShell()->GetBrowsingContext(), args);
|
||||
args.elementCreationArgs() = docArgs;
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIContentPolicy::TYPE_OBJECT: {
|
||||
ObjectCreationArgs objectArgs;
|
||||
objectArgs.embedderInnerWindowId() = InnerWindowIDForExtantDoc(docShell);
|
||||
objectArgs.loadFlags() = mLoadFlags;
|
||||
objectArgs.contentPolicyType() = mLoadInfo->InternalContentPolicyType();
|
||||
objectArgs.isUrgentStart() = UserActivation::IsHandlingUserInput();
|
||||
|
||||
args.elementCreationArgs() = objectArgs;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (mLoadInfo->GetExternalContentPolicyType()) {
|
||||
case nsIContentPolicy::TYPE_DOCUMENT:
|
||||
case nsIContentPolicy::TYPE_SUBDOCUMENT:
|
||||
loadingContext->SetCurrentLoadIdentifier(
|
||||
Some(mLoadState->GetLoadIdentifier()));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gNeckoChild->SendPDocumentChannelConstructor(this, loadingContext, args);
|
||||
|
||||
mIsPending = true;
|
||||
mWasOpened = true;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||
#include "mozilla/dom/ClientInfo.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "nsDocShellLoadState.h"
|
||||
|
||||
extern mozilla::LazyLogModule gDocumentChannelLog;
|
||||
#define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)
|
||||
|
@ -51,12 +52,30 @@ bool DocumentChannelParent::Init(dom::CanonicalBrowsingContext* aContext,
|
|||
}
|
||||
|
||||
nsresult rv = NS_ERROR_UNEXPECTED;
|
||||
promise = mDocumentLoadListener->Open(
|
||||
loadState, aArgs.cacheKey(), Some(aArgs.channelId()),
|
||||
aArgs.asyncOpenTime(), aArgs.timing().refOr(nullptr),
|
||||
std::move(clientInfo), aArgs.outerWindowId(),
|
||||
aArgs.hasValidTransientUserAction(), Some(aArgs.uriModified()),
|
||||
Some(aArgs.isXFOError()), IProtocol::OtherPid(), &rv);
|
||||
|
||||
if (aArgs.elementCreationArgs().type() ==
|
||||
DocumentChannelElementCreationArgs::TDocumentCreationArgs) {
|
||||
const DocumentCreationArgs& docArgs = aArgs.elementCreationArgs();
|
||||
|
||||
promise = mDocumentLoadListener->OpenDocument(
|
||||
loadState, aArgs.cacheKey(), Some(aArgs.channelId()),
|
||||
aArgs.asyncOpenTime(), aArgs.timing().refOr(nullptr),
|
||||
std::move(clientInfo), docArgs.outerWindowId(),
|
||||
aArgs.hasValidTransientUserAction(), Some(docArgs.uriModified()),
|
||||
Some(docArgs.isXFOError()), IProtocol::OtherPid(), &rv);
|
||||
|
||||
} else {
|
||||
const ObjectCreationArgs& objectArgs = aArgs.elementCreationArgs();
|
||||
|
||||
promise = mDocumentLoadListener->OpenObject(
|
||||
loadState, aArgs.cacheKey(), Some(aArgs.channelId()),
|
||||
aArgs.asyncOpenTime(), aArgs.timing().refOr(nullptr),
|
||||
std::move(clientInfo), objectArgs.embedderInnerWindowId(),
|
||||
objectArgs.loadFlags(), objectArgs.contentPolicyType(),
|
||||
aArgs.hasValidTransientUserAction(), objectArgs.isUrgentStart(),
|
||||
IProtocol::OtherPid(), &rv);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_ASSERT(!promise);
|
||||
return SendFailedAsyncOpen(rv);
|
||||
|
|
|
@ -42,10 +42,13 @@
|
|||
#include "nsIViewSourceChannel.h"
|
||||
#include "nsImportModule.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsRedirectHistoryEntry.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "nsURILoader.h"
|
||||
#include "nsWebNavigationInfo.h"
|
||||
#include "mozilla/dom/BrowserParent.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/nsHTTPSOnlyUtils.h"
|
||||
#include "mozilla/dom/RemoteWebProgress.h"
|
||||
|
@ -76,6 +79,94 @@ static void SetNeedToAddURIVisit(nsIChannel* aChannel,
|
|||
aNeedToAddURIVisit);
|
||||
}
|
||||
|
||||
static auto SecurityFlagsForLoadInfo(nsDocShellLoadState* aLoadState)
|
||||
-> nsSecurityFlags {
|
||||
// TODO: Block copied from nsDocShell::DoURILoad, refactor out somewhere
|
||||
nsSecurityFlags securityFlags =
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
|
||||
|
||||
if (aLoadState->LoadType() == LOAD_ERROR_PAGE) {
|
||||
securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE;
|
||||
}
|
||||
|
||||
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 =
|
||||
StaticPrefs::security_data_uri_unique_opaque_origin() &&
|
||||
SchemeIsData(aLoadState->URI());
|
||||
if (inheritAttrs && !isURIUniqueOrigin) {
|
||||
securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
|
||||
}
|
||||
}
|
||||
|
||||
return securityFlags;
|
||||
}
|
||||
|
||||
// Construct a LoadInfo object to use when creating the internal channel for a
|
||||
// Document/SubDocument load.
|
||||
static auto CreateDocumentLoadInfo(CanonicalBrowsingContext* aBrowsingContext,
|
||||
nsDocShellLoadState* aLoadState,
|
||||
uint64_t aOuterWindowId)
|
||||
-> already_AddRefed<LoadInfo> {
|
||||
uint32_t sandboxFlags = aBrowsingContext->GetSandboxFlags();
|
||||
RefPtr<LoadInfo> loadInfo;
|
||||
|
||||
auto securityFlags = SecurityFlagsForLoadInfo(aLoadState);
|
||||
|
||||
if (aBrowsingContext->GetParent()) {
|
||||
loadInfo = LoadInfo::CreateForFrame(
|
||||
aBrowsingContext, aLoadState->TriggeringPrincipal(), aOuterWindowId,
|
||||
securityFlags, sandboxFlags);
|
||||
} else {
|
||||
OriginAttributes attrs;
|
||||
aBrowsingContext->GetOriginAttributes(attrs);
|
||||
loadInfo = LoadInfo::CreateForDocument(
|
||||
aBrowsingContext, aLoadState->TriggeringPrincipal(), attrs,
|
||||
aOuterWindowId, securityFlags, sandboxFlags);
|
||||
}
|
||||
|
||||
loadInfo->SetHasValidUserGestureActivation(
|
||||
aLoadState->HasValidUserGestureActivation());
|
||||
|
||||
return loadInfo.forget();
|
||||
}
|
||||
|
||||
// Construct a LoadInfo object to use when creating the internal channel for an
|
||||
// Object/Embed load.
|
||||
static auto CreateObjectLoadInfo(nsDocShellLoadState* aLoadState,
|
||||
uint64_t aInnerWindowId,
|
||||
nsContentPolicyType aContentPolicyType,
|
||||
uint32_t aSandboxFlags)
|
||||
-> already_AddRefed<LoadInfo> {
|
||||
RefPtr<WindowGlobalParent> wgp =
|
||||
WindowGlobalParent::GetByInnerWindowId(aInnerWindowId);
|
||||
MOZ_RELEASE_ASSERT(wgp);
|
||||
|
||||
auto securityFlags = SecurityFlagsForLoadInfo(aLoadState);
|
||||
|
||||
RefPtr<LoadInfo> loadInfo = LoadInfo::CreateForNonDocument(
|
||||
wgp, wgp->DocumentPrincipal(), 0, aContentPolicyType, securityFlags,
|
||||
aSandboxFlags);
|
||||
|
||||
loadInfo->SetHasValidUserGestureActivation(
|
||||
aLoadState->HasValidUserGestureActivation());
|
||||
|
||||
return loadInfo.forget();
|
||||
}
|
||||
|
||||
static auto WebProgressForBrowsingContext(
|
||||
CanonicalBrowsingContext* aBrowsingContext)
|
||||
-> already_AddRefed<BrowsingContextWebProgress> {
|
||||
return RefPtr<BrowsingContextWebProgress>(aBrowsingContext->GetWebProgress())
|
||||
.forget();
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension to nsDocumentOpenInfo that we run in the parent process, so
|
||||
* that we can make the decision to retarget to content handlers or the external
|
||||
|
@ -94,10 +185,12 @@ class ParentProcessDocumentOpenInfo final : public nsDocumentOpenInfo,
|
|||
public:
|
||||
ParentProcessDocumentOpenInfo(ParentChannelListener* aListener,
|
||||
uint32_t aFlags,
|
||||
mozilla::dom::BrowsingContext* aBrowsingContext)
|
||||
mozilla::dom::BrowsingContext* aBrowsingContext,
|
||||
nsContentPolicyType aExternalContentPolicyType)
|
||||
: nsDocumentOpenInfo(aFlags, false),
|
||||
mBrowsingContext(aBrowsingContext),
|
||||
mListener(aListener) {
|
||||
mListener(aListener),
|
||||
mExternalContentPolicyType(aExternalContentPolicyType) {
|
||||
LOG(("ParentProcessDocumentOpenInfo ctor [this=%p]", this));
|
||||
}
|
||||
|
||||
|
@ -169,12 +262,13 @@ class ParentProcessDocumentOpenInfo final : public nsDocumentOpenInfo,
|
|||
|
||||
nsDocumentOpenInfo* Clone() override {
|
||||
mCloned = true;
|
||||
return new ParentProcessDocumentOpenInfo(mListener, mFlags,
|
||||
mBrowsingContext);
|
||||
return new ParentProcessDocumentOpenInfo(
|
||||
mListener, mFlags, mBrowsingContext, mExternalContentPolicyType);
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStartRequest(nsIRequest* request) override {
|
||||
LOG(("ParentProcessDocumentOpenInfo OnStartRequest [this=%p]", this));
|
||||
nsresult OnDocumentStartRequest(nsIRequest* request) {
|
||||
LOG(("ParentProcessDocumentOpenInfo OnDocumentStartRequest [this=%p]",
|
||||
this));
|
||||
|
||||
nsresult rv = nsDocumentOpenInfo::OnStartRequest(request);
|
||||
|
||||
|
@ -213,6 +307,32 @@ class ParentProcessDocumentOpenInfo final : public nsDocumentOpenInfo,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult OnObjectStartRequest(nsIRequest* request) {
|
||||
LOG(("ParentProcessDocumentOpenInfo OnObjectStartRequest [this=%p]", this));
|
||||
// Just redirect to the nsObjectLoadingContent in the content process.
|
||||
m_targetStreamListener = mListener;
|
||||
return m_targetStreamListener->OnStartRequest(request);
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStartRequest(nsIRequest* request) override {
|
||||
LOG(("ParentProcessDocumentOpenInfo OnStartRequest [this=%p]", this));
|
||||
|
||||
switch (mExternalContentPolicyType) {
|
||||
case nsIContentPolicy::TYPE_DOCUMENT:
|
||||
case nsIContentPolicy::TYPE_SUBDOCUMENT:
|
||||
return OnDocumentStartRequest(request);
|
||||
break;
|
||||
|
||||
case nsIContentPolicy::TYPE_OBJECT:
|
||||
return OnObjectStartRequest(request);
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unexpect external content policy type.");
|
||||
return NS_BINDING_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHOD OnAfterLastPart(nsresult aStatus) override {
|
||||
mListener->OnAfterLastPart(aStatus);
|
||||
return NS_OK;
|
||||
|
@ -236,6 +356,7 @@ class ParentProcessDocumentOpenInfo final : public nsDocumentOpenInfo,
|
|||
|
||||
RefPtr<mozilla::dom::BrowsingContext> mBrowsingContext;
|
||||
RefPtr<ParentChannelListener> mListener;
|
||||
nsContentPolicyType mExternalContentPolicyType;
|
||||
|
||||
/**
|
||||
* Set to true if we got cloned to create a chained listener.
|
||||
|
@ -267,10 +388,11 @@ NS_INTERFACE_MAP_BEGIN(DocumentLoadListener)
|
|||
NS_INTERFACE_MAP_END
|
||||
|
||||
DocumentLoadListener::DocumentLoadListener(
|
||||
CanonicalBrowsingContext* aBrowsingContext) {
|
||||
CanonicalBrowsingContext* aLoadingBrowsingContext) {
|
||||
LOG(("DocumentLoadListener ctor [this=%p]", this));
|
||||
mParentChannelListener = new ParentChannelListener(
|
||||
this, aBrowsingContext, aBrowsingContext->UsePrivateBrowsing());
|
||||
mParentChannelListener =
|
||||
new ParentChannelListener(this, aLoadingBrowsingContext,
|
||||
aLoadingBrowsingContext->UsePrivateBrowsing());
|
||||
}
|
||||
|
||||
DocumentLoadListener::~DocumentLoadListener() {
|
||||
|
@ -304,7 +426,7 @@ void DocumentLoadListener::AddURIVisit(nsIChannel* aChannel,
|
|||
}
|
||||
|
||||
RefPtr<CanonicalBrowsingContext> browsingContext =
|
||||
mParentChannelListener->GetBrowsingContext();
|
||||
GetDocumentBrowsingContext();
|
||||
nsCOMPtr<nsIWidget> widget =
|
||||
browsingContext->GetParentProcessWidgetContaining();
|
||||
|
||||
|
@ -313,97 +435,49 @@ void DocumentLoadListener::AddURIVisit(nsIChannel* aChannel,
|
|||
mLoadStateLoadType);
|
||||
}
|
||||
|
||||
already_AddRefed<LoadInfo> DocumentLoadListener::CreateLoadInfo(
|
||||
CanonicalBrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState,
|
||||
uint64_t aOuterWindowId) {
|
||||
// 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 =
|
||||
StaticPrefs::security_data_uri_unique_opaque_origin() &&
|
||||
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;
|
||||
if (aBrowsingContext->GetParent()) {
|
||||
// Build LoadInfo for TYPE_SUBDOCUMENT
|
||||
loadInfo = LoadInfo::CreateForFrame(
|
||||
aBrowsingContext, aLoadState->TriggeringPrincipal(), aOuterWindowId,
|
||||
securityFlags, sandboxFlags);
|
||||
} else {
|
||||
// Build LoadInfo for TYPE_DOCUMENT
|
||||
OriginAttributes attrs;
|
||||
aBrowsingContext->GetOriginAttributes(attrs);
|
||||
loadInfo = LoadInfo::CreateForDocument(
|
||||
aBrowsingContext, aLoadState->TriggeringPrincipal(), attrs,
|
||||
aOuterWindowId, securityFlags, sandboxFlags);
|
||||
}
|
||||
|
||||
loadInfo->SetHasValidUserGestureActivation(
|
||||
aLoadState->HasValidUserGestureActivation());
|
||||
|
||||
return loadInfo.forget();
|
||||
CanonicalBrowsingContext* DocumentLoadListener::GetLoadingBrowsingContext()
|
||||
const {
|
||||
return mParentChannelListener ? mParentChannelListener->GetBrowsingContext()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
CanonicalBrowsingContext* DocumentLoadListener::GetBrowsingContext() const {
|
||||
if (!mParentChannelListener) {
|
||||
CanonicalBrowsingContext* DocumentLoadListener::GetDocumentBrowsingContext()
|
||||
const {
|
||||
if (mExternalContentPolicyType == nsIContentPolicy::TYPE_OBJECT) {
|
||||
return nullptr;
|
||||
}
|
||||
return mParentChannelListener->GetBrowsingContext();
|
||||
|
||||
return GetLoadingBrowsingContext();
|
||||
}
|
||||
|
||||
auto DocumentLoadListener::Open(
|
||||
nsDocShellLoadState* aLoadState, uint32_t aCacheKey,
|
||||
const Maybe<uint64_t>& aChannelId, const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming, Maybe<ClientInfo>&& aInfo,
|
||||
uint64_t aOuterWindowId, bool aHasGesture, Maybe<bool> aUriModified,
|
||||
Maybe<bool> aIsXFOError, base::ProcessId aPid, nsresult* aRv)
|
||||
-> RefPtr<OpenPromise> {
|
||||
LOG(("DocumentLoadListener Open [this=%p, uri=%s]", this,
|
||||
aLoadState->URI()->GetSpecOrDefault().get()));
|
||||
RefPtr<CanonicalBrowsingContext> browsingContext =
|
||||
mParentChannelListener->GetBrowsingContext();
|
||||
CanonicalBrowsingContext* DocumentLoadListener::GetTopBrowsingContext() const {
|
||||
auto* loadingContext = GetLoadingBrowsingContext();
|
||||
return loadingContext ? loadingContext->Top() : nullptr;
|
||||
}
|
||||
|
||||
auto DocumentLoadListener::Open(nsDocShellLoadState* aLoadState,
|
||||
LoadInfo* aLoadInfo, nsLoadFlags aLoadFlags,
|
||||
uint32_t aCacheKey,
|
||||
const Maybe<uint64_t>& aChannelId,
|
||||
const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming,
|
||||
Maybe<ClientInfo>&& aInfo, bool aHasGesture,
|
||||
bool aUrgentStart, base::ProcessId aPid,
|
||||
nsresult* aRv) -> RefPtr<OpenPromise> {
|
||||
auto* loadingContext = GetLoadingBrowsingContext();
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT_IF(loadingContext->GetParent(),
|
||||
loadingContext->GetParentWindowContext());
|
||||
|
||||
OriginAttributes attrs;
|
||||
browsingContext->GetOriginAttributes(attrs);
|
||||
loadingContext->GetOriginAttributes(attrs);
|
||||
|
||||
mLoadIdentifier = aLoadState->GetLoadIdentifier();
|
||||
MOZ_DIAGNOSTIC_ASSERT_IF(browsingContext->GetParent(),
|
||||
browsingContext->GetParentWindowContext());
|
||||
|
||||
// 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.
|
||||
RefPtr<LoadInfo> loadInfo =
|
||||
CreateLoadInfo(browsingContext, aLoadState, aOuterWindowId);
|
||||
|
||||
nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags(
|
||||
browsingContext, std::move(aUriModified), std::move(aIsXFOError));
|
||||
mExternalContentPolicyType = aLoadInfo->GetExternalContentPolicyType();
|
||||
|
||||
if (!nsDocShell::CreateAndConfigureRealChannelForLoadState(
|
||||
browsingContext, aLoadState, loadInfo, mParentChannelListener,
|
||||
nullptr, attrs, loadFlags, aCacheKey, *aRv,
|
||||
loadingContext, aLoadState, aLoadInfo, mParentChannelListener,
|
||||
nullptr, attrs, aLoadFlags, aCacheKey, *aRv,
|
||||
getter_AddRefs(mChannel))) {
|
||||
LOG(("DocumentLoadListener::Open failed to create channel [this=%p]",
|
||||
this));
|
||||
|
@ -411,19 +485,20 @@ auto DocumentLoadListener::Open(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uriBeingLoaded =
|
||||
AntiTrackingUtils::MaybeGetDocumentURIBeingLoaded(mChannel);
|
||||
nsCOMPtr<nsIURI> uriBeingLoaded;
|
||||
Unused << NS_WARN_IF(
|
||||
NS_FAILED(mChannel->GetURI(getter_AddRefs(uriBeingLoaded))));
|
||||
|
||||
RefPtr<HttpBaseChannel> httpBaseChannel = do_QueryObject(mChannel, aRv);
|
||||
if (httpBaseChannel) {
|
||||
if (uriBeingLoaded && httpBaseChannel) {
|
||||
nsCOMPtr<nsIURI> topWindowURI;
|
||||
if (browsingContext->IsTop()) {
|
||||
if (loadingContext->IsTop()) {
|
||||
// If this is for the top level loading, the top window URI should be the
|
||||
// URI which we are loading.
|
||||
topWindowURI = uriBeingLoaded;
|
||||
} else if (RefPtr<WindowGlobalParent> topWindow = AntiTrackingUtils::
|
||||
GetTopWindowExcludingExtensionAccessibleContentFrames(
|
||||
browsingContext, uriBeingLoaded)) {
|
||||
loadingContext, uriBeingLoaded)) {
|
||||
nsCOMPtr<nsIPrincipal> topWindowPrincipal =
|
||||
topWindow->DocumentPrincipal();
|
||||
if (topWindowPrincipal && !topWindowPrincipal->GetIsNullPrincipal()) {
|
||||
|
@ -451,7 +526,12 @@ auto DocumentLoadListener::Open(
|
|||
|
||||
if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel)) {
|
||||
Unused << httpChannel->SetRequestContextID(
|
||||
browsingContext->GetRequestContextId());
|
||||
loadingContext->GetRequestContextId());
|
||||
|
||||
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(httpChannel));
|
||||
if (cos && aUrgentStart) {
|
||||
cos->AddClassFlags(nsIClassOfService::UrgentStart);
|
||||
}
|
||||
}
|
||||
|
||||
// nsViewSourceChannel normally replaces the nsIRequest passed to
|
||||
|
@ -467,7 +547,8 @@ auto DocumentLoadListener::Open(
|
|||
// across any serviceworker related data between channels as needed.
|
||||
AddClientChannelHelperInParent(mChannel, std::move(aInfo));
|
||||
|
||||
if (!browsingContext->StartDocumentLoad(this)) {
|
||||
auto* documentContext = GetDocumentBrowsingContext();
|
||||
if (documentContext && !documentContext->StartDocumentLoad(this)) {
|
||||
LOG(("DocumentLoadListener::Open failed StartDocumentLoad [this=%p]",
|
||||
this));
|
||||
*aRv = NS_BINDING_ABORTED;
|
||||
|
@ -480,29 +561,30 @@ auto DocumentLoadListener::Open(
|
|||
// NOTE: The only case not handled here to mirror Content process is
|
||||
// redirecting to re-use the channel.
|
||||
MOZ_ASSERT(!aLoadState->GetPendingRedirectedChannel());
|
||||
uint32_t openFlags = nsDocShell::ComputeURILoaderFlags(
|
||||
browsingContext, aLoadState->LoadType());
|
||||
uint32_t openFlags =
|
||||
nsDocShell::ComputeURILoaderFlags(loadingContext, aLoadState->LoadType());
|
||||
|
||||
RefPtr<ParentProcessDocumentOpenInfo> openInfo =
|
||||
new ParentProcessDocumentOpenInfo(mParentChannelListener, openFlags,
|
||||
browsingContext);
|
||||
loadingContext,
|
||||
mExternalContentPolicyType);
|
||||
openInfo->Prepare();
|
||||
|
||||
#ifdef ANDROID
|
||||
RefPtr<MozPromise<bool, bool, false>> promise;
|
||||
if (aLoadState->LoadType() != LOAD_ERROR_PAGE &&
|
||||
if (documentContext && aLoadState->LoadType() != LOAD_ERROR_PAGE &&
|
||||
!(aLoadState->HasLoadFlags(
|
||||
nsDocShell::INTERNAL_LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE)) &&
|
||||
!(aLoadState->LoadType() & LOAD_HISTORY)) {
|
||||
nsCOMPtr<nsIWidget> widget =
|
||||
browsingContext->GetParentProcessWidgetContaining();
|
||||
documentContext->GetParentProcessWidgetContaining();
|
||||
RefPtr<nsWindow> window = nsWindow::From(widget);
|
||||
|
||||
if (window) {
|
||||
promise = window->OnLoadRequest(
|
||||
aLoadState->URI(), nsIBrowserDOMWindow::OPEN_CURRENTWINDOW,
|
||||
aLoadState->LoadFlags(), aLoadState->TriggeringPrincipal(),
|
||||
aHasGesture, browsingContext->IsTopContent());
|
||||
aHasGesture, documentContext->IsTopContent());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -533,7 +615,9 @@ auto DocumentLoadListener::Open(
|
|||
LOG(("DocumentLoadListener::Open failed AsyncOpen [this=%p rv=%" PRIx32
|
||||
"]",
|
||||
this, static_cast<uint32_t>(*aRv)));
|
||||
browsingContext->EndDocumentLoad(false);
|
||||
if (documentContext) {
|
||||
documentContext->EndDocumentLoad(false);
|
||||
}
|
||||
mParentChannelListener = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -548,9 +632,9 @@ auto DocumentLoadListener::Open(
|
|||
mBaseURI = aLoadState->BaseURI();
|
||||
mOriginalUriString = aLoadState->GetOriginalURIString();
|
||||
if (StaticPrefs::fission_sessionHistoryInParent() &&
|
||||
browsingContext->GetSessionHistory()) {
|
||||
documentContext->GetSessionHistory()) {
|
||||
mSessionHistoryInfo =
|
||||
browsingContext->CreateSessionHistoryEntryForLoad(aLoadState, mChannel);
|
||||
documentContext->CreateSessionHistoryEntryForLoad(aLoadState, mChannel);
|
||||
}
|
||||
|
||||
*aRv = NS_OK;
|
||||
|
@ -561,14 +645,72 @@ auto DocumentLoadListener::Open(
|
|||
return mOpenPromise;
|
||||
}
|
||||
|
||||
auto DocumentLoadListener::OpenDocument(
|
||||
nsDocShellLoadState* aLoadState, uint32_t aCacheKey,
|
||||
const Maybe<uint64_t>& aChannelId, const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming, Maybe<dom::ClientInfo>&& aInfo,
|
||||
uint64_t aOuterWindowId, bool aHasGesture, Maybe<bool> aUriModified,
|
||||
Maybe<bool> aIsXFOError, base::ProcessId aPid, nsresult* aRv)
|
||||
-> RefPtr<OpenPromise> {
|
||||
LOG(("DocumentLoadListener [%p] OpenDocument [uri=%s]", this,
|
||||
aLoadState->URI()->GetSpecOrDefault().get()));
|
||||
|
||||
RefPtr<CanonicalBrowsingContext> browsingContext =
|
||||
GetDocumentBrowsingContext();
|
||||
|
||||
// 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.
|
||||
RefPtr<LoadInfo> loadInfo =
|
||||
CreateDocumentLoadInfo(browsingContext, aLoadState, aOuterWindowId);
|
||||
|
||||
MOZ_ASSERT_IF(!browsingContext->GetParent(),
|
||||
loadInfo->GetExternalContentPolicyType() ==
|
||||
nsIContentPolicy::TYPE_DOCUMENT);
|
||||
MOZ_ASSERT_IF(browsingContext->GetParent(),
|
||||
loadInfo->GetExternalContentPolicyType() ==
|
||||
nsIContentPolicy::TYPE_SUBDOCUMENT);
|
||||
|
||||
nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags(
|
||||
browsingContext, std::move(aUriModified), std::move(aIsXFOError));
|
||||
|
||||
return Open(aLoadState, loadInfo, loadFlags, aCacheKey, aChannelId,
|
||||
aAsyncOpenTime, aTiming, std::move(aInfo), aHasGesture, false,
|
||||
aPid, aRv);
|
||||
}
|
||||
|
||||
auto DocumentLoadListener::OpenObject(
|
||||
nsDocShellLoadState* aLoadState, uint32_t aCacheKey,
|
||||
const Maybe<uint64_t>& aChannelId, const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming, Maybe<dom::ClientInfo>&& aInfo,
|
||||
uint64_t aInnerWindowId, nsLoadFlags aLoadFlags,
|
||||
nsContentPolicyType aContentPolicyType, bool aHasGesture, bool aUrgentStart,
|
||||
base::ProcessId aPid, nsresult* aRv) -> RefPtr<OpenPromise> {
|
||||
LOG(("DocumentLoadListener [%p] OpenObject [uri=%s]", this,
|
||||
aLoadState->URI()->GetSpecOrDefault().get()));
|
||||
|
||||
auto sandboxFlags = GetLoadingBrowsingContext()->GetSandboxFlags();
|
||||
|
||||
RefPtr<LoadInfo> loadInfo = CreateObjectLoadInfo(
|
||||
aLoadState, aInnerWindowId, aContentPolicyType, sandboxFlags);
|
||||
|
||||
MOZ_ASSERT(loadInfo->GetExternalContentPolicyType() ==
|
||||
nsIContentPolicy::TYPE_OBJECT);
|
||||
|
||||
return Open(aLoadState, loadInfo, aLoadFlags, aCacheKey, aChannelId,
|
||||
aAsyncOpenTime, aTiming, std::move(aInfo), aHasGesture,
|
||||
aUrgentStart, aPid, aRv);
|
||||
}
|
||||
|
||||
auto DocumentLoadListener::OpenInParent(nsDocShellLoadState* aLoadState,
|
||||
uint64_t aOuterWindowId,
|
||||
bool aSupportsRedirectToRealChannel)
|
||||
-> RefPtr<OpenPromise> {
|
||||
// We currently only support passing nullptr for aLoadInfo for
|
||||
// top level browsing contexts.
|
||||
if (!GetBrowsingContext()->IsTopContent() ||
|
||||
!GetBrowsingContext()->GetContentParent()) {
|
||||
auto* browsingContext = GetDocumentBrowsingContext();
|
||||
if (!browsingContext->IsTopContent() ||
|
||||
!browsingContext->GetContentParent()) {
|
||||
LOG(("DocumentLoadListener::OpenInParent failed because of subdoc"));
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -607,7 +749,7 @@ auto DocumentLoadListener::OpenInParent(nsDocShellLoadState* aLoadState,
|
|||
|
||||
RefPtr<nsDOMNavigationTiming> timing = new nsDOMNavigationTiming(nullptr);
|
||||
timing->NotifyNavigationStart(
|
||||
GetBrowsingContext()->GetIsActive()
|
||||
browsingContext->GetIsActive()
|
||||
? nsDOMNavigationTiming::DocShellState::eActive
|
||||
: nsDOMNavigationTiming::DocShellState::eInactive);
|
||||
|
||||
|
@ -625,27 +767,44 @@ auto DocumentLoadListener::OpenInParent(nsDocShellLoadState* aLoadState,
|
|||
|
||||
mSupportsRedirectToRealChannel = aSupportsRedirectToRealChannel;
|
||||
|
||||
// This is a top-level load, so rebuild the LoadInfo from scratch,
|
||||
// since in the parent the
|
||||
// content process won't have provided us with an existing one.
|
||||
RefPtr<LoadInfo> loadInfo =
|
||||
CreateDocumentLoadInfo(browsingContext, aLoadState, aOuterWindowId);
|
||||
|
||||
MOZ_ASSERT_IF(!browsingContext->GetParent(),
|
||||
loadInfo->GetExternalContentPolicyType() ==
|
||||
nsIContentPolicy::TYPE_DOCUMENT);
|
||||
MOZ_ASSERT_IF(browsingContext->GetParent(),
|
||||
loadInfo->GetExternalContentPolicyType() ==
|
||||
nsIContentPolicy::TYPE_SUBDOCUMENT);
|
||||
|
||||
nsLoadFlags loadFlags = loadState->CalculateChannelLoadFlags(
|
||||
browsingContext, Nothing(), Nothing());
|
||||
|
||||
nsresult rv;
|
||||
return Open(loadState, cacheKey, channelId, TimeStamp::Now(), timing,
|
||||
std::move(initialClientInfo), aOuterWindowId, false, Nothing(),
|
||||
Nothing(), GetBrowsingContext()->GetContentParent()->OtherPid(),
|
||||
&rv);
|
||||
return Open(loadState, loadInfo, loadFlags, cacheKey, channelId,
|
||||
TimeStamp::Now(), timing, std::move(initialClientInfo), false,
|
||||
false, browsingContext->GetContentParent()->OtherPid(), &rv);
|
||||
}
|
||||
|
||||
static void FireStateChange(DocumentLoadListener* aLoad, uint32_t aStateFlags,
|
||||
nsresult aStatus) {
|
||||
nsCOMPtr<nsIChannel> request = aLoad->GetChannel();
|
||||
void DocumentLoadListener::FireStateChange(uint32_t aStateFlags,
|
||||
nsresult aStatus) {
|
||||
nsCOMPtr<nsIChannel> request = GetChannel();
|
||||
nsCOMPtr<nsIWebProgress> webProgress =
|
||||
new RemoteWebProgress(aLoad->GetLoadType(), true, true);
|
||||
new RemoteWebProgress(GetLoadType(), true, true);
|
||||
|
||||
RefPtr<CanonicalBrowsingContext> ctx = aLoad->GetBrowsingContext();
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableFunction("DocumentLoadListener::FireStateChange", [=]() {
|
||||
if (ctx && ctx->GetWebProgress()) {
|
||||
ctx->GetWebProgress()->OnStateChange(webProgress, request,
|
||||
aStateFlags, aStatus);
|
||||
}
|
||||
}));
|
||||
RefPtr<BrowsingContextWebProgress> loadingWebProgress =
|
||||
WebProgressForBrowsingContext(GetLoadingBrowsingContext());
|
||||
|
||||
if (loadingWebProgress) {
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableFunction("DocumentLoadListener::FireStateChange", [=]() {
|
||||
loadingWebProgress->OnStateChange(webProgress, request, aStateFlags,
|
||||
aStatus);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
static void SetNavigating(CanonicalBrowsingContext* aBrowsingContext,
|
||||
|
@ -691,21 +850,19 @@ static void SetNavigating(CanonicalBrowsingContext* aBrowsingContext,
|
|||
// finished (and failed), and we should fire a state change to notify
|
||||
// observers. Normally the docshell would fire this, and it would get
|
||||
// filtered out by BrowserParent if needed.
|
||||
FireStateChange(load,
|
||||
nsIWebProgressListener::STATE_STOP |
|
||||
nsIWebProgressListener::STATE_IS_WINDOW |
|
||||
nsIWebProgressListener::STATE_IS_NETWORK,
|
||||
rejectValue.mStatus);
|
||||
load->FireStateChange(nsIWebProgressListener::STATE_STOP |
|
||||
nsIWebProgressListener::STATE_IS_WINDOW |
|
||||
nsIWebProgressListener::STATE_IS_NETWORK,
|
||||
rejectValue.mStatus);
|
||||
}
|
||||
});
|
||||
|
||||
FireStateChange(load,
|
||||
nsIWebProgressListener::STATE_START |
|
||||
nsIWebProgressListener::STATE_IS_DOCUMENT |
|
||||
nsIWebProgressListener::STATE_IS_REQUEST |
|
||||
nsIWebProgressListener::STATE_IS_WINDOW |
|
||||
nsIWebProgressListener::STATE_IS_NETWORK,
|
||||
NS_OK);
|
||||
load->FireStateChange(nsIWebProgressListener::STATE_START |
|
||||
nsIWebProgressListener::STATE_IS_DOCUMENT |
|
||||
nsIWebProgressListener::STATE_IS_REQUEST |
|
||||
nsIWebProgressListener::STATE_IS_WINDOW |
|
||||
nsIWebProgressListener::STATE_IS_NETWORK,
|
||||
NS_OK);
|
||||
SetNavigating(aBrowsingContext, false);
|
||||
return true;
|
||||
}
|
||||
|
@ -793,7 +950,7 @@ void DocumentLoadListener::Disconnect() {
|
|||
httpChannelImpl->SetWarningReporter(nullptr);
|
||||
}
|
||||
|
||||
if (auto* ctx = GetBrowsingContext()) {
|
||||
if (auto* ctx = GetDocumentBrowsingContext()) {
|
||||
ctx->EndDocumentLoad(mDoingProcessSwitch);
|
||||
}
|
||||
}
|
||||
|
@ -887,7 +1044,7 @@ void DocumentLoadListener::FinishReplacementChannelSetup(nsresult aResult) {
|
|||
this, int(aResult)));
|
||||
|
||||
auto endDocumentLoad = MakeScopeExit([&]() {
|
||||
if (auto* ctx = GetBrowsingContext()) {
|
||||
if (auto* ctx = GetDocumentBrowsingContext()) {
|
||||
ctx->EndDocumentLoad(false);
|
||||
}
|
||||
});
|
||||
|
@ -1068,7 +1225,7 @@ bool DocumentLoadListener::ResumeSuspendedChannel(
|
|||
|
||||
mChannel->Resume();
|
||||
|
||||
if (auto* ctx = GetBrowsingContext()) {
|
||||
if (auto* ctx = GetDocumentBrowsingContext()) {
|
||||
ctx->EndDocumentLoad(mDoingProcessSwitch);
|
||||
}
|
||||
|
||||
|
@ -1295,6 +1452,12 @@ bool DocumentLoadListener::MaybeTriggerProcessSwitch(
|
|||
|
||||
LOG(("DocumentLoadListener MaybeTriggerProcessSwitch [this=%p]", this));
|
||||
|
||||
// Don't switch process for <object>/<embed> loads.
|
||||
if (mExternalContentPolicyType == nsIContentPolicy::TYPE_OBJECT) {
|
||||
LOG(("Process Switch Abort: non-document load"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the BrowsingContext which will be switching processes.
|
||||
RefPtr<CanonicalBrowsingContext> browsingContext =
|
||||
mParentChannelListener->GetBrowsingContext();
|
||||
|
@ -1550,14 +1713,24 @@ DocumentLoadListener::RedirectToRealChannel(
|
|||
"aRedirectFlags=%" PRIx32 ", aLoadFlags=%" PRIx32,
|
||||
this, aRedirectFlags, aLoadFlags));
|
||||
|
||||
// TODO(djg): Add the last URI visit to history if success. Is there a better
|
||||
// place to handle this? Need access to the updated aLoadFlags.
|
||||
nsresult status = NS_OK;
|
||||
mChannel->GetStatus(&status);
|
||||
bool updateGHistory =
|
||||
nsDocShell::ShouldUpdateGlobalHistory(mLoadStateLoadType);
|
||||
if (NS_SUCCEEDED(status) && updateGHistory && !net::ChannelIsPost(mChannel)) {
|
||||
AddURIVisit(mChannel, aLoadFlags);
|
||||
switch (mExternalContentPolicyType) {
|
||||
case nsIContentPolicy::TYPE_DOCUMENT:
|
||||
case nsIContentPolicy::TYPE_SUBDOCUMENT: {
|
||||
// TODO(djg): Add the last URI visit to history if success. Is there a
|
||||
// better place to handle this? Need access to the updated aLoadFlags.
|
||||
nsresult status = NS_OK;
|
||||
mChannel->GetStatus(&status);
|
||||
bool updateGHistory =
|
||||
nsDocShell::ShouldUpdateGlobalHistory(mLoadStateLoadType);
|
||||
if (NS_SUCCEEDED(status) && updateGHistory &&
|
||||
!net::ChannelIsPost(mChannel)) {
|
||||
AddURIVisit(mChannel, aLoadFlags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Register the new channel and obtain id for it
|
||||
|
@ -1703,7 +1876,9 @@ void DocumentLoadListener::TriggerRedirectToRealChannel(
|
|||
MOZ_ALWAYS_SUCCEEDS(mChannel->GetLoadFlags(&newLoadFlags));
|
||||
// We're pulling our flags from the inner channel, which may not have this
|
||||
// flag set on it. This is the case when loading a 'view-source' channel.
|
||||
newLoadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
|
||||
if (mExternalContentPolicyType != nsIContentPolicy::TYPE_OBJECT) {
|
||||
newLoadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
|
||||
}
|
||||
if (!aDestinationProcess) {
|
||||
newLoadFlags |= nsIChannel::LOAD_REPLACE;
|
||||
}
|
||||
|
@ -1742,7 +1917,8 @@ void DocumentLoadListener::TriggerRedirectToRealChannel(
|
|||
}
|
||||
|
||||
void DocumentLoadListener::MaybeReportBlockedByURLClassifier(nsresult aStatus) {
|
||||
if (!GetBrowsingContext() || GetBrowsingContext()->IsTop() ||
|
||||
auto* browsingContext = GetDocumentBrowsingContext();
|
||||
if (!browsingContext || browsingContext->IsTop() ||
|
||||
!StaticPrefs::privacy_trackingprotection_testing_report_blocked_node()) {
|
||||
return;
|
||||
}
|
||||
|
@ -1751,10 +1927,10 @@ void DocumentLoadListener::MaybeReportBlockedByURLClassifier(nsresult aStatus) {
|
|||
return;
|
||||
}
|
||||
|
||||
RefPtr<WindowGlobalParent> parent =
|
||||
GetBrowsingContext()->GetParentWindowContext();
|
||||
RefPtr<WindowGlobalParent> parent = browsingContext->GetParentWindowContext();
|
||||
if (parent) {
|
||||
Unused << parent->SendAddBlockedFrameNodeByClassifier(GetBrowsingContext());
|
||||
Unused << parent->SendAddBlockedFrameNodeByClassifier(
|
||||
GetLoadingBrowsingContext());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1768,15 +1944,17 @@ bool DocumentLoadListener::DocShellWillDisplayContent(nsresult aStatus) {
|
|||
// succeed with fixup, so we don't need to check for it
|
||||
// here.
|
||||
|
||||
auto* loadingContext = GetLoadingBrowsingContext();
|
||||
|
||||
bool isInitialDocument = true;
|
||||
if (WindowGlobalParent* currentWindow =
|
||||
GetBrowsingContext()->GetCurrentWindowGlobal()) {
|
||||
loadingContext->GetCurrentWindowGlobal()) {
|
||||
isInitialDocument = currentWindow->IsInitialDocument();
|
||||
}
|
||||
|
||||
nsresult rv = nsDocShell::FilterStatusForErrorPage(
|
||||
aStatus, mChannel, mLoadStateLoadType, GetBrowsingContext()->IsTop(),
|
||||
GetBrowsingContext()->GetUseErrorPages(), isInitialDocument, nullptr);
|
||||
aStatus, mChannel, mLoadStateLoadType, loadingContext->IsTop(),
|
||||
loadingContext->GetUseErrorPages(), isInitialDocument, nullptr);
|
||||
|
||||
// If filtering returned a failure code, then an error page will
|
||||
// be display for that code, so return true;
|
||||
|
@ -1784,14 +1962,17 @@ bool DocumentLoadListener::DocShellWillDisplayContent(nsresult aStatus) {
|
|||
}
|
||||
|
||||
bool DocumentLoadListener::MaybeHandleLoadErrorWithURIFixup(nsresult aStatus) {
|
||||
auto* bc = GetDocumentBrowsingContext();
|
||||
if (!bc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> newPostData;
|
||||
nsCOMPtr<nsIURI> newURI = nsDocShell::AttemptURIFixup(
|
||||
mChannel, aStatus, mOriginalUriString, mLoadStateLoadType,
|
||||
GetBrowsingContext()->IsTop(),
|
||||
mChannel, aStatus, mOriginalUriString, mLoadStateLoadType, bc->IsTop(),
|
||||
mLoadStateLoadFlags &
|
||||
nsDocShell::INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP,
|
||||
GetBrowsingContext()->UsePrivateBrowsing(), true,
|
||||
getter_AddRefs(newPostData));
|
||||
bc->UsePrivateBrowsing(), true, getter_AddRefs(newPostData));
|
||||
if (!newURI) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1812,7 +1993,7 @@ bool DocumentLoadListener::MaybeHandleLoadErrorWithURIFixup(nsresult aStatus) {
|
|||
|
||||
loadState->SetPostDataStream(newPostData);
|
||||
|
||||
GetBrowsingContext()->LoadURI(loadState, false);
|
||||
bc->LoadURI(loadState, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1834,7 +2015,8 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
|
|||
// might cancel the channel.
|
||||
nsContentSecurityUtils::PerformCSPFrameAncestorAndXFOCheck(mChannel);
|
||||
|
||||
if (!GetBrowsingContext() || GetBrowsingContext()->IsDiscarded()) {
|
||||
auto* loadingContext = GetLoadingBrowsingContext();
|
||||
if (!loadingContext || loadingContext->IsDiscarded()) {
|
||||
DisconnectListeners(NS_ERROR_UNEXPECTED, NS_ERROR_UNEXPECTED);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
@ -1893,10 +2075,10 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
|
|||
|
||||
// If we're not going to process switch, then we must have an existing
|
||||
// window global, right?
|
||||
MOZ_ASSERT(GetBrowsingContext()->GetCurrentWindowGlobal());
|
||||
MOZ_ASSERT(loadingContext->GetCurrentWindowGlobal());
|
||||
|
||||
RefPtr<BrowserParent> browserParent =
|
||||
GetBrowsingContext()->GetCurrentWindowGlobal()->GetBrowserParent();
|
||||
loadingContext->GetCurrentWindowGlobal()->GetBrowserParent();
|
||||
|
||||
// This load has already started, so we want to suspend the start progress
|
||||
// events from the docshell from reaching the parent.
|
||||
|
@ -1908,14 +2090,13 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
|
|||
|
||||
// Use the current process ID to run the 'process switch' path and connect
|
||||
// the channel into the current process.
|
||||
TriggerRedirectToRealChannel(
|
||||
Some(GetBrowsingContext()->OwnerProcessId()));
|
||||
TriggerRedirectToRealChannel(Some(loadingContext->OwnerProcessId()));
|
||||
} else {
|
||||
TriggerRedirectToRealChannel(Nothing());
|
||||
}
|
||||
|
||||
// If we're not switching, then check if we're currently remote.
|
||||
if (GetBrowsingContext() && GetBrowsingContext()->GetContentParent()) {
|
||||
if (auto* bc = GetDocumentBrowsingContext(); bc && bc->GetContentParent()) {
|
||||
willBeRemote = true;
|
||||
}
|
||||
}
|
||||
|
@ -2006,7 +2187,7 @@ DocumentLoadListener::OnAfterLastPart(nsresult aStatus) {
|
|||
NS_IMETHODIMP
|
||||
DocumentLoadListener::GetInterface(const nsIID& aIID, void** result) {
|
||||
RefPtr<CanonicalBrowsingContext> browsingContext =
|
||||
mParentChannelListener->GetBrowsingContext();
|
||||
GetDocumentBrowsingContext();
|
||||
if (aIID.Equals(NS_GET_IID(nsILoadContext)) && browsingContext) {
|
||||
browsingContext.forget(result);
|
||||
return NS_OK;
|
||||
|
@ -2080,7 +2261,8 @@ DocumentLoadListener::Delete() {
|
|||
|
||||
NS_IMETHODIMP
|
||||
DocumentLoadListener::GetRemoteType(nsACString& aRemoteType) {
|
||||
RefPtr<CanonicalBrowsingContext> browsingContext = GetBrowsingContext();
|
||||
RefPtr<CanonicalBrowsingContext> browsingContext =
|
||||
GetDocumentBrowsingContext();
|
||||
if (!browsingContext) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
@ -2160,7 +2342,7 @@ DocumentLoadListener::AsyncOnChannelRedirect(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!net::ChannelIsPost(aOldChannel)) {
|
||||
if (GetDocumentBrowsingContext() && !net::ChannelIsPost(aOldChannel)) {
|
||||
AddURIVisit(aOldChannel, 0);
|
||||
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
|
@ -2207,7 +2389,8 @@ DocumentLoadListener::AsyncOnChannelRedirect(
|
|||
AntiTrackingUtils::MaybeGetDocumentURIBeingLoaded(mChannel);
|
||||
|
||||
RefPtr<MozPromise<bool, bool, false>> promise;
|
||||
nsCOMPtr<nsIWidget> widget = bc->GetParentProcessWidgetContaining();
|
||||
nsCOMPtr<nsIWidget> widget =
|
||||
bc ? bc->GetParentProcessWidgetContaining() : nullptr;
|
||||
RefPtr<nsWindow> window = nsWindow::From(widget);
|
||||
|
||||
if (window) {
|
||||
|
@ -2283,16 +2466,17 @@ NS_IMETHODIMP DocumentLoadListener::OnStatus(nsIRequest* aRequest,
|
|||
nsCOMPtr<nsIWebProgress> webProgress =
|
||||
new RemoteWebProgress(mLoadStateLoadType, true, true);
|
||||
|
||||
RefPtr<CanonicalBrowsingContext> ctx = GetBrowsingContext();
|
||||
RefPtr<BrowsingContextWebProgress> topWebProgress =
|
||||
WebProgressForBrowsingContext(GetTopBrowsingContext());
|
||||
const nsString message(aStatusArg);
|
||||
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableFunction("DocumentLoadListener::FireStateChange", [=]() {
|
||||
if (ctx && ctx->Top()->GetWebProgress()) {
|
||||
ctx->Top()->GetWebProgress()->OnStatusChange(webProgress, channel,
|
||||
aStatus, message.get());
|
||||
}
|
||||
}));
|
||||
if (topWebProgress) {
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableFunction("DocumentLoadListener::OnStatus", [=]() {
|
||||
topWebProgress->OnStatusChange(webProgress, channel, aStatus,
|
||||
message.get());
|
||||
}));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -94,8 +94,10 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
public nsIMultiPartChannelListener,
|
||||
public nsIProgressEventSink {
|
||||
public:
|
||||
// See the comment on GetLoadingBrowsingContext for explanation of
|
||||
// aLoadingBrowsingContext.
|
||||
explicit DocumentLoadListener(
|
||||
dom::CanonicalBrowsingContext* aBrowsingContext);
|
||||
dom::CanonicalBrowsingContext* aLoadingBrowsingContext);
|
||||
|
||||
struct OpenPromiseSucceededType {
|
||||
nsTArray<ipc::Endpoint<extensions::PStreamFilterParent>>
|
||||
|
@ -117,6 +119,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
true /* isExclusive */>
|
||||
OpenPromise;
|
||||
|
||||
private:
|
||||
// Creates the channel, and then calls AsyncOpen on it.
|
||||
// The DocumentLoadListener will require additional process from the consumer
|
||||
// in order to complete the redirect to the end channel. This is done by
|
||||
|
@ -125,14 +128,30 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
// Once that promise is resolved; the consumer no longer needs to hold a
|
||||
// reference to the DocumentLoadListener nor will the consumer required to be
|
||||
// used again.
|
||||
RefPtr<OpenPromise> Open(nsDocShellLoadState* aLoadState, uint32_t aCacheKey,
|
||||
RefPtr<OpenPromise> Open(nsDocShellLoadState* aLoadState, LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags, uint32_t aCacheKey,
|
||||
const Maybe<uint64_t>& aChannelId,
|
||||
const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming,
|
||||
Maybe<dom::ClientInfo>&& aInfo,
|
||||
uint64_t aOuterWindowId, bool aHasGesture,
|
||||
Maybe<bool> aUriModified, Maybe<bool> aIsXFOError,
|
||||
base::ProcessId aPid, nsresult* aRv);
|
||||
Maybe<dom::ClientInfo>&& aInfo, bool aHasGesture,
|
||||
bool aUrgentStart, base::ProcessId aPid,
|
||||
nsresult* aRv);
|
||||
|
||||
public:
|
||||
RefPtr<OpenPromise> OpenDocument(
|
||||
nsDocShellLoadState* aLoadState, uint32_t aCacheKey,
|
||||
const Maybe<uint64_t>& aChannelId, const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming, Maybe<dom::ClientInfo>&& aInfo,
|
||||
uint64_t aOuterWindowId, bool aHasGesture, Maybe<bool> aUriModified,
|
||||
Maybe<bool> aIsXFOError, base::ProcessId aPid, nsresult* aRv);
|
||||
|
||||
RefPtr<OpenPromise> OpenObject(
|
||||
nsDocShellLoadState* aLoadState, uint32_t aCacheKey,
|
||||
const Maybe<uint64_t>& aChannelId, const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming, Maybe<dom::ClientInfo>&& aInfo,
|
||||
uint64_t aInnerWindowId, nsLoadFlags aLoadFlags,
|
||||
nsContentPolicyType aContentPolicyType, bool aHasGesture,
|
||||
bool aUrgentStart, base::ProcessId aPid, nsresult* aRv);
|
||||
|
||||
// Creates a DocumentLoadListener entirely in the parent process and opens it,
|
||||
// and never needs a DocumentChannel to connect to an existing docshell.
|
||||
|
@ -237,8 +256,6 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
dom::ContentParent* aParent) const;
|
||||
|
||||
uint64_t GetLoadIdentifier() const { return mLoadIdentifier; }
|
||||
dom::CanonicalBrowsingContext* GetBrowsingContext() const;
|
||||
|
||||
uint32_t GetLoadType() const { return mLoadStateLoadType; }
|
||||
|
||||
protected:
|
||||
|
@ -298,7 +315,18 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
// Construct a LoadInfo object to use for the internal channel.
|
||||
already_AddRefed<LoadInfo> CreateLoadInfo(
|
||||
dom::CanonicalBrowsingContext* aBrowsingContext,
|
||||
nsDocShellLoadState* aLoadState, uint64_t aOuterWindowId);
|
||||
nsDocShellLoadState* aLoadState, uint64_t aOuterWindowId,
|
||||
uint64_t aInnerWindowId, nsContentPolicyType aContentPolicyType);
|
||||
|
||||
// Return the Browsing Context that is performing the load.
|
||||
// For document loads, the BC is the one that the (sub)doc
|
||||
// will load into. For <object>/<embed>, it's the embedder document's BC.
|
||||
dom::CanonicalBrowsingContext* GetLoadingBrowsingContext() const;
|
||||
|
||||
// Return the Browsing Context that document is being loaded into. For
|
||||
// non-document loads, this will return nullptr.
|
||||
dom::CanonicalBrowsingContext* GetDocumentBrowsingContext() const;
|
||||
dom::CanonicalBrowsingContext* GetTopBrowsingContext() const;
|
||||
|
||||
void AddURIVisit(nsIChannel* aChannel, uint32_t aLoadFlags);
|
||||
bool HasCrossOriginOpenerPolicyMismatch() const;
|
||||
|
@ -314,6 +342,8 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
// Returns false if the docshell will ignore the load entirely.
|
||||
bool DocShellWillDisplayContent(nsresult aStatus);
|
||||
|
||||
void FireStateChange(uint32_t aStateFlags, nsresult aStatus);
|
||||
|
||||
// Returns true if this is a failed load, where we have successfully
|
||||
// created a fixed URI to attempt loading instead.
|
||||
// If successful, this calls DisconnectListeners to completely finish
|
||||
|
@ -441,6 +471,8 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
|
||||
mozilla::UniquePtr<mozilla::dom::SessionHistoryInfo> mSessionHistoryInfo;
|
||||
|
||||
nsContentPolicyType mExternalContentPolicyType;
|
||||
|
||||
// Flags from nsDocShellLoadState::LoadFlags/Type that we want to make
|
||||
// available to the new docshell if we switch processes.
|
||||
uint32_t mLoadStateLoadFlags = 0;
|
||||
|
|
|
@ -437,18 +437,33 @@ struct CookieStruct
|
|||
uint8_t schemeMap;
|
||||
};
|
||||
|
||||
struct DocumentCreationArgs {
|
||||
uint64_t outerWindowId;
|
||||
bool uriModified;
|
||||
bool isXFOError;
|
||||
};
|
||||
|
||||
struct ObjectCreationArgs {
|
||||
uint64_t embedderInnerWindowId;
|
||||
uint32_t loadFlags;
|
||||
uint8_t contentPolicyType;
|
||||
bool isUrgentStart;
|
||||
};
|
||||
|
||||
union DocumentChannelElementCreationArgs {
|
||||
DocumentCreationArgs;
|
||||
ObjectCreationArgs;
|
||||
};
|
||||
|
||||
struct DocumentChannelCreationArgs {
|
||||
DocShellLoadStateInit loadState;
|
||||
TimeStamp asyncOpenTime;
|
||||
uint64_t channelId;
|
||||
uint32_t cacheKey;
|
||||
bool pluginsAllowed;
|
||||
nsDOMNavigationTiming? timing;
|
||||
IPCClientInfo? initialClientInfo;
|
||||
uint64_t outerWindowId;
|
||||
bool hasValidTransientUserAction;
|
||||
bool uriModified;
|
||||
bool isXFOError;
|
||||
DocumentChannelElementCreationArgs elementCreationArgs;
|
||||
};
|
||||
|
||||
struct RedirectToRealChannelArgs {
|
||||
|
|
|
@ -129,8 +129,10 @@ ParentProcessDocumentChannel::OnRedirectVerifyCallback(nsresult aResult) {
|
|||
NS_IMETHODIMP ParentProcessDocumentChannel::AsyncOpen(
|
||||
nsIStreamListener* aListener) {
|
||||
LOG(("ParentProcessDocumentChannel AsyncOpen [this=%p]", this));
|
||||
mDocumentLoadListener = new DocumentLoadListener(
|
||||
GetDocShell()->GetBrowsingContext()->Canonical());
|
||||
auto docShell = RefPtr<nsDocShell>(GetDocShell());
|
||||
MOZ_ASSERT(docShell);
|
||||
mDocumentLoadListener = MakeRefPtr<DocumentLoadListener>(
|
||||
docShell->GetBrowsingContext()->Canonical());
|
||||
LOG(("Created PPDocumentChannel with listener=%p",
|
||||
mDocumentLoadListener.get()));
|
||||
|
||||
|
@ -144,18 +146,47 @@ NS_IMETHODIMP ParentProcessDocumentChannel::AsyncOpen(
|
|||
|
||||
gHttpHandler->OnOpeningDocumentRequest(this);
|
||||
|
||||
GetDocShell()->GetBrowsingContext()->SetCurrentLoadIdentifier(
|
||||
Some(mLoadState->GetLoadIdentifier()));
|
||||
switch (mLoadInfo->GetExternalContentPolicyType()) {
|
||||
case nsIContentPolicy::TYPE_DOCUMENT:
|
||||
case nsIContentPolicy::TYPE_SUBDOCUMENT:
|
||||
GetDocShell()->GetBrowsingContext()->SetCurrentLoadIdentifier(
|
||||
Some(mLoadState->GetLoadIdentifier()));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
Maybe<dom::ClientInfo> initialClientInfo = mInitialClientInfo;
|
||||
auto promise = mDocumentLoadListener->Open(
|
||||
mLoadState, mCacheKey, Some(mChannelId), mAsyncOpenTime, mTiming,
|
||||
std::move(initialClientInfo), GetDocShell()->GetOuterWindowID(),
|
||||
GetDocShell()
|
||||
->GetBrowsingContext()
|
||||
->HasValidTransientUserGestureActivation(),
|
||||
Some(mUriModified), Some(mIsXFOError), 0 /* ProcessId */, &rv);
|
||||
|
||||
const bool hasValidTransientUserGestureActivation =
|
||||
docShell->GetBrowsingContext()->HasValidTransientUserGestureActivation();
|
||||
|
||||
RefPtr<DocumentLoadListener::OpenPromise> promise;
|
||||
switch (mLoadInfo->GetExternalContentPolicyType()) {
|
||||
case nsIContentPolicy::TYPE_DOCUMENT:
|
||||
case nsIContentPolicy::TYPE_SUBDOCUMENT:
|
||||
promise = mDocumentLoadListener->OpenDocument(
|
||||
mLoadState, mCacheKey, Some(mChannelId), mAsyncOpenTime, mTiming,
|
||||
std::move(initialClientInfo), docShell->GetOuterWindowID(),
|
||||
hasValidTransientUserGestureActivation, Some(mUriModified),
|
||||
Some(mIsXFOError), 0 /* ProcessId */, &rv);
|
||||
break;
|
||||
|
||||
case nsIContentPolicy::TYPE_OBJECT:
|
||||
promise = mDocumentLoadListener->OpenObject(
|
||||
mLoadState, mCacheKey, Some(mChannelId), mAsyncOpenTime, mTiming,
|
||||
std::move(initialClientInfo), InnerWindowIDForExtantDoc(docShell),
|
||||
mLoadFlags, mLoadInfo->InternalContentPolicyType(),
|
||||
hasValidTransientUserGestureActivation,
|
||||
UserActivation::IsHandlingUserInput(), 0 /* ProcessId */, &rv);
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unhandled content policy type.");
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_ASSERT(!promise);
|
||||
mDocumentLoadListener = nullptr;
|
||||
|
|
Загрузка…
Ссылка в новой задаче