forked from mirrors/gecko-dev
Bug 1867628 - Fire a load event when frame-ancestors blocks an iframe (similar to X-Frame-Options). r=nika,smaug
Differential Revision: https://phabricator.services.mozilla.com/D196036
This commit is contained in:
parent
8782212612
commit
061fc361e2
14 changed files with 49 additions and 44 deletions
|
|
@ -10525,22 +10525,23 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
|
|||
uriModified = false;
|
||||
}
|
||||
|
||||
bool isXFOError = false;
|
||||
bool isEmbeddingBlockedError = false;
|
||||
if (mFailedChannel) {
|
||||
nsresult status;
|
||||
mFailedChannel->GetStatus(&status);
|
||||
isXFOError = status == NS_ERROR_XFO_VIOLATION;
|
||||
isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION ||
|
||||
status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION;
|
||||
}
|
||||
|
||||
nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags(
|
||||
mBrowsingContext, Some(uriModified), Some(isXFOError));
|
||||
mBrowsingContext, Some(uriModified), Some(isEmbeddingBlockedError));
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
|
||||
!isAboutBlankLoadOntoInitialAboutBlank) {
|
||||
channel = DocumentChannel::CreateForDocument(aLoadState, loadInfo,
|
||||
loadFlags, this, cacheKey,
|
||||
uriModified, isXFOError);
|
||||
channel = DocumentChannel::CreateForDocument(
|
||||
aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified,
|
||||
isEmbeddingBlockedError);
|
||||
MOZ_ASSERT(channel);
|
||||
|
||||
// Disable keyword fixup when using DocumentChannel, since
|
||||
|
|
|
|||
|
|
@ -1092,7 +1092,7 @@ void nsDocShellLoadState::CalculateLoadURIFlags() {
|
|||
|
||||
nsLoadFlags nsDocShellLoadState::CalculateChannelLoadFlags(
|
||||
BrowsingContext* aBrowsingContext, Maybe<bool> aUriModified,
|
||||
Maybe<bool> aIsXFOError) {
|
||||
Maybe<bool> aIsEmbeddingBlockedError) {
|
||||
MOZ_ASSERT(aBrowsingContext);
|
||||
|
||||
nsLoadFlags loadFlags = aBrowsingContext->GetDefaultLoadFlags();
|
||||
|
|
@ -1106,13 +1106,13 @@ nsLoadFlags nsDocShellLoadState::CalculateChannelLoadFlags(
|
|||
|
||||
// These values aren't available for loads initiated in the Parent process.
|
||||
MOZ_ASSERT_IF(loadType == LOAD_HISTORY, aUriModified.isSome());
|
||||
MOZ_ASSERT_IF(loadType == LOAD_ERROR_PAGE, aIsXFOError.isSome());
|
||||
MOZ_ASSERT_IF(loadType == LOAD_ERROR_PAGE, aIsEmbeddingBlockedError.isSome());
|
||||
|
||||
if (loadType == LOAD_ERROR_PAGE) {
|
||||
// Error pages are LOAD_BACKGROUND, unless it's an
|
||||
// XFO error for which we want an error page to load
|
||||
// XFO / frame-ancestors error for which we want an error page to load
|
||||
// but additionally want the onload() event to fire.
|
||||
if (!*aIsXFOError) {
|
||||
if (!*aIsEmbeddingBlockedError) {
|
||||
loadFlags |= nsIChannel::LOAD_BACKGROUND;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -363,10 +363,12 @@ class nsDocShellLoadState final {
|
|||
void CalculateLoadURIFlags();
|
||||
|
||||
// Compute the load flags to be used by creating channel. aUriModified and
|
||||
// aIsXFOError are expected to be Nothing when called from Parent process.
|
||||
// aIsEmbeddingBlockedError are expected to be Nothing when called from parent
|
||||
// process.
|
||||
nsLoadFlags CalculateChannelLoadFlags(
|
||||
mozilla::dom::BrowsingContext* aBrowsingContext,
|
||||
mozilla::Maybe<bool> aUriModified, mozilla::Maybe<bool> aIsXFOError);
|
||||
mozilla::Maybe<bool> aUriModified,
|
||||
mozilla::Maybe<bool> aIsEmbeddingBlockedError);
|
||||
|
||||
mozilla::dom::DocShellLoadStateInit Serialize(
|
||||
mozilla::ipc::IProtocol* aActor);
|
||||
|
|
|
|||
|
|
@ -67,14 +67,15 @@ NS_INTERFACE_MAP_END
|
|||
DocumentChannel::DocumentChannel(nsDocShellLoadState* aLoadState,
|
||||
net::LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags, uint32_t aCacheKey,
|
||||
bool aUriModified, bool aIsXFOError)
|
||||
bool aUriModified,
|
||||
bool aIsEmbeddingBlockedError)
|
||||
: mLoadState(aLoadState),
|
||||
mCacheKey(aCacheKey),
|
||||
mLoadFlags(aLoadFlags),
|
||||
mURI(aLoadState->URI()),
|
||||
mLoadInfo(aLoadInfo),
|
||||
mUriModified(aUriModified),
|
||||
mIsXFOError(aIsXFOError) {
|
||||
mIsEmbeddingBlockedError(aIsEmbeddingBlockedError) {
|
||||
LOG(("DocumentChannel ctor [this=%p, uri=%s]", this,
|
||||
aLoadState->URI()->GetSpecOrDefault().get()));
|
||||
RefPtr<nsHttpHandler> handler = nsHttpHandler::GetInstance();
|
||||
|
|
@ -171,15 +172,16 @@ bool DocumentChannel::CanUseDocumentChannel(nsIURI* aURI) {
|
|||
already_AddRefed<DocumentChannel> DocumentChannel::CreateForDocument(
|
||||
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks,
|
||||
uint32_t aCacheKey, bool aUriModified, bool aIsXFOError) {
|
||||
uint32_t aCacheKey, bool aUriModified, bool aIsEmbeddingBlockedError) {
|
||||
RefPtr<DocumentChannel> channel;
|
||||
if (XRE_IsContentProcess()) {
|
||||
channel = new DocumentChannelChild(aLoadState, aLoadInfo, aLoadFlags,
|
||||
aCacheKey, aUriModified, aIsXFOError);
|
||||
} else {
|
||||
channel =
|
||||
new ParentProcessDocumentChannel(aLoadState, aLoadInfo, aLoadFlags,
|
||||
aCacheKey, aUriModified, aIsXFOError);
|
||||
new DocumentChannelChild(aLoadState, aLoadInfo, aLoadFlags, aCacheKey,
|
||||
aUriModified, aIsEmbeddingBlockedError);
|
||||
} else {
|
||||
channel = new ParentProcessDocumentChannel(
|
||||
aLoadState, aLoadInfo, aLoadFlags, aCacheKey, aUriModified,
|
||||
aIsEmbeddingBlockedError);
|
||||
}
|
||||
channel->SetNotificationCallbacks(aNotificationCallbacks);
|
||||
return channel.forget();
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class DocumentChannel : public nsIIdentChannel {
|
|||
static already_AddRefed<DocumentChannel> CreateForDocument(
|
||||
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks,
|
||||
uint32_t aCacheKey, bool aUriModified, bool aIsXFOError);
|
||||
uint32_t aCacheKey, bool aUriModified, bool aIsEmbeddingBlockedError);
|
||||
static already_AddRefed<DocumentChannel> CreateForObject(
|
||||
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks);
|
||||
|
|
@ -77,7 +77,7 @@ class DocumentChannel : public nsIIdentChannel {
|
|||
protected:
|
||||
DocumentChannel(nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags, uint32_t aCacheKey, bool aUriModified,
|
||||
bool aIsXFOError);
|
||||
bool aIsEmbeddingBlockedError);
|
||||
|
||||
void ShutdownListeners(nsresult aStatusCode);
|
||||
virtual void DeleteIPDL() {}
|
||||
|
|
@ -106,9 +106,10 @@ class DocumentChannel : public nsIIdentChannel {
|
|||
// mUriModified is true if we're doing a history load and the URI of the
|
||||
// session history had been modified by pushState/replaceState.
|
||||
bool mUriModified = false;
|
||||
// mIsXFOError is true if we're handling a load error and the status of the
|
||||
// failed channel is NS_ERROR_XFO_VIOLATION.
|
||||
bool mIsXFOError = false;
|
||||
// mIsEmbeddingBlockedError is true if we're handling a load error and the
|
||||
// status of the failed channel is NS_ERROR_XFO_VIOLATION or
|
||||
// NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION.
|
||||
bool mIsEmbeddingBlockedError = false;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(DocumentChannel, DOCUMENT_CHANNEL_IID)
|
||||
|
|
|
|||
|
|
@ -48,9 +48,10 @@ DocumentChannelChild::DocumentChannelChild(nsDocShellLoadState* aLoadState,
|
|||
net::LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags,
|
||||
uint32_t aCacheKey,
|
||||
bool aUriModified, bool aIsXFOError)
|
||||
bool aUriModified,
|
||||
bool aIsEmbeddingBlockedError)
|
||||
: DocumentChannel(aLoadState, aLoadInfo, aLoadFlags, aCacheKey,
|
||||
aUriModified, aIsXFOError) {
|
||||
aUriModified, aIsEmbeddingBlockedError) {
|
||||
mLoadingContext = nullptr;
|
||||
LOG(("DocumentChannelChild ctor [this=%p, uri=%s]", this,
|
||||
aLoadState->URI()->GetSpecOrDefault().get()));
|
||||
|
|
@ -119,7 +120,7 @@ DocumentChannelChild::AsyncOpen(nsIStreamListener* aListener) {
|
|||
case ExtContentPolicy::TYPE_SUBDOCUMENT: {
|
||||
DocumentCreationArgs docArgs;
|
||||
docArgs.uriModified() = mUriModified;
|
||||
docArgs.isXFOError() = mIsXFOError;
|
||||
docArgs.isEmbeddingBlockedError() = mIsEmbeddingBlockedError;
|
||||
|
||||
ipcElementCreationArgs = docArgs;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ class DocumentChannelChild final : public DocumentChannel,
|
|||
public:
|
||||
DocumentChannelChild(nsDocShellLoadState* aLoadState,
|
||||
class LoadInfo* aLoadInfo, nsLoadFlags aLoadFlags,
|
||||
uint32_t aCacheKey, bool aUriModified, bool aIsXFOError);
|
||||
uint32_t aCacheKey, bool aUriModified,
|
||||
bool aIsEmbeddingBlockedError);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ bool DocumentChannelParent::Init(dom::CanonicalBrowsingContext* aContext,
|
|||
promise = mDocumentLoadListener->OpenDocument(
|
||||
loadState, aArgs.cacheKey(), Some(aArgs.channelId()),
|
||||
aArgs.asyncOpenTime(), aArgs.timing(), std::move(clientInfo),
|
||||
Some(docArgs.uriModified()), Some(docArgs.isXFOError()),
|
||||
Some(docArgs.uriModified()), Some(docArgs.isEmbeddingBlockedError()),
|
||||
contentParent, &rv);
|
||||
} else {
|
||||
const ObjectCreationArgs& objectArgs = aArgs.elementCreationArgs();
|
||||
|
|
|
|||
|
|
@ -933,7 +933,7 @@ auto DocumentLoadListener::OpenDocument(
|
|||
nsDocShellLoadState* aLoadState, uint32_t aCacheKey,
|
||||
const Maybe<uint64_t>& aChannelId, const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming, Maybe<dom::ClientInfo>&& aInfo,
|
||||
Maybe<bool> aUriModified, Maybe<bool> aIsXFOError,
|
||||
Maybe<bool> aUriModified, Maybe<bool> aIsEmbeddingBlockedError,
|
||||
dom::ContentParent* aContentParent, nsresult* aRv) -> RefPtr<OpenPromise> {
|
||||
LOG(("DocumentLoadListener [%p] OpenDocument [uri=%s]", this,
|
||||
aLoadState->URI()->GetSpecOrDefault().get()));
|
||||
|
|
@ -950,7 +950,8 @@ auto DocumentLoadListener::OpenDocument(
|
|||
CreateDocumentLoadInfo(browsingContext, aLoadState);
|
||||
|
||||
nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags(
|
||||
browsingContext, std::move(aUriModified), std::move(aIsXFOError));
|
||||
browsingContext, std::move(aUriModified),
|
||||
std::move(aIsEmbeddingBlockedError));
|
||||
|
||||
// Keep track of navigation for the Bounce Tracking Protection.
|
||||
if (browsingContext->IsTopContent()) {
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
nsDocShellLoadState* aLoadState, uint32_t aCacheKey,
|
||||
const Maybe<uint64_t>& aChannelId, const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming, Maybe<dom::ClientInfo>&& aInfo,
|
||||
Maybe<bool> aUriModified, Maybe<bool> aIsXFOError,
|
||||
Maybe<bool> aUriModified, Maybe<bool> aIsEmbeddingBlockedError,
|
||||
dom::ContentParent* aContentParent, nsresult* aRv);
|
||||
|
||||
RefPtr<OpenPromise> OpenObject(
|
||||
|
|
|
|||
|
|
@ -455,7 +455,7 @@ struct CookieStruct
|
|||
|
||||
struct DocumentCreationArgs {
|
||||
bool uriModified;
|
||||
bool isXFOError;
|
||||
bool isEmbeddingBlockedError;
|
||||
};
|
||||
|
||||
struct ObjectCreationArgs {
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ NS_IMPL_ISUPPORTS_INHERITED(ParentProcessDocumentChannel, DocumentChannel,
|
|||
ParentProcessDocumentChannel::ParentProcessDocumentChannel(
|
||||
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags, uint32_t aCacheKey, bool aUriModified,
|
||||
bool aIsXFOError)
|
||||
bool aIsEmbeddingBlockedError)
|
||||
: DocumentChannel(aLoadState, aLoadInfo, aLoadFlags, aCacheKey,
|
||||
aUriModified, aIsXFOError) {
|
||||
aUriModified, aIsEmbeddingBlockedError) {
|
||||
LOG(("ParentProcessDocumentChannel ctor [this=%p]", this));
|
||||
}
|
||||
|
||||
|
|
@ -176,8 +176,8 @@ NS_IMETHODIMP ParentProcessDocumentChannel::AsyncOpen(
|
|||
if (isDocumentLoad) {
|
||||
promise = mDocumentLoadListener->OpenDocument(
|
||||
mLoadState, mCacheKey, Some(mChannelId), TimeStamp::Now(), mTiming,
|
||||
std::move(initialClientInfo), Some(mUriModified), Some(mIsXFOError),
|
||||
nullptr /* ContentParent */, &rv);
|
||||
std::move(initialClientInfo), Some(mUriModified),
|
||||
Some(mIsEmbeddingBlockedError), nullptr /* ContentParent */, &rv);
|
||||
} else {
|
||||
promise = mDocumentLoadListener->OpenObject(
|
||||
mLoadState, mCacheKey, Some(mChannelId), TimeStamp::Now(), mTiming,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ class ParentProcessDocumentChannel : public DocumentChannel,
|
|||
ParentProcessDocumentChannel(nsDocShellLoadState* aLoadState,
|
||||
class LoadInfo* aLoadInfo,
|
||||
nsLoadFlags aLoadFlags, uint32_t aCacheKey,
|
||||
bool aUriModified, bool aIsXFOError);
|
||||
bool aUriModified,
|
||||
bool aIsEmbeddingBlockedError);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
[deny.html]
|
||||
expected: TIMEOUT
|
||||
[`DENY` blocks cross-origin framing with CSP frame-ancestors 'self']
|
||||
expected: TIMEOUT
|
||||
|
||||
Loading…
Reference in a new issue