Bug 1518454: Part 1, backend changes, add CSP to loadURIOptions dictionary and pass CSP explicitly from frontend to docshell. r=bz

This commit is contained in:
Christoph Kerschbaumer 2019-02-21 16:00:32 +01:00
Родитель f52a83802a
Коммит 7c441f1bcb
37 изменённых файлов: 495 добавлений и 89 удалений

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

@ -151,12 +151,13 @@ interface nsIPrincipal : nsISerializable
in boolean allowIfInheritsPrincipal);
/**
* A Content Security Policy associated with this principal.
* Use this function to query the associated CSP with this principal.
* Please *only* use this function to *set* a CSP when you know exactly what you are doing.
* A Content Security Policy associated with this principal. Use this function to
* query the associated CSP with this principal, but please *only* use this
* function to *set* a CSP when you know exactly what you are doing.
* Most likely you want to call ensureCSP instead of setCSP.
*/
[noscript] attribute nsIContentSecurityPolicy csp;
readonly attribute nsIContentSecurityPolicy csp;
[noscript] void setCsp(in nsIContentSecurityPolicy aCsp);
/*
* Use this function to query a CSP associated with this principal.

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

@ -3916,6 +3916,7 @@ nsresult nsDocShell::LoadURI(const nsAString& aURI,
loadState->SetHeadersStream(aLoadURIOptions.mHeaders);
loadState->SetBaseURI(aLoadURIOptions.mBaseURI);
loadState->SetTriggeringPrincipal(aLoadURIOptions.mTriggeringPrincipal);
loadState->SetCsp(aLoadURIOptions.mCsp);
loadState->SetForceAllowDataURI(forceAllowDataURI);
if (fixupInfo) {
@ -4558,6 +4559,13 @@ nsDocShell::Reload(uint32_t aReloadFlags) {
bool loadReplace = false;
nsIPrincipal* triggeringPrincipal = doc->NodePrincipal();
// Currently the NodePrincipal holds the CSP for that document,
// after Bug 965637 we can query the CSP directly from the doc
// instead of doc->NodePrincipal().
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString contentTypeHint;
doc->GetContentType(contentTypeHint);
@ -4600,6 +4608,7 @@ nsDocShell::Reload(uint32_t aReloadFlags) {
loadState->SetLoadReplace(loadReplace);
loadState->SetTriggeringPrincipal(triggeringPrincipal);
loadState->SetPrincipalToInherit(triggeringPrincipal);
loadState->SetCsp(csp);
loadState->SetLoadFlags(flags);
loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint));
loadState->SetLoadType(loadType);
@ -5790,13 +5799,21 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
principal = doc->NodePrincipal();
}
loadState->SetTriggeringPrincipal(principal);
// Currently the principal (NodePrincipal) holds the CSP for that
// document, after Bug 965637 we can query the CSP directly from
// the doc instead of the principal.
nsCOMPtr<nsIContentSecurityPolicy> csp;
nsresult rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
loadState->SetCsp(csp);
loadState->SetPrincipalIsExplicit(true);
/* Check if this META refresh causes a redirection
* to another site.
*/
bool equalUri = false;
nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
rv = aURI->Equals(mCurrentURI, &equalUri);
if (NS_SUCCEEDED(rv) && (!equalUri) && aMetaRefresh &&
aDelay <= REFRESH_REDIRECT_TIMER) {
/* It is a META refresh based redirection within the threshold time
@ -6350,7 +6367,7 @@ nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
// from the channel and store it in session history.
// Pass false for aCloneChildren, since we're creating
// a new DOM here.
AddToSessionHistory(uri, wcwgChannel, nullptr, nullptr, false,
AddToSessionHistory(uri, wcwgChannel, nullptr, nullptr, nullptr, false,
getter_AddRefs(mLSHE));
SetCurrentURI(uri, aRequest, true, 0);
// Save history state of the previous page
@ -6855,6 +6872,13 @@ nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
LoadURIOptions loadURIOptions;
loadURIOptions.mTriggeringPrincipal = triggeringPrincipal;
// Currently we query the CSP from the triggeringPrincipal within
// the loadInfo. After Bug 965637, we can query the CSP from the
// loadInfo, which internally queries the CSP from the Client.
nsCOMPtr<nsIContentSecurityPolicy> csp;
nsresult rv = triggeringPrincipal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
loadURIOptions.mCsp = csp;
loadURIOptions.mPostData = newPostData;
return LoadURI(newSpecW, loadURIOptions);
}
@ -8079,7 +8103,7 @@ nsresult nsDocShell::CreateContentViewer(const nsACString& aContentType,
if (failedURI) {
errorOnLocationChangeNeeded =
OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr,
mLoadType, false, false, false);
mLoadType, nullptr, false, false, false);
}
// Be sure to have a correct mLSHE, it may have been cleared by
@ -8737,6 +8761,7 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState,
// LoadReplace will always be false due to asserts above, skip setting
// it.
loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal());
loadState->SetCsp(aLoadState->Csp());
loadState->SetInheritPrincipal(
aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL));
// Explicit principal because we do not want any guesses as to what the
@ -8942,12 +8967,21 @@ nsresult nsDocShell::MaybeHandleSameDocumentNavigation(
* recorded in session and global history.
*/
nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit;
nsCOMPtr<nsIContentSecurityPolicy> newCsp;
if (mOSHE) {
newURITriggeringPrincipal = mOSHE->GetTriggeringPrincipal();
newURIPrincipalToInherit = mOSHE->GetPrincipalToInherit();
newCsp = mOSHE->GetCsp();
} else {
newURITriggeringPrincipal = aLoadState->TriggeringPrincipal();
newURIPrincipalToInherit = doc->NodePrincipal();
// This is a same-document navigation hence we query the CSP
// from the current document. Please note that currently the
// NodePrincipal holds the CSP for that document, after
// Bug 965637 we can query the CSP directly from
// the doc instead of the NodePrincipal.
nsresult rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(newCsp));
NS_ENSURE_SUCCESS(rv, rv);
}
// Pass true for aCloneSHChildren, since we're not
// changing documents here, so all of our subframes are
@ -8958,7 +8992,7 @@ nsresult nsDocShell::MaybeHandleSameDocumentNavigation(
// Anyway, aCloneSHChildren param is simply reflecting
// doSameDocumentNavigation in this scope.
OnNewURI(aLoadState->URI(), nullptr, newURITriggeringPrincipal,
newURIPrincipalToInherit, mLoadType, true, true, true);
newURIPrincipalToInherit, mLoadType, newCsp, true, true, true);
nsCOMPtr<nsIInputStream> postData;
uint32_t cacheKey = 0;
@ -9327,7 +9361,7 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
}
rv = browserChrome3->ShouldLoadURI(
this, aLoadState->URI(), referrer, !!aLoadState->PostDataStream(),
aLoadState->TriggeringPrincipal(), &shouldLoad);
aLoadState->TriggeringPrincipal(), aLoadState->Csp(), &shouldLoad);
if (NS_SUCCEEDED(rv) && !shouldLoad) {
return NS_OK;
}
@ -9914,6 +9948,36 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
// holds upgrade-insecure-requests.
nsCOMPtr<nsIContentSecurityPolicy> csp;
aLoadState->TriggeringPrincipal()->GetCsp(getter_AddRefs(csp));
#ifdef DEBUG
{
// After Bug 965637 we move the CSP from the Principal into the Client,
// hence we need an explicit CSP argument passed to docshell. Let's make
// sure the explicit CSP is the same as the CSP on the Principal.
uint32_t principalCSPCount = 0;
if (csp) {
csp->GetPolicyCount(&principalCSPCount);
}
nsCOMPtr<nsIContentSecurityPolicy> argsCSP = aLoadState->Csp();
uint32_t argCSPCount = 0;
if (argsCSP) {
argsCSP->GetPolicyCount(&argCSPCount);
}
MOZ_ASSERT(principalCSPCount == argCSPCount,
"Different PolicyCount for CSP as arg and Principal");
nsAutoString principalPolicyStr, argPolicyStr;
for (uint32_t i = 0; i < principalCSPCount; ++i) {
csp->GetPolicyString(i, principalPolicyStr);
argsCSP->GetPolicyString(i, argPolicyStr);
MOZ_ASSERT(principalPolicyStr.Equals(argPolicyStr),
"Different PolicyStr for CSP as arg and Principal");
}
}
#endif
if (csp) {
bool upgradeInsecureRequests = false;
csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
@ -10544,6 +10608,7 @@ void nsDocShell::SetupReferrerInfoFromChannel(nsIChannel* aChannel) {
bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aPrincipalToInherit, uint32_t aLoadType,
nsIContentSecurityPolicy* aCsp,
bool aFireOnLocationChange, bool aAddToGlobalHistory,
bool aCloneSHChildren) {
MOZ_ASSERT(aURI, "uri is null");
@ -10719,7 +10784,7 @@ bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
* rootDocShell
*/
(void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal,
aPrincipalToInherit, aCloneSHChildren,
aPrincipalToInherit, aCsp, aCloneSHChildren,
getter_AddRefs(mLSHE));
}
} else if (mSessionHistory && mLSHE && mURIResultedInDocument) {
@ -10805,7 +10870,7 @@ bool nsDocShell::OnLoadingSite(nsIChannel* aChannel, bool aFireOnLocationChange,
NS_ENSURE_TRUE(uri, false);
// Pass false for aCloneSHChildren, since we're loading a new page here.
return OnNewURI(uri, aChannel, nullptr, nullptr, mLoadType,
return OnNewURI(uri, aChannel, nullptr, nullptr, mLoadType, nullptr,
aFireOnLocationChange, aAddToGlobalHistory, false);
}
@ -11010,11 +11075,17 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
bool scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
// Currently the NodePrincipal holds the CSP for that document,
// after Bug 965637 we can query the CSP directly from
// the doc instead of the NodePrincipal.
nsCOMPtr<nsIContentSecurityPolicy> csp;
document->NodePrincipal()->GetCsp(getter_AddRefs(csp));
// Since we're not changing which page we have loaded, pass
// true for aCloneChildren.
rv = AddToSessionHistory(newURI, nullptr,
document->NodePrincipal(), // triggeringPrincipal
nullptr, true, getter_AddRefs(newSHEntry));
nullptr, csp, true, getter_AddRefs(newSHEntry));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(newSHEntry, NS_ERROR_FAILURE);
@ -11187,6 +11258,7 @@ bool nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel) {
nsresult nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aPrincipalToInherit,
nsIContentSecurityPolicy* aCsp,
bool aCloneChildren,
nsISHEntry** aNewEntry) {
MOZ_ASSERT(aURI, "uri is null");
@ -11253,6 +11325,7 @@ nsresult nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
uint32_t cacheKey = 0;
nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal;
nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp;
bool expired = false;
bool discardLayoutState = false;
nsCOMPtr<nsICacheInfoChannel> cacheChannel;
@ -11292,6 +11365,14 @@ nsresult nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
if (!triggeringPrincipal) {
triggeringPrincipal = loadInfo->TriggeringPrincipal();
}
if (!csp && triggeringPrincipal) {
// Currently if no CSP is passed explicitly we query the CSP from
// the triggeringPrincipal from within the loadinfo. After Bug 965637,
// we can query the CSP from the loadInfo directly in case the CSP is
// not passed explicitly. Internally the loadinfo queries the CSP
// from the Client.
triggeringPrincipal->GetCsp(getter_AddRefs(csp));
}
loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
@ -11321,7 +11402,7 @@ nsresult nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
cacheKey, // CacheKey
mContentTypeHint, // Content-type
triggeringPrincipal, // Channel or provided principal
principalToInherit, mHistoryID, mDynamicallyCreated);
principalToInherit, csp, mHistoryID, mDynamicallyCreated);
entry->SetOriginalURI(originalURI);
entry->SetResultPrincipalURI(resultPrincipalURI);
@ -11439,6 +11520,7 @@ nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType) {
aEntry->GetContentType(contentType);
nsCOMPtr<nsIPrincipal> triggeringPrincipal = aEntry->GetTriggeringPrincipal();
nsCOMPtr<nsIPrincipal> principalToInherit = aEntry->GetPrincipalToInherit();
nsCOMPtr<nsIContentSecurityPolicy> csp = aEntry->GetCsp();
nsCOMPtr<nsIReferrerInfo> referrerInfo = aEntry->GetReferrerInfo();
// Calling CreateAboutBlankContentViewer can set mOSHE to null, and if
@ -11532,6 +11614,7 @@ nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType) {
loadState->SetFirstParty(true);
loadState->SetSrcdocData(srcdoc);
loadState->SetBaseURI(baseURI);
loadState->SetCsp(csp);
rv = InternalLoad(loadState,
nullptr, // No nsIDocShell
@ -12346,7 +12429,8 @@ class OnLinkClickEvent : public Runnable {
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream, bool aNoOpenerImplied,
bool aIsUserTriggered, bool aIsTrusted,
nsIPrincipal* aTriggeringPrincipal);
nsIPrincipal* aTriggeringPrincipal,
nsIContentSecurityPolicy* aCsp);
NS_IMETHOD Run() override {
nsAutoPopupStatePusher popupStatePusher(mPopupState);
@ -12362,7 +12446,7 @@ class OnLinkClickEvent : public Runnable {
mHandler->OnLinkClickSync(mContent, mURI, mTargetSpec, mFileName,
mPostDataStream, mHeadersDataStream,
mNoOpenerImplied, nullptr, nullptr,
mIsUserTriggered, mTriggeringPrincipal);
mIsUserTriggered, mTriggeringPrincipal, mCsp);
}
return NS_OK;
}
@ -12380,16 +12464,15 @@ class OnLinkClickEvent : public Runnable {
bool mIsUserTriggered;
bool mIsTrusted;
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
nsCOMPtr<nsIContentSecurityPolicy> mCsp;
};
OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
nsIURI* aURI, const nsAString& aTargetSpec,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
bool aNoOpenerImplied, bool aIsUserTriggered,
bool aIsTrusted,
nsIPrincipal* aTriggeringPrincipal)
OnLinkClickEvent::OnLinkClickEvent(
nsDocShell* aHandler, nsIContent* aContent, nsIURI* aURI,
const nsAString& aTargetSpec, const nsAString& aFileName,
nsIInputStream* aPostDataStream, nsIInputStream* aHeadersDataStream,
bool aNoOpenerImplied, bool aIsUserTriggered, bool aIsTrusted,
nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp)
: mozilla::Runnable("OnLinkClickEvent"),
mHandler(aHandler),
mURI(aURI),
@ -12402,16 +12485,15 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
mNoOpenerImplied(aNoOpenerImplied),
mIsUserTriggered(aIsUserTriggered),
mIsTrusted(aIsTrusted),
mTriggeringPrincipal(aTriggeringPrincipal) {}
mTriggeringPrincipal(aTriggeringPrincipal),
mCsp(aCsp) {}
NS_IMETHODIMP
nsDocShell::OnLinkClick(nsIContent* aContent, nsIURI* aURI,
const nsAString& aTargetSpec,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
bool aIsUserTriggered, bool aIsTrusted,
nsIPrincipal* aTriggeringPrincipal) {
nsDocShell::OnLinkClick(
nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec,
const nsAString& aFileName, nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream, bool aIsUserTriggered, bool aIsTrusted,
nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) {
#ifndef ANDROID
MOZ_ASSERT(aTriggeringPrincipal, "Need a valid triggeringPrincipal");
#endif
@ -12452,10 +12534,10 @@ nsDocShell::OnLinkClick(nsIContent* aContent, nsIURI* aURI,
target = aTargetSpec;
}
nsCOMPtr<nsIRunnable> ev =
new OnLinkClickEvent(this, aContent, aURI, target, aFileName,
aPostDataStream, aHeadersDataStream, noOpenerImplied,
aIsUserTriggered, aIsTrusted, aTriggeringPrincipal);
nsCOMPtr<nsIRunnable> ev = new OnLinkClickEvent(
this, aContent, aURI, target, aFileName, aPostDataStream,
aHeadersDataStream, noOpenerImplied, aIsUserTriggered, aIsTrusted,
aTriggeringPrincipal, aCsp);
return DispatchToTabGroup(TaskCategory::UI, ev.forget());
}
@ -12466,14 +12548,12 @@ static bool IsElementAnchorOrArea(nsIContent* aContent) {
}
NS_IMETHODIMP
nsDocShell::OnLinkClickSync(nsIContent* aContent, nsIURI* aURI,
const nsAString& aTargetSpec,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
bool aNoOpenerImplied, nsIDocShell** aDocShell,
nsIRequest** aRequest, bool aIsUserTriggered,
nsIPrincipal* aTriggeringPrincipal) {
nsDocShell::OnLinkClickSync(
nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec,
const nsAString& aFileName, nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream, bool aNoOpenerImplied,
nsIDocShell** aDocShell, nsIRequest** aRequest, bool aIsUserTriggered,
nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) {
// Initialize the DocShell / Request
if (aDocShell) {
*aDocShell = nullptr;
@ -12524,6 +12604,14 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent, nsIURI* aURI,
nsCOMPtr<nsIPrincipal> triggeringPrincipal =
aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal();
nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp;
if (!csp) {
// Currently, if no csp is passed explicitly we fall back to querying the
// CSP from the NodePrincipal(). After Bug 965637 we can fall back to
// querying the CSP from the document (aContent->OwnerDoc()).
aContent->NodePrincipal()->GetCsp(getter_AddRefs(csp));
}
uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
if (IsElementAnchorOrArea(aContent)) {
MOZ_ASSERT(aContent->IsHTMLElement());
@ -12635,6 +12723,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent, nsIURI* aURI,
loadState->SetReferrerInfo(referrerInfo);
loadState->SetTriggeringPrincipal(triggeringPrincipal);
loadState->SetPrincipalToInherit(aContent->NodePrincipal());
loadState->SetCsp(csp);
loadState->SetLoadFlags(flags);
loadState->SetTarget(aTargetSpec);
loadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint));

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

@ -217,14 +217,16 @@ class nsDocShell final : public nsDocLoader,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
bool aIsUserTriggered, bool aIsTrusted,
nsIPrincipal* aTriggeringPrincipal) override;
nsIPrincipal* aTriggeringPrincipal,
nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD OnLinkClickSync(
nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec,
const nsAString& aFileName, nsIInputStream* aPostDataStream = 0,
nsIInputStream* aHeadersDataStream = 0, bool aNoOpenerImplied = false,
nsIDocShell** aDocShell = 0, nsIRequest** aRequest = 0,
bool aIsUserTriggered = false,
nsIPrincipal* aTriggeringPrincipal = nullptr) override;
nsIPrincipal* aTriggeringPrincipal = nullptr,
nsIContentSecurityPolicy* aCsp = nullptr) override;
NS_IMETHOD OnOverLink(nsIContent* aContent, nsIURI* aURI,
const nsAString& aTargetSpec) override;
NS_IMETHOD OnLeaveLink() override;
@ -502,10 +504,15 @@ class nsDocShell final : public nsDocLoader,
// children will be cloned onto the new entry. This should be
// used when we aren't actually changing the document while adding
// the new session history entry.
// aCsp is the CSP to be used for the load. That is *not* the CSP
// that will be applied to subresource loads within that document
// but the CSP for the document load itself. E.g. if that CSP
// includes upgrade-insecure-requests, then the new top-level load
// will be upgraded to HTTPS.
nsresult AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aPrincipalToInherit,
nsIContentSecurityPolicy* aCsp,
bool aCloneChildren, nsISHEntry** aNewEntry);
nsresult AddChildSHEntryToParent(nsISHEntry* aNewEntry, int32_t aChildOffset,
@ -570,11 +577,16 @@ class nsDocShell final : public nsDocLoader,
// present, the owner should be gotten from it.
// If OnNewURI calls AddToSessionHistory, it will pass its
// aCloneSHChildren argument as aCloneChildren.
// aCsp is the CSP to be used for the load. That is *not* the CSP
// that will be applied to subresource loads within that document
// but the CSP for the document load itself. E.g. if that CSP
// includes upgrade-insecure-requests, then the new top-level load
// will be upgraded to HTTPS.
bool OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aPrincipalToInherit, uint32_t aLoadType,
bool aFireOnLocationChange, bool aAddToGlobalHistory,
bool aCloneSHChildren);
nsIContentSecurityPolicy* aCsp, bool aFireOnLocationChange,
bool aAddToGlobalHistory, bool aCloneSHChildren);
// Helper method that is called when a new document (including any
// sub-documents - ie. frames) has been completely loaded.

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

