Skip to content

Commit

Permalink
Bug 1867628 - Fire a load event when frame-ancestors blocks an iframe…
Browse files Browse the repository at this point in the history
… (similar to X-Frame-Options). r=nika,smaug

Differential Revision: https://phabricator.services.mozilla.com/D196036
  • Loading branch information
evilpie committed Dec 19, 2023
1 parent 8782212 commit 061fc36
Show file tree
Hide file tree
Showing 14 changed files with 49 additions and 44 deletions.
13 changes: 7 additions & 6 deletions docshell/base/nsDocShell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions docshell/base/nsDocShellLoadState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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;
}
}
Expand Down
6 changes: 4 additions & 2 deletions docshell/base/nsDocShellLoadState.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
18 changes: 10 additions & 8 deletions netwerk/ipc/DocumentChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
11 changes: 6 additions & 5 deletions netwerk/ipc/DocumentChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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() {}
Expand Down Expand Up @@ -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)
Expand Down
7 changes: 4 additions & 3 deletions netwerk/ipc/DocumentChannelChild.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion netwerk/ipc/DocumentChannelChild.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion netwerk/ipc/DocumentChannelParent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
5 changes: 3 additions & 2 deletions netwerk/ipc/DocumentLoadListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
Expand All @@ -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()) {
Expand Down
2 changes: 1 addition & 1 deletion netwerk/ipc/DocumentLoadListener.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion netwerk/ipc/NeckoChannelParams.ipdlh
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ struct CookieStruct

struct DocumentCreationArgs {
bool uriModified;
bool isXFOError;
bool isEmbeddingBlockedError;
};

struct ObjectCreationArgs {
Expand Down
8 changes: 4 additions & 4 deletions netwerk/ipc/ParentProcessDocumentChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

Expand Down Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion netwerk/ipc/ParentProcessDocumentChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 0 additions & 5 deletions testing/web-platform/meta/x-frame-options/deny.html.ini

This file was deleted.

0 comments on commit 061fc36

Please sign in to comment.