Merge f-t and m-i to m-c, a=merge

This commit is contained in:
Phil Ringnalda 2015-11-15 09:11:43 -08:00
commit c461374e8e
114 changed files with 1291 additions and 415 deletions

View File

@ -317,15 +317,31 @@ BasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
NS_IMETHODIMP
BasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
{
// If CSP was already set, it should not be destroyed! Instead, it should
// get set anew when a new principal is created.
if (mCSP)
if (mCSP) {
return NS_ERROR_ALREADY_INITIALIZED;
}
mCSP = aCsp;
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP)
{
NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP)
{
if (mPreloadCSP) {
return NS_ERROR_ALREADY_INITIALIZED;
}
mPreloadCSP = aPreloadCSP;
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::GetCspJSON(nsAString& outCSPinJSON)
{

View File

@ -146,6 +146,8 @@ public:
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) final;
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
NS_IMETHOD SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP) override;
NS_IMETHOD GetCspJSON(nsAString& outCSPinJSON) override;
NS_IMETHOD GetIsNullPrincipal(bool* aResult) override;
NS_IMETHOD GetIsCodebasePrincipal(bool* aResult) override;
@ -200,6 +202,7 @@ protected:
bool AddonAllowsLoad(nsIURI* aURI);
nsCOMPtr<nsIContentSecurityPolicy> mCSP;
nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
OriginAttributes mOriginAttributes;
};

View File

@ -20,7 +20,7 @@ interface nsIContentSecurityPolicy;
[ptr] native JSPrincipals(JSPrincipals);
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
[scriptable, builtinclass, uuid(86e5fd29-dccb-4547-8918-f224005479a0)]
[scriptable, builtinclass, uuid(188fc4a2-3157-4956-a7a2-d674991770da)]
interface nsIPrincipal : nsISerializable
{
/**
@ -132,9 +132,29 @@ interface nsIPrincipal : nsISerializable
/**
* A Content Security Policy associated with this principal.
*
* Please note that if a csp was already set on the
* principal, then it should not be destroyed! Instead, the
* current csp should be quried and extended by
* calling AppendPolicy() on it.
*/
[noscript] attribute nsIContentSecurityPolicy csp;
/**
* A speculative Content Security Policy associated with this
* principal. Set during speculative loading (preloading) and
* used *only* for preloads.
*
* If you want to query the CSP associated with that principal,
* then this is *not* what you want. Instead query 'csp'.
*
* Please note that if a preloadCSP was already set on the
* principal, then it should not be destroyed! Instead, the
* current preloadCSP should be quried and extended by
* calling AppendPolicy() on it.
*/
[noscript] attribute nsIContentSecurityPolicy preloadCsp;
/**
* The CSP of the principal in JSON notation.
* Note, that the CSP itself is not exposed to JS, but script

View File

@ -72,7 +72,21 @@ nsSystemPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
NS_IMETHODIMP
nsSystemPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
{
// CSP on a null principal makes no sense
// CSP on a system principal makes no sense
return NS_OK;
}
NS_IMETHODIMP
nsSystemPrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP)
{
*aPreloadCSP = nullptr;
return NS_OK;
}
NS_IMETHODIMP
nsSystemPrincipal::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP)
{
// CSP on a system principal makes no sense
return NS_OK;
}

View File

@ -31,6 +31,8 @@ public:
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
NS_IMETHOD SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
nsresult GetOriginInternal(nsACString& aOrigin) override;

View File

@ -8042,6 +8042,18 @@ nsContentUtils::InternalContentPolicyTypeToExternalOrWorker(nsContentPolicyType
}
}
/* static */
bool
nsContentUtils::IsPreloadType(nsContentPolicyType aType)
{
if (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD) {
return true;
}
return false;
}
/* static */
nsContentPolicyType
nsContentUtils::InternalContentPolicyTypeToExternalOrCSPInternal(nsContentPolicyType aType)

View File

@ -1031,6 +1031,14 @@ public:
*/
static nsContentPolicyType InternalContentPolicyTypeToExternalOrWorker(nsContentPolicyType aType);
/**
* Returns true if the content policy type is any of:
* * TYPE_INTERNAL_SCRIPT_PRELOAD
* * TYPE_INTERNAL_IMAGE_PRELOAD
* * TYPE_INTERNAL_STYLESHEET_PRELOAD
*/
static bool IsPreloadType(nsContentPolicyType aType);
/**
* Quick helper to determine whether there are any mutation listeners
* of a given type that apply to this content or any of its ancestors.

View File

@ -1441,6 +1441,7 @@ nsIDocument::nsIDocument()
mReferrerPolicySet(false),
mReferrerPolicy(mozilla::net::RP_Default),
mUpgradeInsecureRequests(false),
mUpgradeInsecurePreloads(false),
mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
mNodeInfoManager(nullptr),
mCompatMode(eCompatibility_FullStandards),
@ -2574,6 +2575,8 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
if (sameTypeParent) {
mUpgradeInsecureRequests =
sameTypeParent->GetDocument()->GetUpgradeInsecureRequests();
mUpgradeInsecurePreloads =
sameTypeParent->GetDocument()->GetUpgradeInsecurePreloads();
}
}
@ -2615,7 +2618,7 @@ AppendCSPFromHeader(nsIContentSecurityPolicy* csp,
nsCharSeparatedTokenizer tokenizer(aHeaderValue, ',');
while (tokenizer.hasMoreTokens()) {
const nsSubstring& policy = tokenizer.nextToken();
rv = csp->AppendPolicy(policy, aReportOnly);
rv = csp->AppendPolicy(policy, aReportOnly, false);
NS_ENSURE_SUCCESS(rv, rv);
{
MOZ_LOG(gCspPRLog, LogLevel::Debug,
@ -2653,6 +2656,58 @@ nsDocument::IsLoopDocument(nsIChannel *aChannel)
return isLoop;
}
void
nsDocument::ApplySettingsFromCSP(bool aSpeculative)
{
nsresult rv = NS_OK;
if (!aSpeculative) {
// 1) apply settings from regular CSP
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS_VOID(rv);
if (csp) {
// Set up any Referrer Policy specified by CSP
bool hasReferrerPolicy = false;
uint32_t referrerPolicy = mozilla::net::RP_Default;
rv = csp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
NS_ENSURE_SUCCESS_VOID(rv);
if (hasReferrerPolicy) {
mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
mReferrerPolicySet = true;
}
// Set up 'upgrade-insecure-requests' if not already inherited
// from the parent context or set by any other CSP.
if (!mUpgradeInsecureRequests) {
rv = csp->GetUpgradeInsecureRequests(&mUpgradeInsecureRequests);
NS_ENSURE_SUCCESS_VOID(rv);
}
}
return;
}
// 2) apply settings from speculative csp
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
rv = NodePrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
if (preloadCsp) {
// Set up any Referrer Policy specified by CSP
bool hasReferrerPolicy = false;
uint32_t referrerPolicy = mozilla::net::RP_Default;
rv = preloadCsp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
NS_ENSURE_SUCCESS_VOID(rv);
if (hasReferrerPolicy) {
// please note that referrer policy spec defines that the latest
// policy awlays wins, hence we can safely overwrite the policy here.
mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
mReferrerPolicySet = true;
}
if (!mUpgradeInsecurePreloads) {
rv = preloadCsp->GetUpgradeInsecureRequests(&mUpgradeInsecurePreloads);
NS_ENSURE_SUCCESS_VOID(rv);
}
}
}
nsresult
nsDocument::InitCSP(nsIChannel* aChannel)
{
@ -2768,12 +2823,12 @@ nsDocument::InitCSP(nsIChannel* aChannel)
// ----- if the doc is an app and we want a default CSP, apply it.
if (applyAppDefaultCSP) {
csp->AppendPolicy(appDefaultCSP, false);
csp->AppendPolicy(appDefaultCSP, false, false);
}
// ----- if the doc is an app and specifies a CSP in its manifest, apply it.
if (applyAppManifestCSP) {
csp->AppendPolicy(appManifestCSP, false);
csp->AppendPolicy(appManifestCSP, false, false);
}
// ----- if the doc is part of Loop, apply the loop CSP
@ -2783,7 +2838,7 @@ nsDocument::InitCSP(nsIChannel* aChannel)
NS_ASSERTION(loopCSP, "Missing loop.CSP preference");
// If the pref has been removed, we continue without setting a CSP
if (loopCSP) {
csp->AppendPolicy(loopCSP, false);
csp->AppendPolicy(loopCSP, false, false);
}
}
@ -2815,34 +2870,13 @@ nsDocument::InitCSP(nsIChannel* aChannel)
}
}
// ----- Set up any Referrer Policy specified by CSP
bool hasReferrerPolicy = false;
uint32_t referrerPolicy = mozilla::net::RP_Default;
rv = csp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
NS_ENSURE_SUCCESS(rv, rv);
if (hasReferrerPolicy) {
// Referrer policy spec (section 6.1) says that we always use the newest
// referrer policy we find
mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
mReferrerPolicySet = true;
// Referrer Policy is set separately for the speculative parser in
// nsHTMLDocument::StartDocumentLoad() so there's nothing to do here for
// speculative loads.
}
// ------ Set flag for 'upgrade-insecure-requests' if not already
// inherited from the parent context.
if (!mUpgradeInsecureRequests) {
rv = csp->GetUpgradeInsecureRequests(&mUpgradeInsecureRequests);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = principal->SetCsp(csp);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_LOG(gCspPRLog, LogLevel::Debug,
("Inserted CSP into principal %p", principal));
ApplySettingsFromCSP(false);
return NS_OK;
}

View File

@ -717,6 +717,8 @@ public:
virtual void SetChromeXHRDocBaseURI(nsIURI* aURI) override;
virtual void ApplySettingsFromCSP(bool aSpeculative) override;
/**
* Set the principal responsible for this document.
*/

View File

@ -296,6 +296,11 @@ public:
*/
virtual void SetChromeXHRDocBaseURI(nsIURI* aURI) = 0;
/**
* Set referrer policy and upgrade-insecure-requests flags
*/
virtual void ApplySettingsFromCSP(bool aSpeculative) = 0;
/**
* Return the referrer policy of the document. Return "default" if there's no
* valid meta referrer tag found in the document.
@ -325,6 +330,14 @@ public:
return mUpgradeInsecureRequests;
}
/**
* Same as GetUpgradeInsecureRequests() but *only* for preloads.
*/
bool GetUpgradeInsecurePreloads() const
{
return mUpgradeInsecurePreloads;
}
/**
* Set the principal responsible for this document.
*/
@ -2713,6 +2726,7 @@ protected:
ReferrerPolicyEnum mReferrerPolicy;
bool mUpgradeInsecureRequests;
bool mUpgradeInsecurePreloads;
mozilla::WeakPtr<nsDocShell> mDocumentContainer;

View File

@ -563,7 +563,12 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
ourCORSMode == request->mCORSMode &&
ourRefPolicy == request->mReferrerPolicy) {
rv = CheckContentPolicy(mDocument, aElement, request->mURI, type, false);
NS_ENSURE_SUCCESS(rv, false);
if (NS_FAILED(rv)) {
// probably plans have changed; even though the preload was allowed seems
// like the actual load is not; let's cancel the preload request.
request->Cancel();
return false;
}
} else {
// Drop the preload
request = nullptr;

View File

@ -119,6 +119,15 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
maxUniformBlockLenWithNull = 1;
}
GLuint maxTransformFeedbackVaryingLenWithNull = 0;
if (gl->IsSupported(gl::GLFeature::transform_feedback2)) {
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH,
(GLint*)&maxTransformFeedbackVaryingLenWithNull);
if (maxTransformFeedbackVaryingLenWithNull < 1)
maxTransformFeedbackVaryingLenWithNull = 1;
}
#ifdef DUMP_SHADERVAR_MAPPINGS
printf_stderr("maxAttribLenWithNull: %d\n", maxAttribLenWithNull);
printf_stderr("maxUniformLenWithNull: %d\n", maxUniformLenWithNull);
@ -278,6 +287,51 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
}
}
// Transform feedback varyings
if (gl->IsSupported(gl::GLFeature::transform_feedback2)) {
GLuint numTransformFeedbackVaryings = 0;
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS,
(GLint*)&numTransformFeedbackVaryings);
for (GLuint i = 0; i < numTransformFeedbackVaryings; i++) {
nsAutoCString mappedName;
mappedName.SetLength(maxTransformFeedbackVaryingLenWithNull - 1);
GLint lengthWithoutNull;
GLsizei size;
GLenum type;
gl->fGetTransformFeedbackVarying(prog->mGLName, i, maxTransformFeedbackVaryingLenWithNull,
&lengthWithoutNull, &size, &type,
mappedName.BeginWriting());
mappedName.SetLength(lengthWithoutNull);
nsAutoCString baseMappedName;
bool isArray;
size_t arrayIndex;
if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
MOZ_CRASH("Failed to parse `mappedName` received from driver.");
nsAutoCString baseUserName;
if (!prog->FindVaryingByMappedName(mappedName, &baseUserName, &isArray)) {
baseUserName = baseMappedName;
if (needsCheckForArrays && !isArray) {
std::string mappedNameStr = baseMappedName.BeginReading();
mappedNameStr += "[0]";
GLuint loc = gl->fGetUniformBlockIndex(prog->mGLName,
mappedNameStr.c_str());
if (loc != LOCAL_GL_INVALID_INDEX)
isArray = true;
}
}
AddActiveInfo(prog->Context(), size, type, isArray, baseUserName, mappedName,
&info->transformFeedbackVaryings, &info->transformFeedbackVaryingsMap);
}
}
return info.forget();
}
@ -995,6 +1049,18 @@ WebGLProgram::FindAttribUserNameByMappedName(const nsACString& mappedName,
return false;
}
bool
WebGLProgram::FindVaryingByMappedName(const nsACString& mappedName,
nsCString* const out_userName,
bool* const out_isArray) const
{
if (mVertShader->FindVaryingByMappedName(mappedName, out_userName, out_isArray))
return true;
return false;
}
bool
WebGLProgram::FindUniformByMappedName(const nsACString& mappedName,
nsCString* const out_userName,
@ -1058,19 +1124,13 @@ WebGLProgram::GetTransformFeedbackVarying(GLuint index)
return nullptr;
}
if (index >= mTransformFeedbackVaryings.size()) {
if (index >= LinkInfo()->transformFeedbackVaryings.size()) {
mContext->ErrorInvalidValue("getTransformFeedbackVarying: `index` is greater or "
"equal to TRANSFORM_FEEDBACK_VARYINGS.");
return nullptr;
}
const nsCString& varyingUserName = mTransformFeedbackVaryings[index];
WebGLActiveInfo* info;
LinkInfo()->FindAttrib(varyingUserName, (const WebGLActiveInfo**) &info);
MOZ_ASSERT(info);
RefPtr<WebGLActiveInfo> ret(info);
RefPtr<WebGLActiveInfo> ret = LinkInfo()->transformFeedbackVaryings[index];
return ret.forget();
}