@ -62,6 +62,7 @@ nsDocShellLoadState::nsDocShellLoadState(DocShellLoadStateInit& aLoadState) {
mBaseURI = aLoadState.BaseURI();
mTriggeringPrincipal = aLoadState.TriggeringPrincipal();
mPrincipalToInherit = aLoadState.PrincipalToInherit();
mCsp = aLoadState.Csp();
}
nsDocShellLoadState::~nsDocShellLoadState() {}
@ -167,6 +168,12 @@ void nsDocShellLoadState::SetPrincipalToInherit(
mPrincipalToInherit = aPrincipalToInherit;
}
void nsDocShellLoadState::SetCsp(nsIContentSecurityPolicy* aCsp) {
mCsp = aCsp;
}
nsIContentSecurityPolicy* nsDocShellLoadState::Csp() const { return mCsp; }
bool nsDocShellLoadState::InheritPrincipal() const { return mInheritPrincipal; }
void nsDocShellLoadState::SetInheritPrincipal(bool aInheritPrincipal) {
@ -459,6 +466,7 @@ DocShellLoadStateInit nsDocShellLoadState::Serialize() {
loadState.BaseURI() = mBaseURI;
loadState.TriggeringPrincipal() = mTriggeringPrincipal;
loadState.PrincipalToInherit() = mPrincipalToInherit;
loadState.Csp() = mCsp;
loadState.Referrer() = mReferrerInfo->GetOriginalReferrer();
loadState.SendReferrer() = mReferrerInfo->GetSendReferrer();
loadState.ReferrerPolicy() = mReferrerInfo->GetReferrerPolicy();

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

@ -13,6 +13,7 @@
#include "nsDocShellLoadTypes.h"
#include "mozilla/net/ReferrerPolicy.h"
class nsIContentSecurityPolicy;
class nsIInputStream;
class nsISHEntry;
class nsIURI;
@ -78,6 +79,10 @@ class nsDocShellLoadState final {
void SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal);
nsIContentSecurityPolicy* Csp() const;
void SetCsp(nsIContentSecurityPolicy* aCsp);
bool InheritPrincipal() const;
void SetInheritPrincipal(bool aInheritPrincipal);
@ -226,6 +231,13 @@ class nsDocShellLoadState final {
// SystemPrincipal as the triggeringPrincipal.
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
// The CSP of the load, that is, the CSP of the entity responsible for causing
// the load to occur. Most likely this is the CSP of the document that started
// the load. In case the entity starting the load did not use a CSP, then mCsp
// can be null. Please note that this is also the CSP that will be applied to
// the load in case the load encounters a server side redirect.
nsCOMPtr<nsIContentSecurityPolicy> mCsp;
// If a refresh is caused by http-equiv="refresh" we want to set
// aResultPrincipalURI, but we do not want to overwrite the channel's
// ResultPrincipalURI, if it has already been set on the channel by a protocol

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

@ -906,6 +906,9 @@ nsDocShellTreeOwner::HandleEvent(Event* aEvent) {
#endif
LoadURIOptions loadURIOptions;
loadURIOptions.mTriggeringPrincipal = triggeringPrincipal;
nsCOMPtr<nsIContentSecurityPolicy> csp;
handler->GetCSP(dragEvent, getter_AddRefs(csp));
loadURIOptions.mCsp = csp;
webnav->LoadURI(url, loadURIOptions);
}
}

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

@ -10,6 +10,7 @@
#include "mozilla/EventForwards.h"
class nsIContent;
class nsIContentSecurityPolicy;
class nsIDocShell;
class nsIInputStream;
class nsIRequest;
@ -42,6 +43,11 @@ class nsILinkHandler : public nsISupports {
* @param aIsTrusted false if the triggerer is an untrusted DOM event.
* @param aTriggeringPrincipal, if not passed explicitly we fall back to
* the document's principal.
* @param aCsp, the CSP to be used for the load, that is the CSP of the
* entity responsible for causing the load to occur. Most likely
* this is the CSP of the document that started the load. In case
* aCsp was not passed explicitly we fall back to using
* aContent's document's CSP if that document holds any.
*/
NS_IMETHOD OnLinkClick(nsIContent* aContent, nsIURI* aURI,
const nsAString& aTargetSpec,
@ -49,7 +55,8 @@ class nsILinkHandler : public nsISupports {
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
bool aIsUserTriggered, bool aIsTrusted,
nsIPrincipal* aTriggeringPrincipal) = 0;
nsIPrincipal* aTriggeringPrincipal,
nsIContentSecurityPolicy* aCsp) = 0;
/**
* Process a click on a link.
@ -70,6 +77,11 @@ class nsILinkHandler : public nsISupports {
* @param aRequest the request that was opened
* @param aTriggeringPrincipal, if not passed explicitly we fall back to
* the document's principal.
* @param aCsp, the CSP to be used for the load, that is the CSP of the
* entity responsible for causing the load to occur. Most likely
* this is the CSP of the document that started the load. In case
* aCsp was not passed explicitly we fall back to using
* aContent's document's CSP if that document holds any.
*/
NS_IMETHOD OnLinkClickSync(
nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec,
@ -77,7 +89,8 @@ class nsILinkHandler : public nsISupports {
nsIInputStream* aHeadersDataStream = 0, bool aNoOpenerImplied = false,
nsIDocShell** aDocShell = 0, nsIRequest** aRequest = 0,
bool aIsUserTriggered = false,
nsIPrincipal* aTriggeringPrincipal = nullptr) = 0;
nsIPrincipal* aTriggeringPrincipal = nullptr,
nsIContentSecurityPolicy* aCsp = nullptr) = 0;
/**
* Process a mouse-over a link.

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

@ -11,6 +11,7 @@
#include "nsISupports.idl"
interface nsIContentSecurityPolicy;
interface nsIMutableArray;
interface nsILayoutHistoryState;
interface nsIContentViewer;
@ -148,6 +149,13 @@ interface nsISHEntry : nsISupports
*/
[infallible] attribute nsIPrincipal principalToInherit;
/**
* Get the csp, if any, that was used for this document load. That
* is not the CSP that was applied to subresource loads within the
* document, but the CSP that was applied to this document load.
*/
[infallible] attribute nsIContentSecurityPolicy csp;
/**
* Get/set data associated with this history state via a pushState() call,
* serialized using structured clone.
@ -277,6 +285,7 @@ interface nsISHEntry : nsISupports
in unsigned long cacheKey, in ACString contentType,
in nsIPrincipal triggeringPrincipal,
in nsIPrincipal principalToInherit,
in nsIContentSecurityPolicy aCsp,
in nsIDRef docshellID,
in boolean dynamicCreation);

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

@ -8,6 +8,7 @@
#include <algorithm>
#include "nsIContentSecurityPolicy.h"
#include "nsDocShellEditorData.h"
#include "nsDocShellLoadTypes.h"
#include "nsIContentViewer.h"
@ -384,7 +385,8 @@ nsSHEntry::Create(nsIURI* aURI, const nsAString& aTitle,
nsILayoutHistoryState* aLayoutHistoryState,
uint32_t aCacheKey, const nsACString& aContentType,
nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aPrincipalToInherit, const nsID& aDocShellID,
nsIPrincipal* aPrincipalToInherit,
nsIContentSecurityPolicy* aCsp, const nsID& aDocShellID,
bool aDynamicCreation) {
MOZ_ASSERT(
aTriggeringPrincipal,
@ -401,6 +403,7 @@ nsSHEntry::Create(nsIURI* aURI, const nsAString& aTitle,
mShared->mContentType = aContentType;
mShared->mTriggeringPrincipal = aTriggeringPrincipal;
mShared->mPrincipalToInherit = aPrincipalToInherit;
mShared->mCsp = aCsp;
mShared->mDocShellID = aDocShellID;
mShared->mDynamicallyCreated = aDynamicCreation;
@ -495,6 +498,18 @@ nsSHEntry::SetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit) {
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetCsp(nsIContentSecurityPolicy** aCsp) {
NS_IF_ADDREF(*aCsp = mShared->mCsp);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetCsp(nsIContentSecurityPolicy* aCsp) {
mShared->mCsp = aCsp;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetBFCacheEntry(nsIBFCacheEntry** aEntry) {
NS_IF_ADDREF(*aEntry = mShared);

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

@ -70,6 +70,7 @@ already_AddRefed<nsSHEntryShared> nsSHEntryShared::Duplicate(
newEntry->mChildShells.AppendObjects(aEntry->mChildShells);
newEntry->mTriggeringPrincipal = aEntry->mTriggeringPrincipal;
newEntry->mPrincipalToInherit = aEntry->mPrincipalToInherit;
newEntry->mCsp = aEntry->mCsp;
newEntry->mContentType.Assign(aEntry->mContentType);
newEntry->mIsFrameNavigation = aEntry->mIsFrameNavigation;
newEntry->mSaveLayoutState = aEntry->mSaveLayoutState;

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

@ -80,6 +80,7 @@ class nsSHEntryShared final : public nsIBFCacheEntry,
nsCOMArray<nsIDocShellTreeItem> mChildShells;
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
nsCOMPtr<nsIPrincipal> mPrincipalToInherit;
nsCOMPtr<nsIContentSecurityPolicy> mCsp;
nsCString mContentType;
uint32_t mCacheKey;

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

@ -1496,6 +1496,8 @@ nsresult nsSHistory::InitiateLoad(nsISHEntry* aFrameEntry,
aFrameEntry->GetTriggeringPrincipal();
loadState->SetTriggeringPrincipal(triggeringPrincipal);
loadState->SetFirstParty(false);
nsCOMPtr<nsIContentSecurityPolicy> csp = aFrameEntry->GetCsp();
loadState->SetCsp(csp);
// Time to initiate a document load
return aFrameDS->LoadURI(loadState);

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

@ -200,6 +200,27 @@ ContentAreaDropListener.prototype =
},
getCSP: function(aEvent)
{
let sourceNode = aEvent.dataTransfer.mozSourceNode;
if (sourceNode &&
(sourceNode.localName !== "browser" ||
sourceNode.namespaceURI !== "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul")) {
// Use sourceNode's principal only if the sourceNode is not browser.
//
// If sourceNode is browser, the actual triggering principal may be
// differ than sourceNode's principal, since sourceNode's principal is
// top level document's one and the drag may be triggered from a frame
// with different principal.
if (sourceNode.nodePrincipal) {
// Currently we query the CSP from the nodePrincipal. After Bug 965637 we can
// query the CSP directly from the sourceNode.
return sourceNode.nodePrincipal.csp;
}
}
return null;
},
canDropLink: function(aEvent, aAllowSameDocument)
{
if (this._eventTargetIsDisabled(aEvent))

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

@ -151,6 +151,15 @@ already_AddRefed<nsDocShellLoadState> Location::CheckURL(
loadState->SetTriggeringPrincipal(triggeringPrincipal);
// Currently we query the CSP from the triggeringPrincipal, which is the
// doc->NodePrincipal() in case there is a doc. In that case we can query
// the CSP directly from the doc after Bug 965637. In case there is no doc,
// then we also do not need to query the CSP, because only documents can have
// a CSP attached.
nsCOMPtr<nsIContentSecurityPolicy> csp;
triggeringPrincipal->GetCsp(getter_AddRefs(csp));
loadState->SetCsp(csp);
if (sourceURI) {
nsCOMPtr<nsIReferrerInfo> referrerInfo =
new ReferrerInfo(sourceURI, referrerPolicy);

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

@ -5179,10 +5179,17 @@ void nsContentUtils::TriggerLink(nsIContent* aContent,
fileName.SetIsVoid(true); // No actionable download attribute was found.
}
// Currently we query the CSP from the triggeringPrincipal, which is
// aContent->NodePrincipal(). After Bug 965637 we can query the CSP
// directly from the doc instead (aContent->OwnerDoc()).
nsCOMPtr<nsIPrincipal> triggeringPrincipal = aContent->NodePrincipal();
nsCOMPtr<nsIContentSecurityPolicy> csp;
triggeringPrincipal->GetCsp(getter_AddRefs(csp));
handler->OnLinkClick(
aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec : EmptyString(),
fileName, nullptr, nullptr, EventStateManager::IsHandlingUserInput(),
aIsTrusted, aContent->NodePrincipal());
aIsTrusted, triggeringPrincipal, csp);
}
}
@ -9812,6 +9819,15 @@ nsContentUtils::LookupCustomElementDefinition(Document* aDoc, nsAtom* aNameAtom,
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
nsCOMPtr<nsIPrincipal> triggeringPrincipal = loadInfo->TriggeringPrincipal();
// Currently we query the CSP from the triggeringPrincipal within the
// loadInfo. After Bug 965637, we can query the CSP from the loadInfo, which
// internally queries the CSP from the Client.
nsCOMPtr<nsIContentSecurityPolicy> csp;
if (triggeringPrincipal) {
rv = triggeringPrincipal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, false);
}
// Get the channel's load flags, and use them to generate nsIWebNavigation
// load flags. We want to make sure to propagate the refresh and cache busting
// flags.
@ -9829,7 +9845,7 @@ nsContentUtils::LookupCustomElementDefinition(Document* aDoc, nsAtom* aNameAtom,
// Actually perform the cross process load
bool reloadSucceeded = false;
rv = wbc3->ReloadInFreshProcess(docShell, uri, referrer, triggeringPrincipal,
webnavLoadFlags, &reloadSucceeded);
webnavLoadFlags, csp, &reloadSucceeded);
NS_ENSURE_SUCCESS(rv, false);
return reloadSucceeded;

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

@ -396,6 +396,13 @@ nsresult nsFrameLoader::ReallyStartLoadingInternal() {
loadState->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
}
// Currently we query the CSP from the principal, but after
// Bug 1529877 we should query the CSP from within GetURL and
// store it as a member, similar to mTriggeringPrincipal.
nsCOMPtr<nsIContentSecurityPolicy> csp;
loadState->TriggeringPrincipal()->GetCsp(getter_AddRefs(csp));
loadState->SetCsp(csp);
nsCOMPtr<nsIURI> referrer;
nsAutoString srcdoc;

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

@ -4,6 +4,7 @@
#include "nsISupports.idl"
#include "nsIPrincipal.idl"
#include "nsIContentSecurityPolicy.idl"
webidl DragEvent;
webidl DataTransfer;
@ -105,4 +106,9 @@ interface nsIDroppedLinkHandler : nsISupports
* event and returns it.
*/
nsIPrincipal getTriggeringPrincipal(in DragEvent aEvent);
/**
* Given a drop event aEvent, determines the CSP for the event and returns it.
*/
nsIContentSecurityPolicy getCSP(in DragEvent aEvent);
};

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

@ -73,6 +73,19 @@ nsOpenURIInFrameParams::SetTriggeringPrincipal(
return NS_OK;
}
NS_IMETHODIMP
nsOpenURIInFrameParams::GetCsp(nsIContentSecurityPolicy** aCsp) {
NS_IF_ADDREF(*aCsp = mCsp);
return NS_OK;
}
NS_IMETHODIMP
nsOpenURIInFrameParams::SetCsp(nsIContentSecurityPolicy* aCsp) {
NS_ENSURE_TRUE(aCsp, NS_ERROR_INVALID_ARG);
mCsp = aCsp;
return NS_OK;
}
nsresult nsOpenURIInFrameParams::GetOpenerBrowser(Element** aOpenerBrowser) {
RefPtr<Element> owner = mOpenerBrowser;
owner.forget(aOpenerBrowser);

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

@ -31,4 +31,5 @@ class nsOpenURIInFrameParams final : public nsIOpenURIInFrameParams {
nsString mReferrer;
uint32_t mReferrerPolicy;
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
nsCOMPtr<nsIContentSecurityPolicy> mCsp;
};

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

@ -1848,6 +1848,8 @@ def addExternalIface(iface, nativeType=None, headerFile=None,
addExternalIface('Cookie', nativeType='nsICookie2',
headerFile='nsICookie2.h', notflattened=True)
addExternalIface('ContentSecurityPolicy', nativeType='nsIContentSecurityPolicy',
notflattened=True)
addExternalIface('HitRegionOptions', nativeType='nsISupports')
addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver')
addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)

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

@ -230,6 +230,16 @@ RefPtr<ClientOpPromise> ClientNavigateOpChild::DoNavigate(
nsCOMPtr<nsIReferrerInfo> referrerInfo =
new ReferrerInfo(doc->GetDocumentURI(), doc->GetReferrerPolicy());
loadState->SetTriggeringPrincipal(principal);
// Currently we query the CSP from the principal, which is the
// doc->NodePrincipal(). After Bug 965637 we can query the CSP
// from the doc directly.
if (principal) {
nsCOMPtr<nsIContentSecurityPolicy> csp;
principal->GetCsp(getter_AddRefs(csp));
loadState->SetCsp(csp);
}
loadState->SetReferrerInfo(referrerInfo);
loadState->SetLoadType(LOAD_STOP_CONTENT);
loadState->SetSourceDocShell(docShell);

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

@ -9,6 +9,7 @@ interface mozIDOMWindowProxy;
interface nsIDOMWindow;
interface nsIURI;
interface nsIPrincipal;
interface nsIContentSecurityPolicy;
webidl Element;
[scriptable, uuid(e774db14-79ac-4156-a7a3-aa3fd0a22c10)]
@ -18,6 +19,7 @@ interface nsIOpenURIInFrameParams : nsISupports
attribute unsigned long referrerPolicy;
readonly attribute boolean isPrivate;
attribute nsIPrincipal triggeringPrincipal;
attribute nsIContentSecurityPolicy csp;
// The browser or frame element in the parent process which holds the
// opener window in the content process. May be null.

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

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/CSPMessageUtils.h"
#include "nsISerializable.h"
#include "nsSerializationHelper.h"
namespace IPC {
void ParamTraits<nsIContentSecurityPolicy>::Write(
Message* aMsg, nsIContentSecurityPolicy* aParam) {
bool isNull = !aParam;
WriteParam(aMsg, isNull);
if (isNull) {
return;
}
nsCString cspString;
nsresult rv = NS_SerializeToString(aParam, cspString);
if (NS_FAILED(rv)) {
MOZ_CRASH("Unable to serialize csp.");
return;
}
WriteParam(aMsg, cspString);
}
bool ParamTraits<nsIContentSecurityPolicy>::Read(
const Message* aMsg, PickleIterator* aIter,
RefPtr<nsIContentSecurityPolicy>* aResult) {
bool isNull;
if (!ReadParam(aMsg, aIter, &isNull)) {
return false;
}
if (isNull) {
*aResult = nullptr;
return true;
}
nsCString cspString;
if (!ReadParam(aMsg, aIter, &cspString)) {
return false;
}
nsCOMPtr<nsISupports> iSupports;
nsresult rv = NS_DeserializeObject(cspString, getter_AddRefs(iSupports));
NS_ENSURE_SUCCESS(rv, false);
nsCOMPtr<nsIContentSecurityPolicy> csp = do_QueryInterface(iSupports);
NS_ENSURE_TRUE(csp, false);
*aResult = csp.forget();
return true;
}
} // namespace IPC

25
dom/ipc/CSPMessageUtils.h Normal file
Просмотреть файл

@ -0,0 +1,25 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_csp_message_utils_h__
#define mozilla_dom_csp_message_utils_h__
#include "ipc/IPCMessageUtils.h"
#include "nsCOMPtr.h"
#include "nsIContentSecurityPolicy.h"
namespace IPC {
template <>
struct ParamTraits<nsIContentSecurityPolicy> {
static void Write(Message* aMsg, nsIContentSecurityPolicy* aParam);
static bool Read(const Message* aMsg, PickleIterator* aIter,
RefPtr<nsIContentSecurityPolicy>* aResult);
};
} // namespace IPC
#endif // mozilla_dom_csp_message_utils_h__

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

@ -755,15 +755,13 @@ ContentChild::ProvideWindow(mozIDOMWindowProxy* aParent, uint32_t aChromeFlags,
aWindowIsNew, aReturn);
}
static nsresult GetCreateWindowParams(mozIDOMWindowProxy* aParent,
nsDocShellLoadState* aLoadState,
nsACString& aBaseURIString,
float* aFullZoom,
uint32_t* aReferrerPolicy,
nsIPrincipal** aTriggeringPrincipal) {
static nsresult GetCreateWindowParams(
mozIDOMWindowProxy* aParent, nsDocShellLoadState* aLoadState,
nsACString& aBaseURIString, float* aFullZoom, uint32_t* aReferrerPolicy,
nsIPrincipal** aTriggeringPrincipal, nsIContentSecurityPolicy** aCsp) {
*aFullZoom = 1.0f;
if (!aTriggeringPrincipal) {
NS_ERROR("aTriggeringPrincipal is null");
if (!aTriggeringPrincipal || !aCsp) {
NS_ERROR("aTriggeringPrincipal || aCsp is null");
return NS_ERROR_FAILURE;
}
auto* opener = nsPIDOMWindowOuter::From(aParent);
@ -776,6 +774,15 @@ static nsresult GetCreateWindowParams(mozIDOMWindowProxy* aParent,
nsCOMPtr<Document> doc = opener->GetDoc();
NS_ADDREF(*aTriggeringPrincipal = doc->NodePrincipal());
// Currently we query the CSP from the doc->NodePrincipal(). After
// Bug 965637 we can query the CSP from the doc directly.
nsCOMPtr<nsIContentSecurityPolicy> csp;
doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
if (csp) {
csp.forget(aCsp);
}
nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
if (!baseURI) {
NS_ERROR("Document didn't return a base URI");
@ -856,10 +863,11 @@ nsresult ContentChild::ProvideWindowCommon(
nsAutoCString baseURIString;
float fullZoom;
nsCOMPtr<nsIPrincipal> triggeringPrincipal;
nsCOMPtr<nsIContentSecurityPolicy> csp;
uint32_t referrerPolicy = mozilla::net::RP_Unset;
rv = GetCreateWindowParams(aParent, aLoadState, baseURIString, &fullZoom,
&referrerPolicy,
getter_AddRefs(triggeringPrincipal));
rv = GetCreateWindowParams(
aParent, aLoadState, baseURIString, &fullZoom, &referrerPolicy,
getter_AddRefs(triggeringPrincipal), getter_AddRefs(csp));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -869,7 +877,7 @@ nsresult ContentChild::ProvideWindowCommon(
Unused << SendCreateWindowInDifferentProcess(
aTabOpener, aChromeFlags, aCalledFromJS, aPositionSpecified,
aSizeSpecified, uriToLoad, features, baseURIString, fullZoom, name,
Principal(triggeringPrincipal), referrerPolicy);
Principal(triggeringPrincipal), csp, referrerPolicy);
// We return NS_ERROR_ABORT, so that the caller knows that we've abandoned
// the window open as far as it is concerned.
@ -1055,10 +1063,11 @@ nsresult ContentChild::ProvideWindowCommon(
nsAutoCString baseURIString;
float fullZoom;
nsCOMPtr<nsIPrincipal> triggeringPrincipal;
nsCOMPtr<nsIContentSecurityPolicy> csp;
uint32_t referrerPolicy = mozilla::net::RP_Unset;
rv = GetCreateWindowParams(aParent, aLoadState, baseURIString, &fullZoom,
&referrerPolicy,
getter_AddRefs(triggeringPrincipal));
rv = GetCreateWindowParams(
aParent, aLoadState, baseURIString, &fullZoom, &referrerPolicy,
getter_AddRefs(triggeringPrincipal), getter_AddRefs(csp));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -1073,7 +1082,8 @@ nsresult ContentChild::ProvideWindowCommon(
SendCreateWindow(aTabOpener, newChild, aChromeFlags, aCalledFromJS,
aPositionSpecified, aSizeSpecified, uriToLoad, features,
baseURIString, fullZoom, Principal(triggeringPrincipal),
referrerPolicy, std::move(resolve), std::move(reject));
csp, referrerPolicy, std::move(resolve),
std::move(reject));
}
// =======================

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

@ -132,6 +132,7 @@
#include "nsIClipboard.h"
#include "nsICookie.h"
#include "nsContentPermissionHelper.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIContentProcess.h"
#include "nsICycleCollectorListener.h"
#include "nsIDocShellTreeOwner.h"
@ -4606,7 +4607,7 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow(
uint64_t aNextTabParentId, const nsString& aName, nsresult& aResult,
nsCOMPtr<nsITabParent>& aNewTabParent, bool* aWindowIsNew,
int32_t& aOpenLocation, nsIPrincipal* aTriggeringPrincipal,
uint32_t aReferrerPolicy, bool aLoadURI)
uint32_t aReferrerPolicy, bool aLoadURI, nsIContentSecurityPolicy* aCsp)
{
// The content process should never be in charge of computing whether or
@ -4690,6 +4691,7 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow(
MOZ_ASSERT(aTriggeringPrincipal, "need a valid triggeringPrincipal");
params->SetTriggeringPrincipal(aTriggeringPrincipal);
params->SetReferrerPolicy(aReferrerPolicy);
params->SetCsp(aCsp);
RefPtr<Element> el;
@ -4806,8 +4808,8 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindow(
const bool& aPositionSpecified, const bool& aSizeSpecified,
const OptionalURIParams& aURIToLoad, const nsCString& aFeatures,
const nsCString& aBaseURI, const float& aFullZoom,
const IPC::Principal& aTriggeringPrincipal, const uint32_t& aReferrerPolicy,
CreateWindowResolver&& aResolve) {
const IPC::Principal& aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp,
const uint32_t& aReferrerPolicy, CreateWindowResolver&& aResolve) {
nsresult rv = NS_OK;
CreatedWindowInfo cwi;
@ -4853,7 +4855,7 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindow(
aPositionSpecified, aSizeSpecified, uriToLoad, aFeatures, aBaseURI,
aFullZoom, nextTabParentId, VoidString(), rv, newRemoteTab,
&cwi.windowOpened(), openLocation, aTriggeringPrincipal, aReferrerPolicy,
/* aLoadUri = */ false);
/* aLoadUri = */ false, aCsp);
if (!ipcResult) {
return ipcResult;
}
@ -4887,12 +4889,13 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindowInDifferentProcess(
const bool& aSizeSpecified, const OptionalURIParams& aURIToLoad,
const nsCString& aFeatures, const nsCString& aBaseURI,
const float& aFullZoom, const nsString& aName,
const IPC::Principal& aTriggeringPrincipal,
const IPC::Principal& aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp,
const uint32_t& aReferrerPolicy) {
nsCOMPtr<nsITabParent> newRemoteTab;
bool windowIsNew;
nsCOMPtr<nsIURI> uriToLoad = DeserializeURI(aURIToLoad);
int32_t openLocation = nsIBrowserDOMWindow::OPEN_NEWWINDOW;
nsresult rv;
mozilla::ipc::IPCResult ipcResult = CommonCreateWindow(
aThisTab, /* aSetOpener = */ false, aChromeFlags, aCalledFromJS,
@ -4900,7 +4903,7 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindowInDifferentProcess(
aFullZoom,
/* aNextTabParentId = */ 0, aName, rv, newRemoteTab, &windowIsNew,
openLocation, aTriggeringPrincipal, aReferrerPolicy,
/* aLoadUri = */ true);
/* aLoadUri = */ true, aCsp);
if (!ipcResult) {
return ipcResult;
}

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

@ -519,7 +519,8 @@ class ContentParent final : public PContentParent,
const OptionalURIParams& aURIToLoad, const nsCString& aFeatures,
const nsCString& aBaseURI, const float& aFullZoom,
const IPC::Principal& aTriggeringPrincipal,
const uint32_t& aReferrerPolicy, CreateWindowResolver&& aResolve);
nsIContentSecurityPolicy* aCsp, const uint32_t& aReferrerPolicy,
CreateWindowResolver&& aResolve);
mozilla::ipc::IPCResult RecvCreateWindowInDifferentProcess(
PBrowserParent* aThisTab, const uint32_t& aChromeFlags,
@ -528,7 +529,7 @@ class ContentParent final : public PContentParent,
const nsCString& aFeatures, const nsCString& aBaseURI,
const float& aFullZoom, const nsString& aName,
const IPC::Principal& aTriggeringPrincipal,
const uint32_t& aReferrerPolicy);
nsIContentSecurityPolicy* aCsp, const uint32_t& aReferrerPolicy);
static void BroadcastBlobURLRegistration(
const nsACString& aURI, BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal,
@ -696,7 +697,7 @@ class ContentParent final : public PContentParent,
nsresult& aResult, nsCOMPtr<nsITabParent>& aNewTabParent,
bool* aWindowIsNew, int32_t& aOpenLocation,
nsIPrincipal* aTriggeringPrincipal, uint32_t aReferrerPolicy,
bool aLoadUri);
bool aLoadUri, nsIContentSecurityPolicy* aCsp);
FORWARD_SHMEM_ALLOCATOR_TO(PContentParent)

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

@ -29,6 +29,7 @@ using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
using refcounted class nsIPrincipal from "mozilla/dom/PermissionMessageUtils.h";
using refcounted class mozilla::dom::BrowsingContext from "mozilla/dom/BrowsingContext.h";
using refcounted class nsIURI from "mozilla/ipc/URIUtils.h";
using refcounted class nsIContentSecurityPolicy from "mozilla/dom/CSPMessageUtils.h";
namespace mozilla {
namespace dom {
@ -219,6 +220,13 @@ struct DocShellLoadStateInit
nsCString TypeHint;
nsString FileName;
bool IsFromProcessingFrameAttributes;
// The Content Security Policy of the load, that is, the CSP of the entity
// responsible for causing the load to occur. Most likely this is the CSP
// of the document that started the load. In case the entity starting the
// load did not use a CSP, then Csp can be null. Please note that this is
// also the CSP that will be applied to the load in case the load
// encounters a server side redirect.
nsIContentSecurityPolicy Csp;
// Fields missing due to lack of need or serialization
// nsCOMPtr<nsISHEntry> mSHEntry;
// nsCOMPtr<nsIDocShell> mSourceDocShell;

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

@ -4,7 +4,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsMemoryReporterManager.h"
#include "MemoryReportRequest.h"
#include "mozilla/ipc/FileDescriptorUtils.h"
namespace mozilla {
namespace dom {

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

@ -1138,6 +1138,7 @@ parent:
nsCString aBaseURI,
float aFullZoom,
Principal aTriggeringPrincipal,
nsIContentSecurityPolicy aCsp,
uint32_t aReferrerPolicy)
returns (CreatedWindowInfo window);
@ -1153,6 +1154,7 @@ parent:
float aFullZoom,
nsString aName,
Principal aTriggeringPrincipal,
nsIContentSecurityPolicy aCsp,
uint32_t aReferrerPolicy);
/**

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

@ -38,6 +38,7 @@ EXPORTS.mozilla.dom += [
'ContentProcess.h',
'ContentProcessManager.h',
'CPOWManagerGetter.h',
'CSPMessageUtils.h',
'DocShellMessageUtils.h',
'FilePickerParent.h',
'JSWindowActorChild.h',
@ -75,6 +76,7 @@ UNIFIED_SOURCES += [
'ContentParent.cpp',
'ContentProcess.cpp',
'ContentProcessManager.cpp',
'CSPMessageUtils.cpp',
'DocShellMessageUtils.cpp',
'FilePickerParent.cpp',
'JSWindowActorChild.cpp',

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

@ -443,10 +443,15 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(
NullPrincipal::CreateWithInheritedAttributes(content->NodePrincipal());
}
// Currently we query the CSP from the NodePrincipal. After Bug 965637
// we can query the CSP from the doc directly (content->OwerDoc()).
nsCOMPtr<nsIContentSecurityPolicy> csp;
content->NodePrincipal()->GetCsp(getter_AddRefs(csp));
rv = lh->OnLinkClick(content, uri, unitarget, VoidString(), aPostStream,
headersDataStream,
/* isUserTriggered */ false,
/* isTrusted */ true, triggeringPrincipal);
/* isTrusted */ true, triggeringPrincipal, csp);
return rv;
}

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

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
interface ContentSecurityPolicy;
interface Principal;
interface URI;
interface InputStream;
@ -17,6 +18,15 @@ dictionary LoadURIOptions {
*/
Principal? triggeringPrincipal = null;
/**
* The CSP to be used for the load. That is *not* the CSP that will
* be applied to subresource loads within that document but the CSP
* for the document load itself. E.g. if that CSP includes
* upgrade-insecure-requests, then the new top-level load will
* be upgraded to HTTPS.
*/
ContentSecurityPolicy? csp = null;
/**
* Flags modifying load behaviour. This parameter is a bitwise
* combination of the load flags defined in nsIWebNavigation.idl.

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

@ -9,6 +9,7 @@ interface nsIDocShell;
interface nsIInputStream;
interface nsIRunnable;
interface nsIPrincipal;
interface nsIContentSecurityPolicy;
webidl Node;
@ -52,12 +53,16 @@ interface nsIWebBrowserChrome3 : nsIWebBrowserChrome2
* boundaries.
* @param aTriggeringPrincipal
* The principal that initiated the load of aURI.
* @param aCsp
* The CSP to be used for that load. That is the CSP that e.g. upgrades
* the load to HTTPS in case upgrade-insecure-requests is set.
*/
bool shouldLoadURI(in nsIDocShell aDocShell,
in nsIURI aURI,
in nsIURI aReferrer,
in boolean aHasPostData,
in nsIPrincipal aTriggeringPrincipal);
bool shouldLoadURI(in nsIDocShell aDocShell,
in nsIURI aURI,
in nsIURI aReferrer,
in boolean aHasPostData,
in nsIPrincipal aTriggeringPrincipal,
in nsIContentSecurityPolicy aCsp);
bool shouldLoadURIInThisProcess(in nsIURI aURI);
@ -67,10 +72,14 @@ interface nsIWebBrowserChrome3 : nsIWebBrowserChrome2
*
* @param aDocShell
* The docshell performing the load.
* @param aCsp
* The CSP to be used for that load. That is the CSP that e.g. upgrades
* the load to HTTPS in case upgrade-insecure-requests is set.
*/
bool reloadInFreshProcess(in nsIDocShell aDocShell,
in nsIURI aURI,
in nsIURI aReferrer,
in nsIPrincipal aTriggeringPrincipal,
in uint32_t aLoadFlags);
in uint32_t aLoadFlags,
in nsIContentSecurityPolicy aCsp);
};

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

@ -1084,6 +1084,15 @@ nsresult nsWindowWatcher::OpenWindowInternal(
}
}
// Currently we query the CSP from the subjectPrincipal. After Bug 965637
// we should query the CSP from the doc, similar to the referrerInfo above.
if (subjectPrincipal && loadState) {
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = subjectPrincipal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
loadState->SetCsp(csp);
}
if (isNewToplevelWindow) {
// Notify observers that the window is open and ready.
// The window has not yet started to load a document.

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

@ -362,7 +362,8 @@ NS_IMETHODIMP nsContentTreeOwner::OnBeforeLinkTraversal(
NS_IMETHODIMP nsContentTreeOwner::ShouldLoadURI(
nsIDocShell* aDocShell, nsIURI* aURI, nsIURI* aReferrer, bool aHasPostData,
nsIPrincipal* aTriggeringPrincipal, bool* _retval) {
nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp,
bool* _retval) {
NS_ENSURE_STATE(mXULWindow);
nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow;
@ -371,7 +372,7 @@ NS_IMETHODIMP nsContentTreeOwner::ShouldLoadURI(
if (xulBrowserWindow)
return xulBrowserWindow->ShouldLoadURI(aDocShell, aURI, aReferrer,
aHasPostData, aTriggeringPrincipal,
_retval);
aCsp, _retval);
*_retval = true;
return NS_OK;
@ -386,7 +387,8 @@ NS_IMETHODIMP nsContentTreeOwner::ShouldLoadURIInThisProcess(nsIURI* aURI,
NS_IMETHODIMP nsContentTreeOwner::ReloadInFreshProcess(
nsIDocShell* aDocShell, nsIURI* aURI, nsIURI* aReferrer,
nsIPrincipal* aTriggeringPrincipal, uint32_t aLoadFlags, bool* aRetVal) {
nsIPrincipal* aTriggeringPrincipal, uint32_t aLoadFlags,
nsIContentSecurityPolicy* aCsp, bool* aRetVal) {
NS_WARNING("Cannot reload in fresh process from a nsContentTreeOwner!");
*aRetVal = false;
return NS_OK;

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

@ -14,6 +14,7 @@ interface nsIDocShell;
interface nsITabParent;
interface nsIPrincipal;
interface mozIDOMWindowProxy;
interface nsIContentSecurityPolicy;
webidl Element;
webidl Node;
@ -61,12 +62,16 @@ interface nsIXULBrowserWindow : nsISupports
* boundaries.
* @param aTriggeringPrincipal
* The principal that initiated the load of aURI.
* @param aCsp
* The CSP to be used for that load. That is the CSP that e.g. upgrades
* the load to HTTPS in case upgrade-insecure-requests is set
*/
bool shouldLoadURI(in nsIDocShell aDocShell,
in nsIURI aURI,
in nsIURI aReferrer,
in boolean aHasPostData,
in nsIPrincipal aTriggeringPrincipal);
in nsIPrincipal aTriggeringPrincipal,
in nsIContentSecurityPolicy aCsp);
/**
* Show/hide a tooltip (when the user mouses over a link, say).
*/