Bug 1544863: Explicitly pass csp to createContentWindow(). r=Gijs,baku

Differential Revision: https://phabricator.services.mozilla.com/D27871

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Christoph Kerschbaumer 2019-04-23 14:37:40 +00:00
parent 07e5bfd27e
commit 42672fde72
12 changed files with 95 additions and 30 deletions

View File

@ -5691,21 +5691,21 @@ nsBrowserAccess.prototype = {
return browser;
},
createContentWindow(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
createContentWindow(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal, aCsp) {
return this.getContentWindowOrOpenURI(null, aOpener, aWhere, aFlags,
aTriggeringPrincipal);
aTriggeringPrincipal, aCsp);
},
openURI(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
openURI(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal, aCsp) {
if (!aURI) {
Cu.reportError("openURI should only be called with a valid URI");
throw Cr.NS_ERROR_FAILURE;
}
return this.getContentWindowOrOpenURI(aURI, aOpener, aWhere, aFlags,
aTriggeringPrincipal);
aTriggeringPrincipal, aCsp);
},
getContentWindowOrOpenURI(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
getContentWindowOrOpenURI(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal, aCsp) {
// This function should only ever be called if we're opening a URI
// from a non-remote browser window (via nsContentTreeOwner).
if (aOpener && Cu.isCrossProcessWrapper(aOpener)) {
@ -5714,6 +5714,19 @@ nsBrowserAccess.prototype = {
throw Cr.NS_ERROR_FAILURE;
}
// After Bug 965637 we can remove that Error because the CSP will not
// hang off the Principal anymore. Please note that the SystemPrincipal
// can not hold a CSP!
if (AppConstants.EARLY_BETA_OR_EARLIER) {
// Please note that the backend will still query the CSP from the Principal in
// release versions of Firefox. We use this error just to annotate all the
// callsites to explicitly pass a CSP before we can remove the CSP from
// the Principal within Bug 965637.
if (!aTriggeringPrincipal.isSystemPrincipal && aTriggeringPrincipal.csp && !aCsp) {
throw new Error("If Principal has CSP then we need an explicit CSP");
}
}
var newWindow = null;
var isExternal = !!(aFlags & Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
@ -5741,8 +5754,6 @@ nsBrowserAccess.prototype = {
if (aOpener && aOpener.document) {
referrerInfo.referrerPolicy = aOpener.document.referrerPolicy;
}
// Bug 965637, query the CSP from the doc instead of the Principal
let csp = aTriggeringPrincipal.csp;
let isPrivate = aOpener
? PrivateBrowsingUtils.isContentWindowPrivate(aOpener)
: PrivateBrowsingUtils.isWindowPrivate(window);
@ -5761,7 +5772,8 @@ nsBrowserAccess.prototype = {
try {
newWindow = openDialog(AppConstants.BROWSER_CHROME_URL, "_blank", features,
// window.arguments
url, null, null, null, null, null, null, aTriggeringPrincipal);
url, null, null, null, null, null, null, aTriggeringPrincipal,
null, aCsp);
} catch (ex) {
Cu.reportError(ex);
}
@ -5782,7 +5794,7 @@ nsBrowserAccess.prototype = {
isPrivate, isExternal,
forceNotRemote, userContextId,
openerWindow, null, aTriggeringPrincipal,
0, "", csp);
0, "", aCsp);
if (browser)
newWindow = browser.contentWindow;
break;
@ -5794,7 +5806,7 @@ nsBrowserAccess.prototype = {
Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
gBrowser.loadURI(aURI.spec, {
triggeringPrincipal: aTriggeringPrincipal,
csp,
csp: aCsp,
flags: loadflags,
referrerInfo,
});

View File

@ -14,6 +14,7 @@
#include "mozilla/dom/ServiceWorkerDescriptor.h"
#include "mozilla/dom/ServiceWorkerManager.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/SystemGroup.h"
#include "nsIGlobalObject.h"
#include "nsString.h"
@ -217,9 +218,12 @@ already_AddRefed<Promise> Clients::OpenWindow(const nsAString& aURL,
}
const PrincipalInfo& principalInfo = workerPrivate->GetPrincipalInfo();
const nsTArray<mozilla::ipc::ContentSecurityPolicy>& cspInfos =
workerPrivate->GetCSPInfos();
nsCString baseURL = workerPrivate->GetLocationInfo().mHref;
ClientOpenWindowArgs args(principalInfo, NS_ConvertUTF16toUTF8(aURL),
baseURL);
ClientOpenWindowArgs args(principalInfo, cspInfos,
NS_ConvertUTF16toUTF8(aURL), baseURL);
nsCOMPtr<nsIGlobalObject> global = mGlobal;

View File

@ -108,6 +108,7 @@ struct ClientGetInfoAndStateArgs
struct ClientOpenWindowArgs
{
PrincipalInfo principalInfo;
ContentSecurityPolicy[] cspInfos;
nsCString url;
nsCString baseURL;
};

View File

@ -22,6 +22,8 @@
#include "nsPIDOMWindow.h"
#include "nsPIWindowWatcher.h"
#include "mozilla/dom/nsCSPContext.h"
#ifdef MOZ_WIDGET_ANDROID
# include "FennecJNIWrappers.h"
#endif
@ -169,6 +171,32 @@ nsresult OpenWindow(const ClientOpenWindowArgs& aArgs,
PrincipalInfoToPrincipal(aArgs.principalInfo());
MOZ_DIAGNOSTIC_ASSERT(principal);
// XXXckerschb: After Bug 965637 we have the CSP stored in the client which
// allows to clean that part up.
nsCOMPtr<nsIContentSecurityPolicy> csp;
if (!aArgs.cspInfos().IsEmpty()) {
csp = new nsCSPContext();
csp->SetRequestContext(nullptr, principal);
for (const mozilla::ipc::ContentSecurityPolicy& policy : aArgs.cspInfos()) {
nsresult rv = csp->AppendPolicy(policy.policy(), policy.reportOnlyFlag(),
policy.deliveredViaMetaTagFlag());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
}
#ifdef DEBUG
if (principal && !principal->GetIsNullPrincipal()) {
// We do not serialize CSP for NullPricnipals as of now, for all others
// we make sure the CSP within the Principal and the explicit CSP are
// identical. After Bug 965637 we can remove that assertion anyway.
nsCOMPtr<nsIContentSecurityPolicy> principalCSP;
principal->GetCsp(getter_AddRefs(principalCSP));
MOZ_ASSERT(nsCSPContext::Equals(csp, principalCSP));
}
#endif
// [[6.1 Open Window]]
if (XRE_IsContentProcess()) {
// Let's create a sandbox in order to have a valid JSContext and correctly
@ -247,7 +275,7 @@ nsresult OpenWindow(const ClientOpenWindowArgs& aArgs,
nsCOMPtr<mozIDOMWindowProxy> win;
rv = bwin->OpenURI(uri, nullptr, nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW,
nsIBrowserDOMWindow::OPEN_NEW, principal,
nsIBrowserDOMWindow::OPEN_NEW, principal, csp,
getter_AddRefs(win));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;

View File

@ -106,12 +106,14 @@ interface nsIBrowserDOMWindow : nsISupports
* aWhere == OPEN_DEFAULTWINDOW.
* @param aTriggeringPrincipal the principal that would trigger the potential
* load of aURI.
* @param aCsp the CSP to use (if any) for the new window.
* @return the window into which the URI would have been opened.
*/
mozIDOMWindowProxy
createContentWindow(in nsIURI aURI, in mozIDOMWindowProxy aOpener,
in short aWhere, in long aFlags,
in nsIPrincipal aTriggeringPrincipal);
in nsIPrincipal aTriggeringPrincipal,
[optional] in nsIContentSecurityPolicy aCsp);
/**
* As above, but return the nsFrameLoaderOwner for the new window. Value is
@ -139,11 +141,13 @@ interface nsIBrowserDOMWindow : nsISupports
* OPEN_EXTERNAL/OPEN_NEW flag is only used when
* aWhere == OPEN_DEFAULTWINDOW.
* @param aTriggeringPrincipal the principal that triggered the load of aURI.
* @param aCsp the CSP to be applied to the new load.
* @return the window into which the URI was opened.
*/
mozIDOMWindowProxy
openURI(in nsIURI aURI, in mozIDOMWindowProxy aOpener,
in short aWhere, in long aFlags, in nsIPrincipal aTriggeringPrincipal);
in short aWhere, in long aFlags, in nsIPrincipal aTriggeringPrincipal,
[optional] in nsIContentSecurityPolicy aCsp);
/**
* As above, but return the nsFrameLoaderOwner for the new window. Value is

View File

@ -4849,7 +4849,7 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow(
nsCOMPtr<mozIDOMWindowProxy> win;
aResult = newBrowserDOMWin->OpenURI(
aURIToLoad, openerWindow, nsIBrowserDOMWindow::OPEN_CURRENTWINDOW,
nsIBrowserDOMWindow::OPEN_NEW, aTriggeringPrincipal,
nsIBrowserDOMWindow::OPEN_NEW, aTriggeringPrincipal, aCsp,
getter_AddRefs(win));
}

View File

@ -105,8 +105,12 @@ nsresult WorkerLoadInfo::SetPrincipalsOnMainThread(
nsresult rv = aPrincipal->GetCsp(getter_AddRefs(mCSP));
NS_ENSURE_SUCCESS(rv, rv);
mCSPInfos.Clear();
if (mCSP) {
mCSP->GetAllowsEval(&mReportCSPViolations, &mEvalAllowed);
rv = PopulateContentSecurityPolicies(mCSP, mCSPInfos);
NS_ENSURE_SUCCESS(rv, rv);
} else {
mEvalAllowed = true;
mReportCSPViolations = false;

View File

@ -31,6 +31,7 @@ class nsPIDOMWindowInner;
namespace mozilla {
namespace ipc {
class ContentSecurityPolicy;
class PrincipalInfo;
} // namespace ipc
@ -96,6 +97,8 @@ struct WorkerLoadInfoData {
nsCString mDomain;
nsString mOrigin; // Derived from mPrincipal; can be used on worker thread.
nsTArray<mozilla::ipc::ContentSecurityPolicy> mCSPInfos;
nsString mServiceWorkerCacheName;
Maybe<ServiceWorkerDescriptor> mServiceWorkerDescriptor;
Maybe<ServiceWorkerRegistrationDescriptor>

View File

@ -685,6 +685,14 @@ class WorkerPrivate : public RelativeTimeline {
return *mLoadInfo.mPrincipalInfo;
}
// The CSPInfo returned is the same CSP as stored inside the Principal
// returned from GetPrincipalInfo. Please note that after Bug 965637
// we do not have a a CSP stored inside the Principal anymore which
// allows us to clean that part up.
const nsTArray<mozilla::ipc::ContentSecurityPolicy>& GetCSPInfos() const {
return mLoadInfo.mCSPInfos;
}
const mozilla::ipc::PrincipalInfo& GetEffectiveStoragePrincipalInfo() const {
return *mLoadInfo.mStoragePrincipalInfo;
}

View File

@ -3393,7 +3393,7 @@ function nsBrowserAccess() {
nsBrowserAccess.prototype = {
QueryInterface: ChromeUtils.generateQI([Ci.nsIBrowserDOMWindow]),
_getBrowser: function _getBrowser(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
_getBrowser: function _getBrowser(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal, aCsp) {
let isExternal = !!(aFlags & Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
if (isExternal && aURI && aURI.schemeIs("chrome"))
return null;
@ -3463,7 +3463,8 @@ nsBrowserAccess.prototype = {
selected: true,
isPrivate: isPrivate,
pinned: pinned,
triggeringPrincipal: aTriggeringPrincipal});
triggeringPrincipal: aTriggeringPrincipal,
csp: aCsp });
return tab.browser;
}
@ -3482,20 +3483,20 @@ nsBrowserAccess.prototype = {
},
openURI: function browser_openURI(aURI, aOpener, aWhere, aFlags,
aTriggeringPrincipal) {
aTriggeringPrincipal, aCsp) {
if (!aURI) {
throw "Can't open an empty uri";
}
let browser = this._getBrowser(aURI, aOpener, aWhere, aFlags,
aTriggeringPrincipal);
aTriggeringPrincipal, aCsp);
return browser && browser.contentWindow;
},
createContentWindow: function browser_createContentWindow(
aURI, aOpener, aWhere, aFlags,
aTriggeringPrincipal) {
aTriggeringPrincipal, aCsp) {
let browser = this._getBrowser(null, aOpener, aWhere, aFlags,
aTriggeringPrincipal);
aTriggeringPrincipal, aCsp);
return browser && browser.contentWindow;
},

View File

@ -217,7 +217,7 @@ class GeckoViewNavigation extends GeckoViewModule {
}
// nsIBrowserDOMWindow.
createContentWindow(aUri, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
createContentWindow(aUri, aOpener, aWhere, aFlags, aTriggeringPrincipal, aCsp) {
debug `createContentWindow: uri=${aUri && aUri.spec}
where=${aWhere} flags=${aFlags}`;
@ -262,7 +262,7 @@ class GeckoViewNavigation extends GeckoViewModule {
return browser;
}
handleOpenUri(aUri, aOpener, aWhere, aFlags, aTriggeringPrincipal,
handleOpenUri(aUri, aOpener, aWhere, aFlags, aTriggeringPrincipal, aCsp,
aNextTabParentId) {
debug `handleOpenUri: uri=${aUri && aUri.spec}
where=${aWhere} flags=${aFlags}`;
@ -285,21 +285,21 @@ class GeckoViewNavigation extends GeckoViewModule {
// Should we throw?
return null;
}
browser.loadURI(aUri.spec, null, null, null, null, aTriggeringPrincipal);
browser.loadURI(aUri.spec, null, null, null, null, aTriggeringPrincipal, aCsp);
return browser;
}
// nsIBrowserDOMWindow.
openURI(aUri, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
openURI(aUri, aOpener, aWhere, aFlags, aTriggeringPrincipal, aCsp) {
const browser = this.handleOpenUri(aUri, aOpener, aWhere, aFlags,
aTriggeringPrincipal, null);
aTriggeringPrincipal, aCsp, null);
return browser && browser.contentWindow;
}
// nsIBrowserDOMWindow.
openURIInFrame(aUri, aParams, aWhere, aFlags, aNextTabParentId, aName) {
const browser = this.handleOpenUri(aUri, null, aWhere, aFlags,
aParams.triggeringPrincipal,
aParams.triggeringPrincipal, aParams.csp,
aNextTabParentId);
return browser;
}

View File

@ -806,8 +806,8 @@ nsContentTreeOwner::ProvideWindow(
// ourselves.
RefPtr<NullPrincipal> nullPrincipal =
NullPrincipal::CreateWithoutOriginAttributes();
return browserDOMWin->CreateContentWindow(aURI, aParent, openLocation,
flags, nullPrincipal, aReturn);
return browserDOMWin->CreateContentWindow(
aURI, aParent, openLocation, flags, nullPrincipal, nullptr, aReturn);
}
}