View File

@ -59,11 +59,13 @@ struct LinkedProgramInfo final
WebGLProgram* const prog;
std::vector<RefPtr<WebGLActiveInfo>> activeAttribs;
std::vector<RefPtr<WebGLActiveInfo>> activeUniforms;
std::vector<RefPtr<WebGLActiveInfo>> transformFeedbackVaryings;
// Needed for Get{Attrib,Uniform}Location. The keys for these are non-mapped
// user-facing `GLActiveInfo::name`s, without any final "[0]".
std::map<nsCString, const WebGLActiveInfo*> attribMap;
std::map<nsCString, const WebGLActiveInfo*> uniformMap;
std::map<nsCString, const WebGLActiveInfo*> transformFeedbackVaryingsMap;
std::map<nsCString, const nsCString>* fragDataMap;
std::vector<RefPtr<UniformBlockInfo>> uniformBlocks;
@ -173,6 +175,9 @@ public:
bool FindAttribUserNameByMappedName(const nsACString& mappedName,
nsDependentCString* const out_userName) const;
bool FindVaryingByMappedName(const nsACString& mappedName,
nsCString* const out_userName,
bool* const out_isArray) const;
bool FindUniformByMappedName(const nsACString& mappedName,
nsCString* const out_userName,
bool* const out_isArray) const;

View File

@ -335,6 +335,23 @@ WebGLShader::FindAttribUserNameByMappedName(const nsACString& mappedName,
return true;
}
bool
WebGLShader::FindVaryingByMappedName(const nsACString& mappedName,
nsCString* const out_userName,
bool* const out_isArray) const
{
if (!mValidator)
return false;
const std::string mappedNameStr(mappedName.BeginReading());
std::string userNameStr;
if (!mValidator->FindVaryingByMappedName(mappedNameStr, &userNameStr, out_isArray))
return false;
*out_userName = userNameStr.c_str();
return true;
}
bool
WebGLShader::FindUniformByMappedName(const nsACString& mappedName,
nsCString* const out_userName,

View File

@ -53,6 +53,9 @@ public:
void BindAttribLocation(GLuint prog, const nsCString& userName, GLuint index) const;
bool FindAttribUserNameByMappedName(const nsACString& mappedName,
nsDependentCString* const out_userName) const;
bool FindVaryingByMappedName(const nsACString& mappedName,
nsCString* const out_userName,
bool* const out_isArray) const;
bool FindUniformByMappedName(const nsACString& mappedName,
nsCString* const out_userName,
bool* const out_isArray) const;

View File

@ -361,6 +361,24 @@ ShaderValidator::FindAttribMappedNameByUserName(const std::string& userName,
return false;
}
bool
ShaderValidator::FindVaryingByMappedName(const std::string& mappedName,
std::string* const out_userName,
bool* const out_isArray) const
{
const std::vector<sh::Varying>& varyings = *ShGetVaryings(mHandle);
for (auto itr = varyings.begin(); itr != varyings.end(); ++itr) {
const sh::ShaderVariable* found;
if (!itr->findInfoByMappedName(mappedName, &found, out_userName))
continue;
*out_isArray = found->isArray();
return true;
}
return false;
}
bool
ShaderValidator::FindVaryingMappedNameByUserName(const std::string& userName,
const std::string** const out_mappedName) const
@ -375,7 +393,6 @@ ShaderValidator::FindVaryingMappedNameByUserName(const std::string& userName,
return false;
}
// This must handle names like "foo.bar[0]".
bool
ShaderValidator::FindUniformByMappedName(const std::string& mappedName,
@ -392,6 +409,18 @@ ShaderValidator::FindUniformByMappedName(const std::string& mappedName,
return true;
}
const std::vector<sh::InterfaceBlock>& interfaces = *ShGetInterfaceBlocks(mHandle);
for (const auto& interface : interfaces) {
for (const auto& field : interface.fields) {
const sh::ShaderVariable* found;
if (!field.findInfoByMappedName(mappedName, &found, out_userName))
continue;
*out_isArray = found->isArray();
return true;
}
}
return false;
}

View File

@ -53,6 +53,9 @@ public:
bool FindVaryingMappedNameByUserName(const std::string& userName,
const std::string** const out_mappedName) const;
bool FindVaryingByMappedName(const std::string& mappedName,
std::string* const out_userName,
bool* const out_isArray) const;
bool FindUniformByMappedName(const std::string& mappedName,
std::string* const out_userName,
bool* const out_isArray) const;

View File

@ -7,8 +7,10 @@
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/dom/HTMLMetaElement.h"
#include "mozilla/dom/HTMLMetaElementBinding.h"
#include "mozilla/dom/nsCSPService.h"
#include "nsContentUtils.h"
#include "nsStyleConsts.h"
#include "nsIContentSecurityPolicy.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Meta)
@ -111,6 +113,51 @@ HTMLMetaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
NS_ENSURE_SUCCESS(rv, rv);
nsContentUtils::ProcessViewportInfo(aDocument, content);
}
if (CSPService::sCSPEnabled && aDocument &&
AttrValueIs(kNameSpaceID_None, nsGkAtoms::httpEquiv, nsGkAtoms::headerCSP, eIgnoreCase)) {
// only accept <meta http-equiv="Content-Security-Policy" content=""> if it appears
// in the <head> element.
Element* headElt = aDocument->GetHeadElement();
if (headElt && nsContentUtils::ContentIsDescendantOf(this, headElt)) {
nsAutoString content;
rv = GetContent(content);
NS_ENSURE_SUCCESS(rv, rv);
content = nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(content);
nsIPrincipal* principal = aDocument->NodePrincipal();
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
// Multiple CSPs (delivered through either header of meta tag) need to be
// joined together, see:
// https://w3c.github.io/webappsec/specs/content-security-policy/#delivery-html-meta-element
if (!csp) {
csp = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Store the request context so CSP can resolve 'self'
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDocument);
rv = csp->SetRequestContext(domDoc, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
// set the new CSP
rv = principal->SetCsp(csp);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = csp->AppendPolicy(content,
false, // csp via meta tag can not be report only
true); // delivered through the meta tag
NS_ENSURE_SUCCESS(rv, rv);
aDocument->ApplySettingsFromCSP(false);
}
}
// Referrer Policy spec requires a <meta name="referrer" tag to be in the
// <head> element.
rv = SetMetaReferrer(aDocument);

View File

@ -21,7 +21,7 @@ interface nsIURI;
typedef unsigned short CSPDirective;
[scriptable, builtinclass, uuid(b9a029c3-9484-4bf7-826d-0c6b545790bc)]
[scriptable, builtinclass, uuid(b3c4c0ae-bd5e-4cad-87e0-8d210dbb3f9f)]
interface nsIContentSecurityPolicy : nsISerializable
{
/**
@ -90,12 +90,17 @@ interface nsIContentSecurityPolicy : nsISerializable
/**
* Parse and install a CSP policy.
* @param aPolicy
* String representation of the policy (e.g., header value)
* String representation of the policy
* (e.g., header value, meta content)
* @param reportOnly
* Should this policy affect content, script and style processing or
* just send reports if it is violated?
* @param deliveredViaMetaTag
* Indicates whether the policy was delivered via the meta tag.
*/
void appendPolicy(in AString policyString, in boolean reportOnly);
void appendPolicy(in AString policyString,
in boolean reportOnly,
in boolean deliveredViaMetaTag);
/*
* Whether this policy allows inline script or style.

View File

@ -32,6 +32,9 @@ ignoringUnknownOption = Ignoring unknown option %1$S
# LOCALIZATION NOTE (ignoringDuplicateSrc):
# %1$S defines the duplicate src
ignoringDuplicateSrc = Ignoring duplicate source %1$S
# LOCALIZATION NOTE (ignoringSrcFromMetaCSP):
# %1$S defines the ignored src
ignoringSrcFromMetaCSP = Ignoring source '%1$S' (Not supported when delivered via meta element).
# LOCALIZATION NOTE (ignoringSrcWithinScriptSrc):
# %1$S is the ignored src
# script-src is a directive name and should not be localized

View File

@ -116,9 +116,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
CSPCONTEXTLOG((">>>> aContentType: %d", aContentType));
}
bool isStyleOrScriptPreLoad =
(aContentType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
aContentType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD);
bool isPreload = nsContentUtils::IsPreloadType(aContentType);
// Since we know whether we are dealing with a preload, we have to convert
// the internal policytype ot the external policy type before moving on.
@ -157,7 +155,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
}
nsAutoString nonce;
if (!isStyleOrScriptPreLoad) {
if (!isPreload) {
nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aRequestContext);
if (htmlElement) {
rv = htmlElement->GetAttribute(NS_LITERAL_STRING("nonce"), nonce);
@ -174,7 +172,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
originalURI,
nonce,
wasRedirected,
isStyleOrScriptPreLoad,
isPreload,
false, // allow fallback to default-src
true, // send violation reports
true); // send blocked URI in violation reports
@ -183,7 +181,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
: nsIContentPolicy::REJECT_SERVER;
// Done looping, cache any relevant result
if (cacheKey.Length() > 0 && !isStyleOrScriptPreLoad) {
if (cacheKey.Length() > 0 && !isPreload) {
mShouldLoadCache.Put(cacheKey, *outDecision);
}
@ -342,14 +340,17 @@ nsCSPContext::GetReferrerPolicy(uint32_t* outPolicy, bool* outIsSet)
NS_IMETHODIMP
nsCSPContext::AppendPolicy(const nsAString& aPolicyString,
bool aReportOnly)
bool aReportOnly,
bool aDeliveredViaMetaTag)
{
CSPCONTEXTLOG(("nsCSPContext::AppendPolicy: %s",
NS_ConvertUTF16toUTF8(aPolicyString).get()));
// Use the mSelfURI from setRequestContext, see bug 991474
NS_ASSERTION(mSelfURI, "mSelfURI required for AppendPolicy, but not set");
nsCSPPolicy* policy = nsCSPParser::parseContentSecurityPolicy(aPolicyString, mSelfURI, aReportOnly, this);
nsCSPPolicy* policy = nsCSPParser::parseContentSecurityPolicy(aPolicyString, mSelfURI,
aReportOnly, this,
aDeliveredViaMetaTag);
if (policy) {
mPolicies.AppendElement(policy);
// reset cache since effective policy changes
@ -1353,10 +1354,15 @@ nsCSPContext::Read(nsIObjectInputStream* aStream)
rv = aStream->ReadBoolean(&reportOnly);
NS_ENSURE_SUCCESS(rv, rv);
// @param deliveredViaMetaTag:
// when parsing the CSP policy string initially we already remove directives
// that should not be processed when delivered via the meta tag. Such directives
// will not be present at this point anymore.
nsCSPPolicy* policy = nsCSPParser::parseContentSecurityPolicy(policyString,
mSelfURI,
reportOnly,
this);
this,
false);
if (policy) {
mPolicies.AppendElement(policy);
}

View File

@ -122,7 +122,8 @@ nsCSPTokenizer::tokenizeCSPPolicy(const nsAString &aPolicyString,
nsCSPParser::nsCSPParser(cspTokens& aTokens,
nsIURI* aSelfURI,
nsCSPContext* aCSPContext)
nsCSPContext* aCSPContext,
bool aDeliveredViaMetaTag)
: mHasHashOrNonce(false)
, mUnsafeInlineKeywordSrc(nullptr)
, mChildSrc(nullptr)
@ -130,6 +131,7 @@ nsCSPParser::nsCSPParser(cspTokens& aTokens,
, mTokens(aTokens)
, mSelfURI(aSelfURI)
, mCSPContext(aCSPContext)
, mDeliveredViaMetaTag(aDeliveredViaMetaTag)
{
CSPPARSERLOG(("nsCSPParser::nsCSPParser"));
}
@ -991,6 +993,20 @@ nsCSPParser::directiveName()
return nullptr;
}
// CSP delivered via meta tag should ignore the following directives:
// report-uri, frame-ancestors, and sandbox, see:
// http://www.w3.org/TR/CSP11/#delivery-html-meta-element
if (mDeliveredViaMetaTag &&
((CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::REPORT_URI_DIRECTIVE)) ||
(CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE)))) {
// log to the console to indicate that meta CSP is ignoring the directive
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag,
"ignoringSrcFromMetaCSP",
params, ArrayLength(params));
return nullptr;
}
// special case handling for upgrade-insecure-requests
if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
return new nsUpgradeInsecureDirective(CSP_StringToCSPDirective(mCurToken));
@ -1116,7 +1132,8 @@ nsCSPPolicy*
nsCSPParser::parseContentSecurityPolicy(const nsAString& aPolicyString,
nsIURI *aSelfURI,
bool aReportOnly,
nsCSPContext* aCSPContext)
nsCSPContext* aCSPContext,
bool aDeliveredViaMetaTag)
{
if (CSPPARSERLOGENABLED()) {
CSPPARSERLOG(("nsCSPParser::parseContentSecurityPolicy, policy: %s",
@ -1126,6 +1143,8 @@ nsCSPParser::parseContentSecurityPolicy(const nsAString& aPolicyString,
CSPPARSERLOG(("nsCSPParser::parseContentSecurityPolicy, selfURI: %s", spec.get()));
CSPPARSERLOG(("nsCSPParser::parseContentSecurityPolicy, reportOnly: %s",
(aReportOnly ? "true" : "false")));
CSPPARSERLOG(("nsCSPParser::parseContentSecurityPolicy, deliveredViaMetaTag: %s",
(aDeliveredViaMetaTag ? "true" : "false")));
}
NS_ASSERTION(aSelfURI, "Can not parseContentSecurityPolicy without aSelfURI");
@ -1138,7 +1157,7 @@ nsCSPParser::parseContentSecurityPolicy(const nsAString& aPolicyString,
nsTArray< nsTArray<nsString> > tokens;
nsCSPTokenizer::tokenizeCSPPolicy(aPolicyString, tokens);
nsCSPParser parser(tokens, aSelfURI, aCSPContext);
nsCSPParser parser(tokens, aSelfURI, aCSPContext, aDeliveredViaMetaTag);
// Start the parser to generate a new CSPPolicy using the generated tokens.
nsCSPPolicy* policy = parser.policy();

View File

@ -100,12 +100,15 @@ class nsCSPParser {
static nsCSPPolicy* parseContentSecurityPolicy(const nsAString &aPolicyString,
nsIURI *aSelfURI,
bool aReportOnly,
nsCSPContext* aCSPContext);
nsCSPContext* aCSPContext,
bool aDeliveredViaMetaTag);
private:
nsCSPParser(cspTokens& aTokens,
nsIURI* aSelfURI,
nsCSPContext* aCSPContext);
nsCSPContext* aCSPContext,
bool aDeliveredViaMetaTag);
~nsCSPParser();
@ -246,6 +249,7 @@ class nsCSPParser {
nsIURI* mSelfURI;
nsCSPPolicy* mPolicy;
nsCSPContext* mCSPContext; // used for console logging
bool mDeliveredViaMetaTag;
};
#endif /* nsCSPParser_h___ */

View File

@ -204,42 +204,57 @@ CSPService::ShouldLoad(uint32_t aContentType,
nsCOMPtr<nsINode> node(do_QueryInterface(aRequestContext));
nsCOMPtr<nsIPrincipal> principal = node ? node->NodePrincipal()
: aRequestPrincipal;
if (principal) {
nsCOMPtr<nsIContentSecurityPolicy> csp;
principal->GetCsp(getter_AddRefs(csp));
if (!principal) {
// if we can't query a principal, then there is nothing to do.
return NS_OK;
}
nsresult rv = NS_OK;
if (csp) {
if (MOZ_LOG_TEST(gCspPRLog, LogLevel::Debug)) {
uint32_t numPolicies = 0;
nsresult rv = csp->GetPolicyCount(&numPolicies);
if (NS_SUCCEEDED(rv)) {
for (uint32_t i=0; i<numPolicies; i++) {
nsAutoString policy;
csp->GetPolicy(i, policy);
MOZ_LOG(gCspPRLog, LogLevel::Debug,
("Document has CSP[%d]: %s", i,
NS_ConvertUTF16toUTF8(policy).get()));
}
}
}
// 1) Apply speculate CSP for preloads
bool isPreload = nsContentUtils::IsPreloadType(aContentType);
if (isPreload) {
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
rv = principal->GetPreloadCsp(getter_AddRefs(preloadCsp));
NS_ENSURE_SUCCESS(rv, rv);
if (preloadCsp) {
// obtain the enforcement decision
// (don't pass aExtra, we use that slot for redirects)
csp->ShouldLoad(aContentType,
aContentLocation,
aRequestOrigin,
aRequestContext,
aMimeTypeGuess,
nullptr,
aDecision);
rv = preloadCsp->ShouldLoad(aContentType,
aContentLocation,
aRequestOrigin,
aRequestContext,
aMimeTypeGuess,
nullptr, // aExtra
aDecision);
NS_ENSURE_SUCCESS(rv, rv);
// if the preload policy already denied the load, then there
// is no point in checking the real policy
if (NS_CP_REJECTED(*aDecision)) {
return NS_OK;
}
}
}
else if (MOZ_LOG_TEST(gCspPRLog, LogLevel::Debug)) {
nsAutoCString uriSpec;
aContentLocation->GetSpec(uriSpec);
MOZ_LOG(gCspPRLog, LogLevel::Debug,
("COULD NOT get nsIPrincipal for location: %s", uriSpec.get()));
}
// 2) Apply actual CSP to all loads
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
// obtain the enforcement decision
// (don't pass aExtra, we use that slot for redirects)
rv = csp->ShouldLoad(aContentType,
aContentLocation,
aRequestOrigin,
aRequestContext,
aMimeTypeGuess,
nullptr,
aDecision);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
@ -294,16 +309,6 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
return NS_OK;
}
// Get the LoadingPrincipal and CSP from the loadInfo
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = loadInfo->LoadingPrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
// if there is no CSP, nothing for us to do
if (!csp) {
return NS_OK;
}
/* Since redirecting channels don't call into nsIContentPolicy, we call our
* Content Policy implementation directly when redirects occur using the
* information set in the LoadInfo when channels are created.
@ -314,37 +319,55 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
nsCOMPtr<nsIURI> originalUri;
rv = oldChannel->GetOriginalURI(getter_AddRefs(originalUri));
NS_ENSURE_SUCCESS(rv, rv);
nsContentPolicyType policyType = loadInfo->InternalContentPolicyType();
bool isPreload = nsContentUtils::IsPreloadType(policyType);
/* On redirect, if the content policy is a preload type, rejecting the preload
* results in the load silently failing, so we convert preloads to the actual
* type. See Bug 1219453.
*/
nsContentPolicyType policyType =
nsContentUtils::InternalContentPolicyTypeToExternalOrWorker(
loadInfo->InternalContentPolicyType());
policyType =
nsContentUtils::InternalContentPolicyTypeToExternalOrWorker(policyType);
int16_t aDecision = nsIContentPolicy::ACCEPT;
csp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t)
newUri, // nsIURI
nullptr, // nsIURI
nullptr, // nsISupports
EmptyCString(), // ACString - MIME guess
originalUri, // aMimeTypeGuess
&aDecision);
// 1) Apply speculative CSP for preloads
if (isPreload) {
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
loadInfo->LoadingPrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
if (newUri && MOZ_LOG_TEST(gCspPRLog, LogLevel::Debug)) {
nsAutoCString newUriSpec("None");
newUri->GetSpec(newUriSpec);
MOZ_LOG(gCspPRLog, LogLevel::Debug,
("CSPService::AsyncOnChannelRedirect called for %s",
newUriSpec.get()));
if (preloadCsp) {
// Pass originalURI as aExtra to indicate the redirect
preloadCsp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t)
newUri, // nsIURI
nullptr, // nsIURI
nullptr, // nsISupports
EmptyCString(), // ACString - MIME guess
originalUri, // aExtra
&aDecision);
// if the preload policy already denied the load, then there
// is no point in checking the real policy
if (NS_CP_REJECTED(aDecision)) {
autoCallback.DontCallback();
return NS_BINDING_FAILED;
}
}
}
if (aDecision == 1) {
MOZ_LOG(gCspPRLog, LogLevel::Debug,
("CSPService::AsyncOnChannelRedirect ALLOWING request."));
}
else {
MOZ_LOG(gCspPRLog, LogLevel::Debug,
("CSPService::AsyncOnChannelRedirect CANCELLING request."));
// 2) Apply actual CSP to all loads
nsCOMPtr<nsIContentSecurityPolicy> csp;
loadInfo->LoadingPrincipal()->GetCsp(getter_AddRefs(csp));
if (csp) {
// Pass originalURI as aExtra to indicate the redirect
csp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t)
newUri, // nsIURI
nullptr, // nsIURI
nullptr, // nsISupports
EmptyCString(), // ACString - MIME guess
originalUri, // aExtra
&aDecision);
}
// if ShouldLoad doesn't accept the load, cancel the request

View File

@ -117,7 +117,7 @@ nsresult runTest(uint32_t aExpectedPolicyCount, // this should be 0 for policies
// append a policy
nsString policyStr;
policyStr.AssignASCII(aPolicy);
rv = csp->AppendPolicy(policyStr, false);
rv = csp->AppendPolicy(policyStr, false, false);
NS_ENSURE_SUCCESS(rv, rv);
// when executing fuzzy tests we do not care about the actual output

View File

@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 663570 - Test doc.write(meta csp)</title>
<meta charset="utf-8">
<!-- Use doc.write() to *un*apply meta csp -->
<script type="application/javascript">
document.write("<!--");
</script>
<meta http-equiv="Content-Security-Policy" content= "style-src 'none'; script-src 'none'; img-src 'none'">
-->
<!-- try to load a css on a page where meta CSP is commented out -->
<link rel="stylesheet" type="text/css" href="file_docwrite_meta.css">
<!-- try to load a script on a page where meta CSP is commented out -->
<script id="testscript" src="file_docwrite_meta.js"></script>
</head>
<body>
<!-- try to load an image on a page where meta CSP is commented out -->
<img id="testimage" src="http://mochi.test:8888/tests/image/test/mochitest/blue.png"></img>
</body>
</html>

View File

@ -0,0 +1,3 @@
body {
background-color: rgb(255, 0, 0);
}

View File

@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 663570 - Test doc.write(meta csp)</title>
<meta charset="utf-8">
<!-- Use doc.write() to apply meta csp -->
<script type="application/javascript">
var metaCSP = "style-src 'none'; script-src 'none'; img-src 'none'";
document.write("<meta http-equiv=\"Content-Security-Policy\" content=\" " + metaCSP + "\">");
</script>
<!-- try to load a css which is forbidden by meta CSP -->
<link rel="stylesheet" type="text/css" href="file_docwrite_meta.css">
<!-- try to load a script which is forbidden by meta CSP -->
<script id="testscript" src="file_docwrite_meta.js"></script>
</head>
<body>
<!-- try to load an image which is forbidden by meta CSP -->
<img id="testimage" src="http://mochi.test:8888/tests/image/test/mochitest/blue.png"></img>
</body>
</html>

View File

@ -0,0 +1,3 @@
// set a variable on the document which we can check to verify
// whether the external script was loaded or blocked
document.myMetaCSPScript = "external-JS-loaded";

View File

@ -0,0 +1,25 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content= "img-src 'none'; script-src 'unsafe-inline'; report-uri http://www.example.com; frame-ancestors https:; sandbox allow-scripts">
<title>Bug 663570 - Implement Content Security Policy via meta tag</title>
</head>
<body>
<!-- try to load an image which is forbidden by meta CSP -->
<img id="testimage" src="http://mochi.test:8888/tests/image/test/mochitest/blue.png"></img>
<script type="application/javascript">
var myImg = document.getElementById("testimage");
myImg.onload = function(e) {
window.parent.postMessage({result: "img-loaded"}, "*");
};
myImg.onerror = function(e) {
window.parent.postMessage({result: "img-blocked"}, "*");
};
</script>
</body>
</html>

View File

@ -0,0 +1,98 @@
// Custom *.sjs file specifically for the needs of Bug:
// Bug 663570 - Implement Content Security Policy via meta tag
const HTML_HEAD =
"<!DOCTYPE HTML>" +
"<html>" +
"<head>" +
"<meta charset='utf-8'>" +
"<title>Bug 663570 - Implement Content Security Policy via <meta> tag</title>";
const HTML_BODY =
"</head>" +
"<body>" +
"<img id='testimage' src='http://mochi.test:8888/tests/image/test/mochitest/blue.png'></img>" +
"<script type='application/javascript'>" +
" var myImg = document.getElementById('testimage');" +
" myImg.onload = function(e) {" +
" window.parent.postMessage({result: 'img-loaded'}, '*');" +
" };" +
" myImg.onerror = function(e) { " +
" window.parent.postMessage({result: 'img-blocked'}, '*');" +
" };" +
"</script>" +
"</body>" +
"</html>";
const META_CSP_BLOCK_IMG =
"<meta http-equiv=\"Content-Security-Policy\" content=\"img-src 'none'\">";
const META_CSP_ALLOW_IMG =
"<meta http-equiv=\"Content-Security-Policy\" content=\"img-src http://mochi.test:8888;\">";
const HEADER_CSP_BLOCK_IMG = "img-src 'none';";
const HEADER_CSP_ALLOW_IMG = "img-src http://mochi.test:8888";
function handleRequest(request, response)
{
// avoid confusing cache behaviors
response.setHeader("Cache-Control", "no-cache", false);
response.setHeader("Content-Type", "text/html", false);
var queryString = request.queryString;
if (queryString === "test1") {
/* load image without any CSP */
response.write(HTML_HEAD + HTML_BODY);
return;
}
if (queryString === "test2") {
/* load image where meta denies load */
response.write(HTML_HEAD + META_CSP_BLOCK_IMG + HTML_BODY);
return;
}
if (queryString === "test3") {
/* load image where meta allows load */
response.write(HTML_HEAD + META_CSP_ALLOW_IMG + HTML_BODY);
return;
}
if (queryString === "test4") {
/* load image where meta allows but header blocks */
response.setHeader("Content-Security-Policy", HEADER_CSP_BLOCK_IMG, false);
response.write(HTML_HEAD + META_CSP_ALLOW_IMG + HTML_BODY);
return;
}
if (queryString === "test5") {
/* load image where meta blocks but header allows */
response.setHeader("Content-Security-Policy", HEADER_CSP_ALLOW_IMG, false);
response.write(HTML_HEAD + META_CSP_BLOCK_IMG + HTML_BODY);
return;
}
if (queryString === "test6") {
/* load image where meta allows and header allows */
response.setHeader("Content-Security-Policy", HEADER_CSP_ALLOW_IMG, false);
response.write(HTML_HEAD + META_CSP_ALLOW_IMG + HTML_BODY);
return;
}
if (queryString === "test7") {
/* load image where meta1 allows but meta2 blocks */
response.write(HTML_HEAD + META_CSP_ALLOW_IMG + META_CSP_BLOCK_IMG + HTML_BODY);
return;
}
if (queryString === "test8") {
/* load image where meta1 allows and meta2 allows */
response.write(HTML_HEAD + META_CSP_ALLOW_IMG + META_CSP_ALLOW_IMG + HTML_BODY);
return;
}
// we should never get here, but just in case, return
// something unexpected
response.write("do'h");
}

View File

@ -0,0 +1,79 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests; default-src https: wss: 'unsafe-inline'; form-action https:;">
<meta charset="utf-8">
<title>Bug 1139297 - Implement CSP upgrade-insecure-requests directive</title>
<!-- style -->
<link rel='stylesheet' type='text/css' href='http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_server.sjs?style' media='screen' />
<!-- font -->
<style>
@font-face {
font-family: "foofont";
src: url('http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_server.sjs?font');
}
.div_foo { font-family: "foofont"; }
</style>
</head>
<body>
<!-- images: -->
<img src="http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_server.sjs?img"></img>
<!-- redirects: upgrade http:// to https:// redirect to http:// and then upgrade to https:// again -->
<img src="http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_server.sjs?redirect-image"></img>
<!-- script: -->
<script src="http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_server.sjs?script"></script>
<!-- media: -->
<audio src="http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_server.sjs?media"></audio>
<!-- objects: -->
<object width="10" height="10" data="http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_server.sjs?object"></object>
<!-- font: (apply font loaded in header to div) -->
<div class="div_foo">foo</div>
<!-- iframe: (same origin) -->
<iframe src="http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_server.sjs?iframe">
<!-- within that iframe we load an image over http and make sure the requested gets upgraded to https -->
</iframe>
<!-- xhr: -->
<script type="application/javascript">
var myXHR = new XMLHttpRequest();
myXHR.open("GET", "http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_server.sjs?xhr");
myXHR.send(null);
</script>
<!-- websockets: upgrade ws:// to wss://-->
<script type="application/javascript">
var mySocket = new WebSocket("ws://example.com/tests/dom/security/test/csp/file_upgrade_insecure");
mySocket.onopen = function(e) {
if (mySocket.url.includes("wss://")) {
window.parent.postMessage({result: "websocket-ok"}, "*");
}
else {
window.parent.postMessage({result: "websocket-error"}, "*");
}
};
mySocket.onerror = function(e) {
window.parent.postMessage({result: "websocket-unexpected-error"}, "*");
};
</script>
<!-- form action: (upgrade POST from http:// to https://) -->
<iframe name='formFrame' id='formFrame'></iframe>
<form target="formFrame" action="http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_server.sjs?form" method="POST">
<input name="foo" value="foo">
<input type="submit" id="submitButton" formenctype='multipart/form-data' value="Submit form">
</form>
<script type="text/javascript">
var submitButton = document.getElementById('submitButton');
submitButton.click();
</script>
</body>
</html>

View File

@ -1,13 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1139297 - Implement CSP upgrade-insecure-requests directive</title>
</head>
<body>
<!-- upgrade img from http:// to https:// -->
<img id="testimage" src="http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_referrer_server.sjs?img"></img>
</body>
</html>

View File

@ -0,0 +1,55 @@
// special *.sjs specifically customized for the needs of
// Bug 1139297 and Bug 663570
const PRE_HEAD =
"<!DOCTYPE HTML>" +
"<html>" +
"<head>";
const POST_HEAD =
"<meta charset='utf-8'>" +
"<title>Bug 1139297 - Implement CSP upgrade-insecure-requests directive</title>" +
"</head>" +
"<body>" +
"<img id='testimage' src='http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_referrer_server.sjs?img'></img>" +
"</body>" +
"</html>";
const PRE_CSP = "upgrade-insecure-requests; default-src https:; ";
const CSP_REFERRER_ORIGIN = "referrer origin";
const CSP_REFEFFER_NO_REFERRER = "referrer no-referrer";
function handleRequest(request, response)
{
// avoid confusing cache behaviors
response.setHeader("Cache-Control", "no-cache", false);
var queryString = request.queryString;
if (queryString === "test1") {
response.setHeader("Content-Security-Policy", PRE_CSP + CSP_REFERRER_ORIGIN, false);
response.write(PRE_HEAD + POST_HEAD);
return;
}
if (queryString === "test2") {
response.setHeader("Content-Security-Policy", PRE_CSP + CSP_REFEFFER_NO_REFERRER, false);
response.write(PRE_HEAD + POST_HEAD);
return;
}
if (queryString === "test3") {
var metacsp = "<meta http-equiv=\"Content-Security-Policy\" content = \"" + PRE_CSP + CSP_REFERRER_ORIGIN + "\" >";
response.write(PRE_HEAD + metacsp + POST_HEAD);
return;
}
if (queryString === "test4") {
var metacsp = "<meta http-equiv=\"Content-Security-Policy\" content = \"" + PRE_CSP + CSP_REFEFFER_NO_REFERRER + "\" >";
response.write(PRE_HEAD + metacsp + POST_HEAD);
return;
}
// we should never get here, but just in case return
// something unexpected
response.write("do'h");
}

View File

@ -119,11 +119,12 @@ support-files =
file_referrerdirective.html
referrerdirective.sjs
file_upgrade_insecure.html
file_upgrade_insecure_meta.html
file_upgrade_insecure_server.sjs
file_upgrade_insecure_wsh.py
file_upgrade_insecure_reporting.html
file_upgrade_insecure_reporting_server.sjs
file_upgrade_insecure_referrer.html
file_upgrade_insecure_referrer.sjs
file_upgrade_insecure_referrer_server.sjs
file_upgrade_insecure_cors.html
file_upgrade_insecure_cors_server.sjs
@ -145,6 +146,12 @@ support-files =
file_child-src_shared_worker-redirect.html
file_child-src_shared_worker.js
file_redirect_worker.sjs
file_meta_element.html
file_meta_header_dual.sjs
file_docwrite_meta.html
file_doccomment_meta.html
file_docwrite_meta.css
file_docwrite_meta.js
[test_base-uri.html]
[test_blob_data_schemes.html]
@ -216,3 +223,6 @@ skip-if = buildapp == 'b2g' #investigate in bug 1222904
[test_child-src_worker_data.html]
[test_child-src_worker-redirect.html]
[test_child-src_iframe.html]
[test_meta_element.html]
[test_meta_header_dual.html]
[test_docwrite_meta.html]

View File

@ -0,0 +1,86 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 663570 - Implement Content Security Policy via meta tag</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<iframe style="width:100%;" id="writemetacspframe"></iframe>
<iframe style="width:100%;" id="commentmetacspframe"></iframe>
<script class="testbody" type="text/javascript">
/* Description of the test:
* We load two frames, where the first frame does doc.write(meta csp) and
* the second does doc.write(comment out meta csp).
* We make sure to reuse/invalidate preloads depending on the policy.
*/
SimpleTest.waitForExplicitFinish();
var writemetacspframe = document.getElementById("writemetacspframe");
var commentmetacspframe = document.getElementById("commentmetacspframe");
var seenResults = 0;
function checkTestsDone() {
seenResults++;
if (seenResults < 2) {
return;
}
SimpleTest.finish();
}
// document.write(<meta csp ...>) should block resources from being included in the doc
function checkResultsBlocked() {
writemetacspframe.removeEventListener('load', checkResultsBlocked, false);
// stylesheet: default background color within FF is transparent
var bgcolor = window.getComputedStyle(writemetacspframe.contentDocument.body)
.getPropertyValue("background-color");
is(bgcolor, "transparent", "inital background value in FF should be 'transparent'");
// image: make sure image is blocked
var img = writemetacspframe.contentDocument.getElementById("testimage");
is(img.width, 0, "image widht should be 0");
is(img.height, 0, "image widht should be 0");
// script: make sure defined variable in external script is undefined
is(writemetacspframe.contentDocument.myMetaCSPScript, undefined, "myMetaCSPScript should be 'undefined'");
checkTestsDone();
}
// document.write(<--) to comment out meta csp should allow resources to be loaded
// after the preload failed
function checkResultsAllowed() {
commentmetacspframe.removeEventListener('load', checkResultsAllowed, false);
// stylesheet: should be applied; bgcolor should be red
var bgcolor = window.getComputedStyle(commentmetacspframe.contentDocument.body).getPropertyValue("background-color");
is(bgcolor, "rgb(255, 0, 0)", "background should be red/rgb(255, 0, 0)");
// image: should be completed
var img = commentmetacspframe.contentDocument.getElementById("testimage");
ok(img.complete, "image should not be loaded");
// script: defined variable in external script should be accessible
is(commentmetacspframe.contentDocument.myMetaCSPScript, "external-JS-loaded", "myMetaCSPScript should be 'external-JS-loaded'");
checkTestsDone();
}
// doc.write(meta csp) should should allow preloads but should block actual loads
writemetacspframe.src = 'file_docwrite_meta.html';
writemetacspframe.addEventListener('load', checkResultsBlocked, false);
// commenting out a meta CSP should result in loaded image, script, style
commentmetacspframe.src = 'file_doccomment_meta.html';
commentmetacspframe.addEventListener('load', checkResultsAllowed, false);
</script>
</body>
</html>

View File

@ -0,0 +1,90 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 663570 - Implement Content Security Policy via <meta> tag</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<iframe style="width:100%;" id="testframe" src="file_meta_element.html"></iframe>
<script class="testbody" type="text/javascript">
/* Description of the test:
* The test is twofold:
* First, by loading a page using meta csp (into an iframe) we make sure that
* images get correctly blocked as the csp policy includes "img-src 'none'";
*
* Second, we make sure meta csp ignores the following directives:
* * report-uri
* * frame-ancestors
* * sandbox
*
* Please note that the CSP sanbdox directive (bug 671389) has not landed yet.
* Once bug 671389 lands this test will fail and needs to be updated.
*/
SimpleTest.waitForExplicitFinish();
const EXPECTED_DIRS = ["img-src", "script-src"];
function finishTest() {
window.removeEventListener("message", receiveMessage, false);
SimpleTest.finish();
}
function checkResults(result) {
is(result, "img-blocked", "loading images should be blocked by meta csp");
try {
// get the csp in JSON notation from the principal
var frame = document.getElementById("testframe");
var principal = SpecialPowers.wrap(frame.contentDocument).nodePrincipal;
var cspJSON = principal.cspJSON;
ok(cspJSON, "CSP applied through meta element");
// parse the cspJSON in a csp-object
var cspOBJ = JSON.parse(cspJSON);
ok(cspOBJ, "was able to parse the JSON");
// make sure we only got one policy
var policies = cspOBJ["csp-policies"];
is(policies.length, 1, "there should be one policy applied");
// iterate the policy and make sure to only encounter
// expected directives.
var policy = policies[0];
for (var dir in policy) {
// special case handling for report-only which is not a directive
// but present in the JSON notation of the CSP.
if (dir === "report-only") {
continue;
}
var index = EXPECTED_DIRS.indexOf(dir);
isnot(index, -1, "meta csp contains directive: " + dir + "!");
// take the element out of the array so we can make sure
// that we have seen all the expected values in the end.
EXPECTED_DIRS.splice(index, 1);
}
is(EXPECTED_DIRS.length, 0, "have seen all the expected values");
}
catch (e) {
ok(false, "uuh, something went wrong within meta csp test");
}
finishTest();
}
// a postMessage handler used to bubble up the onsuccess/onerror state
// from within the iframe.
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
checkResults(event.data.result);
}
</script>
</body>
</html>

View File

@ -0,0 +1,137 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 663570 - Implement Content Security Policy via meta tag</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<iframe style="width:100%;" id="testframe"></iframe>
<script class="testbody" type="text/javascript">
/* Description of the test:
* We test all sorts of CSPs on documents, including documents with no
* CSP, with meta CSP and with meta CSP in combination with a CSP header.
*/
const TESTS = [
{
/* load image without any CSP */
query: "test1",
result: "img-loaded",
policyLen: 0,
desc: "no CSP should allow load",
},
{
/* load image where meta denies load */
query: "test2",
result: "img-blocked",
policyLen: 1,
desc: "meta (img-src 'none') should block load"
},
{
/* load image where meta allows load */
query: "test3",
result: "img-loaded",
policyLen: 1,
desc: "meta (img-src http://mochi.test) should allow load"
},
{
/* load image where meta allows but header blocks */
query: "test4", // triggers speculative load
result: "img-blocked",
policyLen: 2,
desc: "meta (img-src http://mochi.test), header (img-src 'none') should block load"
},
{
/* load image where meta blocks but header allows */
query: "test5", // triggers speculative load
result: "img-blocked",
policyLen: 2,
desc: "meta (img-src 'none'), header (img-src http://mochi.test) should block load"
},
{
/* load image where meta allows and header allows */
query: "test6", // triggers speculative load
result: "img-loaded",
policyLen: 2,
desc: "meta (img-src http://mochi.test), header (img-src http://mochi.test) should allow load"
},
{
/* load image where meta1 allows but meta2 blocks */
query: "test7",
result: "img-blocked",
policyLen: 2,
desc: "meta1 (img-src http://mochi.test), meta2 (img-src 'none') should allow blocked"
},
{
/* load image where meta1 allows and meta2 allows */
query: "test8",
result: "img-loaded",
policyLen: 2,
desc: "meta1 (img-src http://mochi.test), meta2 (img-src http://mochi.test) should allow allowed"
},
];
var curTest;
var counter = -1;
function finishTest() {
window.removeEventListener("message", receiveMessage, false);
SimpleTest.finish();
}
function checkResults(result) {
// make sure the image got loaded or blocked
is(result, curTest.result, curTest.query + ": " + curTest.desc);
if (curTest.policyLen != 0) {
// make sure that meta policy got not parsed and appended twice
try {
// get the csp in JSON notation from the principal
var frame = document.getElementById("testframe");
var principal = SpecialPowers.wrap(frame.contentDocument).nodePrincipal;
var cspJSON = principal.cspJSON;
var cspOBJ = JSON.parse(cspJSON);
// make sure that the speculative policy and the actual policy
// are not appended twice.
var policies = cspOBJ["csp-policies"];
is(policies.length, curTest.policyLen, curTest.query + " should have: " + curTest.policyLen + " policies");
}
catch (e) {
ok(false, "uuh, something went wrong within cspToJSON in " + curTest.query);
}
}
// move on to the next test
runNextTest();
}
// a postMessage handler used to bubble up the
// onsuccess/onerror state from within the iframe.
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
checkResults(event.data.result);
}
function runNextTest() {
if (++counter == TESTS.length) {
finishTest();
return;
}
curTest = TESTS[counter];
// load next test
document.getElementById("testframe").src = "file_meta_header_dual.sjs?" + curTest.query;
}
// start the test
SimpleTest.waitForExplicitFinish();
runNextTest();
</script>
</body>
</html>

View File

@ -37,7 +37,6 @@ const UPGRADE_POLICY_NO_DEFAULT_SRC =
"upgrade-insecure-requests;" + // upgrade all http requests to https
"script-src 'unsafe-inline' *"; // we have to whitelist the inline scripts
// in the test.
const NO_UPGRADE_POLICY =
"default-src http: ws: 'unsafe-inline';" + // allow http:// and ws://
"form-action http:;"; // explicit, no fallback to default-src
@ -47,6 +46,7 @@ var tests = [
policy: UPGRADE_POLICY,
topLevelScheme: "https://",
description: "upgrade all requests on toplevel https",
deliveryMethod: "header",
results: [
"iframe-ok", "script-ok", "img-ok", "img-redir-ok", "font-ok", "xhr-ok", "style-ok",
"media-ok", "object-ok", "form-ok", "websocket-ok", "nested-img-ok"
@ -56,6 +56,7 @@ var tests = [
policy: UPGRADE_POLICY,
topLevelScheme: "http://",
description: "upgrade all requests on toplevel http",
deliveryMethod: "header",
results: [
"iframe-ok", "script-ok", "img-ok", "img-redir-ok", "font-ok", "xhr-ok", "style-ok",
"media-ok", "object-ok", "form-ok", "websocket-ok", "nested-img-ok"
@ -66,6 +67,7 @@ var tests = [
policy: UPGRADE_POLICY_NO_DEFAULT_SRC,
topLevelScheme: "http://",
description: "upgrade all requests on toplevel http where default-src is not specified",
deliveryMethod: "header",
results: [
"iframe-ok", "script-ok", "img-ok", "img-redir-ok", "font-ok", "xhr-ok", "style-ok",
"media-ok", "object-ok", "form-ok", "websocket-ok", "nested-img-ok"
@ -75,12 +77,25 @@ var tests = [
policy: NO_UPGRADE_POLICY,
topLevelScheme: "http://",
description: "do not upgrade any requests on toplevel http",
deliveryMethod: "header",
results: [
"iframe-error", "script-error", "img-error", "img-redir-error", "font-error",
"xhr-error", "style-error", "media-error", "object-error", "form-error",
"websocket-error", "nested-img-error"
]
},
{ // (5) test that all requests within an >> https << page using meta CSP get updated
// policy: UPGRADE_POLICY, that test uses UPGRADE_POLICY within
// file_upgrade_insecure_meta.html
// no need to define it within that object.
topLevelScheme: "https://",
description: "upgrade all requests on toplevel https using meta csp",
deliveryMethod: "meta",
results: [
"iframe-ok", "script-ok", "img-ok", "img-redir-ok", "font-ok", "xhr-ok", "style-ok",
"media-ok", "object-ok", "form-ok", "websocket-ok", "nested-img-ok"
]
},
];
var counter = 0;
@ -89,10 +104,16 @@ var curTest;
function loadTestPage() {
curTest = tests[counter++];
var src = curTest.topLevelScheme + "example.com/tests/dom/security/test/csp/file_testserver.sjs?file=";
// append the file that should be served
src += escape("tests/dom/security/test/csp/file_upgrade_insecure.html")
// append the CSP that should be used to serve the file
src += "&csp=" + escape(curTest.policy);
if (curTest.deliveryMethod === "header") {
// append the file that should be served
src += escape("tests/dom/security/test/csp/file_upgrade_insecure.html");
// append the CSP that should be used to serve the file
src += "&csp=" + escape(curTest.policy);
}
else {
src += escape("tests/dom/security/test/csp/file_upgrade_insecure_meta.html");
// no csp here, since it's in the meta element
}
document.getElementById("testframe").src = src;
}

View File

@ -19,17 +19,25 @@
* correct referrer gets sent.
*/
const PRE_POLICY = "upgrade-insecure-requests; default-src https:; ";
var tests = [
{
policy: "referrer origin",
description: "upgrade insecure request with referrer = origin",
query: "test1",
description: "upgrade insecure request with 'referrer = origin' (CSP in header)",
result: "http://example.com"
},
{
policy: "referrer no-referrer",
description: "upgrade insecure request with referrer = no-referrer",
query: "test2",
description: "upgrade insecure request with 'referrer = no-referrer' (CSP in header)",
result: ""
},
{
query: "test3",
description: "upgrade insecure request with 'referrer = origin' (Meta CSP)",
result: "http://example.com"
},
{
query: "test4",
description: "upgrade insecure request with 'referrer = no-referrer' (Meta CSP)",
result: ""
}
];
@ -39,11 +47,9 @@ var curTest;
function loadTestPage() {
curTest = tests[counter++];
var src = "http://example.com/tests/dom/security/test/csp/file_testserver.sjs?file=";
// append the file that should be served
src += escape("tests/dom/security/test/csp/file_upgrade_insecure_referrer.html")
// append the CSP that should be used to serve the file
src += "&csp=" + escape(PRE_POLICY + curTest.policy);
var src = "http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_referrer.sjs?";
// append the query
src += curTest.query;
document.getElementById("testframe").src = src;
}

View File

@ -84,7 +84,7 @@ function makeTest(id, expectedJSON, useReportOnlyPolicy, callback) {
// Load up the policy
// set as report-only if that's the case
csp.appendPolicy(policy, useReportOnlyPolicy);
csp.appendPolicy(policy, useReportOnlyPolicy, false);
// prime the report server
var handler = makeReportHandler("/test" + id, "Test " + id, expectedJSON);

View File

@ -48,7 +48,7 @@ const kNewTab = "new tab";
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
requestLongerTimeout(2);
requestLongerTimeout(3);
// The following "matrices" represent the result of content attempting to
// open a window with window.open with the default feature set. The key of

View File

@ -62,6 +62,7 @@ support-files =
[test_ImageContentLoaded.html]
[test_bug399925.html]
skip-if = buildapp == 'b2g' && debug # Bug 1182951
# [test_bug435296.html]
# disabled - See bug 578591
[test_bug466586.html]

View File

@ -243,6 +243,7 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
aLoadInfo->GetSecurityFlags(),
aLoadInfo->InternalContentPolicyType(),
aLoadInfo->GetUpgradeInsecureRequests(),
aLoadInfo->GetUpgradeInsecurePreloads(),
aLoadInfo->GetInnerWindowID(),
aLoadInfo->GetOuterWindowID(),
aLoadInfo->GetParentOuterWindowID(),
@ -297,6 +298,7 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
loadInfoArgs.securityFlags(),
loadInfoArgs.contentPolicyType(),
loadInfoArgs.upgradeInsecureRequests(),
loadInfoArgs.upgradeInsecurePreloads(),
loadInfoArgs.innerWindowID(),
loadInfoArgs.outerWindowID(),
loadInfoArgs.parentOuterWindowID(),

View File

@ -1654,7 +1654,7 @@ fuzzy-if(Android&&AndroidVersion>=15,8,300) == 625409-1.html 625409-1-ref.html
== 630835-1.html about:blank
== 631352-1.html 631352-1-ref.html
skip-if(!haveTestPlugin) skip-if(B2G||Mulet) fails-if(Android) fuzzy-if(winWidget&&!layersGPUAccelerated,102,535) == 632423-1.html 632423-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(Android||B2G||Mulet) random-if(winWidget) == 632781-verybig.html 632781-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(Android||B2G||Mulet) random-if(winWidget||OSX==1010) == 632781-verybig.html 632781-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== 632781-normalsize.html 632781-ref.html
fuzzy-if(d2d&&/^Windows\x20NT\x206\.2/.test(http.oscpu),1,559) == 633344-1.html 633344-1-ref.html # bug 1103623
== 634232-1.html 634232-1-ref.html

View File

@ -33,6 +33,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
, mInternalContentPolicyType(aContentPolicyType)
, mTainting(LoadTainting::Basic)
, mUpgradeInsecureRequests(false)
, mUpgradeInsecurePreloads(false)
, mInnerWindowID(0)
, mOuterWindowID(0)
, mParentOuterWindowID(0)
@ -79,6 +80,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
}
mUpgradeInsecureRequests = aLoadingContext->OwnerDoc()->GetUpgradeInsecureRequests();
mUpgradeInsecurePreloads = aLoadingContext->OwnerDoc()->GetUpgradeInsecurePreloads();
}
mOriginAttributes = BasePrincipal::Cast(mLoadingPrincipal)->OriginAttributesRef();
@ -92,6 +94,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
, mInternalContentPolicyType(rhs.mInternalContentPolicyType)
, mTainting(rhs.mTainting)
, mUpgradeInsecureRequests(rhs.mUpgradeInsecureRequests)
, mUpgradeInsecurePreloads(rhs.mUpgradeInsecurePreloads)
, mInnerWindowID(rhs.mInnerWindowID)
, mOuterWindowID(rhs.mOuterWindowID)
, mParentOuterWindowID(rhs.mParentOuterWindowID)
@ -109,6 +112,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
nsSecurityFlags aSecurityFlags,
nsContentPolicyType aContentPolicyType,
bool aUpgradeInsecureRequests,
bool aUpgradeInsecurePreloads,
uint64_t aInnerWindowID,
uint64_t aOuterWindowID,
uint64_t aParentOuterWindowID,
@ -122,6 +126,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
, mSecurityFlags(aSecurityFlags)
, mInternalContentPolicyType(aContentPolicyType)
, mUpgradeInsecureRequests(aUpgradeInsecureRequests)
, mUpgradeInsecurePreloads(aUpgradeInsecurePreloads)
, mInnerWindowID(aInnerWindowID)
, mOuterWindowID(aOuterWindowID)
, mParentOuterWindowID(aParentOuterWindowID)
@ -292,6 +297,13 @@ LoadInfo::GetUpgradeInsecureRequests(bool* aResult)
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetUpgradeInsecurePreloads(bool* aResult)
{
*aResult = mUpgradeInsecurePreloads;
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetInnerWindowID(uint64_t* aResult)
{

View File

@ -70,6 +70,7 @@ private:
nsSecurityFlags aSecurityFlags,
nsContentPolicyType aContentPolicyType,
bool aUpgradeInsecureRequests,
bool aUpgradeInsecurePreloads,
uint64_t aInnerWindowID,
uint64_t aOuterWindowID,
uint64_t aParentOuterWindowID,
@ -101,6 +102,7 @@ private:
nsContentPolicyType mInternalContentPolicyType;
LoadTainting mTainting;
bool mUpgradeInsecureRequests;
bool mUpgradeInsecurePreloads;
uint64_t mInnerWindowID;
uint64_t mOuterWindowID;
uint64_t mParentOuterWindowID;

View File

@ -26,7 +26,7 @@ typedef unsigned long nsSecurityFlags;
/**
* An nsILoadOwner represents per-load information about who started the load.
*/
[scriptable, builtinclass, uuid(45a4a9e1-b50d-468a-a01c-43de5c38c8db)]
[scriptable, builtinclass, uuid(542b38c6-1c7b-4630-bd6b-9fee0d1b474d)]
interface nsILoadInfo : nsISupports
{
/**
@ -295,6 +295,11 @@ interface nsILoadInfo : nsISupports
*/
[infallible] readonly attribute boolean upgradeInsecureRequests;
/**
* Same as upgradeInsecureRequests but for preloads.
*/
[infallible] readonly attribute boolean upgradeInsecurePreloads;
/**
* Typically these are the window IDs of the window in which the element being
* loaded lives. However, if the element being loaded is <frame

View File

@ -31,6 +31,7 @@ struct LoadInfoArgs
uint32_t securityFlags;
uint32_t contentPolicyType;
bool upgradeInsecureRequests;
bool upgradeInsecurePreloads;
uint64_t innerWindowID;
uint64_t outerWindowID;
uint64_t parentOuterWindowID;

View File

@ -332,7 +332,15 @@ nsHttpChannel::Connect()
// the CSP directive 'upgrade-insecure-requests', then it's time to fulfill
// the promise to CSP and mixed content blocking to upgrade the channel
// from http to https.
if (mLoadInfo && mLoadInfo->GetUpgradeInsecureRequests()) {
if (mLoadInfo) {
bool isPreload =
(mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD ||
mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD);
bool upgradeRequests =
((isPreload && mLoadInfo->GetUpgradeInsecurePreloads()) ||
(mLoadInfo->GetUpgradeInsecureRequests()));
// Please note that cross origin top level navigations are not subject
// to upgrade-insecure-requests, see:
// http://www.w3.org/TR/upgrade-insecure-requests/#examples
@ -343,7 +351,7 @@ nsHttpChannel::Connect()
(mLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT) &&
(!resultPrincipal->Equals(mLoadInfo->LoadingPrincipal()));
if (!crossOriginNavigation) {
if (upgradeRequests && !crossOriginNavigation) {
// let's log a message to the console that we are upgrading a request
nsAutoCString spec, scheme;
mURI->GetSpec(spec);

View File

@ -1,6 +1,10 @@
function run_test()
{
do_get_profile();
if (!newCacheBackEndUsed()) {
do_check_true(true, "This test checks only cache2 specific behavior.");
return;
}
// Open for write, write
asyncOpenCacheEntry("http://a/", "pin", Ci.nsICacheStorage.OPEN_TRUNCATE, LoadContextInfo.default,

View File

@ -1,6 +1,10 @@
function run_test()
{
do_get_profile();
if (!newCacheBackEndUsed()) {
do_check_true(true, "This test checks only cache2 specific behavior.");
return;
}
var lci = LoadContextInfo.default;
// Open a pinned entry for write, write

View File

@ -26,6 +26,11 @@ function log_(msg) { if (true) dump(">>>>>>>>>>>>> " + msg + "\n"); }
function run_test()
{
do_get_profile();
if (!newCacheBackEndUsed()) {
do_check_true(true, "This test checks only cache2 specific behavior.");
return;
}
var lci = LoadContextInfo.default;
var testingInterface = get_cache_service().QueryInterface(Ci.nsICacheTesting);
do_check_true(testingInterface);

View File

@ -22,6 +22,10 @@ function log_(msg) { if (true) dump(">>>>>>>>>>>>> " + msg + "\n"); }
function run_test()
{
do_get_profile();
if (!newCacheBackEndUsed()) {
do_check_true(true, "This test checks only cache2 specific behavior.");
return;
}
var lci = LoadContextInfo.default;
var testingInterface = get_cache_service().QueryInterface(Ci.nsICacheTesting);
do_check_true(testingInterface);

View File

@ -89,6 +89,10 @@ function run_all_tests() {
var gTests;
function run_test() {
do_get_profile();
if (!newCacheBackEndUsed()) {
do_check_true(true, "This test checks only cache2 specific behavior.");
return;
}
do_test_pending();
httpserv = new HttpServer();
httpserv.registerPathHandler("/cached", cached_handler);

View File

@ -1,3 +1,4 @@
function run_test() {
run_test_in_child("../unit/head_cache2.js");
run_test_in_child("../unit/test_cache_jar.js");
}
}

View File

@ -27,6 +27,9 @@ nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor)
case eSpeculativeLoadBase:
aExecutor->SetSpeculationBase(mUrl);
break;
case eSpeculativeLoadCSP:
aExecutor->AddSpeculationCSP(mMetaCSP);
break;
case eSpeculativeLoadMetaReferrer:
aExecutor->SetSpeculationReferrerPolicy(mReferrerPolicy);
break;

View File

@ -15,6 +15,7 @@ enum eHtml5SpeculativeLoad {
eSpeculativeLoadUninitialized,
#endif
eSpeculativeLoadBase,
eSpeculativeLoadCSP,
eSpeculativeLoadMetaReferrer,
eSpeculativeLoadImage,
eSpeculativeLoadOpenPicture,
@ -41,6 +42,14 @@ class nsHtml5SpeculativeLoad {
mUrl.Assign(aUrl);
}
inline void InitMetaCSP(const nsAString& aCSP) {
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
"Trying to reinitialize a speculative load!");
mOpCode = eSpeculativeLoadCSP;
mMetaCSP.Assign(
nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(aCSP));
}
inline void InitMetaReferrerPolicy(const nsAString& aReferrerPolicy) {
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
"Trying to reinitialize a speculative load!");
@ -187,6 +196,8 @@ class nsHtml5SpeculativeLoad {
eHtml5SpeculativeLoad mOpCode;
nsString mUrl;
nsString mReferrerPolicy;
nsString mMetaCSP;
/**
* If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead]
* then this is the value of the "charset" attribute. For

View File

@ -236,6 +236,14 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName,
}
} else if (nsHtml5Atoms::meta == aName) {
if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
"content-security-policy",
aAttributes->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV))) {
nsString* csp = aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);
if (csp) {
mSpeculativeLoadQueue.AppendElement()->InitMetaCSP(*csp);
}
}
else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
"referrer",
aAttributes->getValue(nsHtml5AttributeName::ATTR_NAME))) {
nsString* referrerPolicy = aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);

View File

@ -6,13 +6,16 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/Likely.h"
#include "mozilla/dom/nsCSPService.h"
#include "nsError.h"
#include "nsHtml5TreeOpExecutor.h"
#include "nsScriptLoader.h"
#include "nsIContentViewer.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocShell.h"
#include "nsIDOMDocument.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptSecurityManager.h"
#include "nsIWebShellServices.h"
@ -1014,6 +1017,43 @@ nsHtml5TreeOpExecutor::SetSpeculationReferrerPolicy(const nsAString& aReferrerPo
return SetSpeculationReferrerPolicy(policy);
}
void
nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP)
{
if (!CSPService::sCSPEnabled) {
return;
}
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsIPrincipal* principal = mDocument->NodePrincipal();
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
nsresult rv = principal->GetPreloadCsp(getter_AddRefs(preloadCsp));
NS_ENSURE_SUCCESS_VOID(rv);
if (!preloadCsp) {
preloadCsp = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
NS_ENSURE_SUCCESS_VOID(rv);
// Store the request context for violation reports
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
rv = preloadCsp->SetRequestContext(domDoc, nullptr);
NS_ENSURE_SUCCESS_VOID(rv);
// set the new csp
rv = principal->SetPreloadCsp(preloadCsp);
NS_ENSURE_SUCCESS_VOID(rv);
}
// please note that meta CSPs and CSPs delivered through a header need
// to be joined together.
rv = preloadCsp->AppendPolicy(aCSP,
false, // csp via meta tag can not be report only
true); // delivered through the meta tag
NS_ENSURE_SUCCESS_VOID(rv);
mDocument->ApplySettingsFromCSP(true);
}
void
nsHtml5TreeOpExecutor::SetSpeculationReferrerPolicy(ReferrerPolicy aReferrerPolicy)
{

View File

@ -275,6 +275,8 @@ class nsHtml5TreeOpExecutor final : public nsHtml5DocumentBuilder,
void SetSpeculationReferrerPolicy(ReferrerPolicy aReferrerPolicy);
void SetSpeculationReferrerPolicy(const nsAString& aReferrerPolicy);
void AddSpeculationCSP(const nsAString& aCSP);
void AddBase(const nsAString& aURL);
static void InitializeStatics();

View File

@ -1,5 +0,0 @@
[combine-header-and-meta-policies.sub.html]
type: testharness
[Expecting logs: ["TEST COMPLETE"\]]
expected: FAIL

View File

@ -1,5 +0,0 @@
[meta-img-src.html]
type: testharness
[Expecting logs: ["PASS","TEST COMPLETE"\]]
expected: FAIL

View File

@ -1,5 +0,0 @@
[meta-modified.html]
type: testharness
[Expecting logs: ["PASS", "PASS","TEST COMPLETE"\]]
expected: FAIL

View File

@ -0,0 +1,3 @@
[close_beforeunload.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1215800

View File

@ -0,0 +1,3 @@
[close_unload.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1215800

View File

@ -1,5 +0,0 @@
[generic.keep-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via fetch-request using the meta-csp\n delivery method with keep-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.no-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via fetch-request using the meta-csp\n delivery method with no-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.swap-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via fetch-request using the meta-csp\n delivery method with swap-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.keep-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via iframe-tag using the meta-csp\n delivery method with keep-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.no-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via iframe-tag using the meta-csp\n delivery method with no-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.swap-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via iframe-tag using the meta-csp\n delivery method with swap-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.keep-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via script-tag using the meta-csp\n delivery method with keep-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.no-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via script-tag using the meta-csp\n delivery method with no-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.swap-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via script-tag using the meta-csp\n delivery method with swap-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.keep-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via xhr-request using the meta-csp\n delivery method with keep-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.no-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via xhr-request using the meta-csp\n delivery method with no-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.swap-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via xhr-request using the meta-csp\n delivery method with swap-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.keep-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an https\n sub-resource via fetch-request using the meta-csp\n delivery method with keep-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.no-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an https\n sub-resource via fetch-request using the meta-csp\n delivery method with no-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.swap-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an https\n sub-resource via fetch-request using the meta-csp\n delivery method with swap-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.keep-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an https\n sub-resource via iframe-tag using the meta-csp\n delivery method with keep-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.no-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an https\n sub-resource via iframe-tag using the meta-csp\n delivery method with no-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.swap-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an https\n sub-resource via iframe-tag using the meta-csp\n delivery method with swap-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.keep-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an https\n sub-resource via script-tag using the meta-csp\n delivery method with keep-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.no-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an https\n sub-resource via script-tag using the meta-csp\n delivery method with no-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.swap-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an https\n sub-resource via script-tag using the meta-csp\n delivery method with swap-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.keep-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an https\n sub-resource via xhr-request using the meta-csp\n delivery method with keep-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.no-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an https\n sub-resource via xhr-request using the meta-csp\n delivery method with no-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.swap-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an https\n sub-resource via xhr-request using the meta-csp\n delivery method with swap-origin-redirect and when\n the target request is cross-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.keep-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via fetch-request using the meta-csp\n delivery method with keep-origin-redirect and when\n the target request is same-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.no-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via fetch-request using the meta-csp\n delivery method with no-redirect and when\n the target request is same-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.swap-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via fetch-request using the meta-csp\n delivery method with swap-origin-redirect and when\n the target request is same-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.keep-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via iframe-tag using the meta-csp\n delivery method with keep-origin-redirect and when\n the target request is same-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.no-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via iframe-tag using the meta-csp\n delivery method with no-redirect and when\n the target request is same-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.swap-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via iframe-tag using the meta-csp\n delivery method with swap-origin-redirect and when\n the target request is same-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.keep-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via script-tag using the meta-csp\n delivery method with keep-origin-redirect and when\n the target request is same-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.no-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via script-tag using the meta-csp\n delivery method with no-redirect and when\n the target request is same-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.swap-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via script-tag using the meta-csp\n delivery method with swap-origin-redirect and when\n the target request is same-origin.]
expected: FAIL

View File

@ -1,5 +0,0 @@
[generic.keep-origin-redirect.http.html]
type: testharness
[The referrer URL is omitted when a\n document served over http requires an http\n sub-resource via xhr-request using the meta-csp\n delivery method with keep-origin-redirect and when\n the target request is same-origin.]
expected: FAIL

Some files were not shown because too many files have changed in this diff Show More