Bug 1496034 - Apply bz's comments to FeaturePolicy, r=bz

This commit is contained in:
Andrea Marchesini
2018-10-12 09:36:33 +02:00
parent f8add49a23
commit b51e9d489e
20 changed files with 640 additions and 306 deletions

View File

@@ -3024,27 +3024,19 @@ nsIDocument::InitFeaturePolicy(nsIChannel* aChannel)
return NS_OK;
}
nsAutoString origin;
nsresult rv = nsContentUtils::GetUTFOrigin(NodePrincipal(), origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mFeaturePolicy->SetDefaultOrigin(origin);
mFeaturePolicy->SetDefaultOrigin(NodePrincipal());
RefPtr<FeaturePolicy> parentPolicy = nullptr;
if (mDocumentContainer) {
nsPIDOMWindowOuter* containerWindow = mDocumentContainer->GetWindow();
if (containerWindow) {
nsCOMPtr<nsINode> node = containerWindow->GetFrameElementInternal();
if (node) {
HTMLIFrameElement* iframe = HTMLIFrameElement::FromNode(node);
HTMLIFrameElement* iframe = HTMLIFrameElement::FromNodeOrNull(node);
if (iframe) {
parentPolicy = iframe->Policy();
}
}
}
}
if (parentPolicy) {
// Let's inherit the policy from the parent HTMLIFrameElement if it exists.
@@ -3052,7 +3044,7 @@ nsIDocument::InitFeaturePolicy(nsIChannel* aChannel)
}
nsCOMPtr<nsIHttpChannel> httpChannel;
rv = GetHttpChannelHelper(aChannel, getter_AddRefs(httpChannel));
nsresult rv = GetHttpChannelHelper(aChannel, getter_AddRefs(httpChannel));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@@ -3067,8 +3059,7 @@ nsIDocument::InitFeaturePolicy(nsIChannel* aChannel)
value);
if (NS_SUCCEEDED(rv)) {
mFeaturePolicy->SetDeclaredPolicy(this, NS_ConvertUTF8toUTF16(value),
origin, EmptyString(),
false /* 'src' enabled */);
NodePrincipal(), nullptr);
}
return NS_OK;
@@ -10231,7 +10222,8 @@ nsIDocument::Policy() const
MOZ_ASSERT(StaticPrefs::dom_security_featurePolicy_enabled());
// The policy is created when the document is initialized. We _must_ have a
// policy here.
// policy here even if the featurePolicy pref is off. If this assertion fails,
// it means that ::Policy() is called before ::StartDocumentLoad().
MOZ_ASSERT(mFeaturePolicy);
return mFeaturePolicy;
}

View File

@@ -8,6 +8,7 @@
#include "mozilla/dom/HTMLIFrameElementBinding.h"
#include "mozilla/dom/FeaturePolicy.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/StaticPrefs.h"
#include "nsMappedAttributes.h"
#include "nsAttrValueInlines.h"
@@ -22,6 +23,24 @@ NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(IFrame)
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLIFrameElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLIFrameElement,
nsGenericHTMLFrameElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFeaturePolicy)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLIFrameElement,
nsGenericHTMLFrameElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFeaturePolicy)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ADDREF_INHERITED(HTMLIFrameElement, nsGenericHTMLFrameElement)
NS_IMPL_RELEASE_INHERITED(HTMLIFrameElement, nsGenericHTMLFrameElement)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(HTMLIFrameElement)
NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLFrameElement)
// static
const DOMTokenListSupportedToken HTMLIFrameElement::sSupportedSandboxTokens[] = {
#define SANDBOX_KEYWORD(string, atom, flags) string,
@@ -34,10 +53,9 @@ HTMLIFrameElement::HTMLIFrameElement(already_AddRefed<mozilla::dom::NodeInfo>&&
FromParser aFromParser)
: nsGenericHTMLFrameElement(std::move(aNodeInfo), aFromParser)
{
if (StaticPrefs::dom_security_featurePolicy_enabled()) {
// We always need a featurePolicy, even if not exposed.
mFeaturePolicy = new FeaturePolicy(this);
}
}
HTMLIFrameElement::~HTMLIFrameElement()
{
@@ -174,6 +192,7 @@ HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
}
if ((aName == nsGkAtoms::allow ||
aName == nsGkAtoms::src ||
aName == nsGkAtoms::srcdoc ||
aName == nsGkAtoms::sandbox ||
aName == nsGkAtoms::allowpaymentrequest) &&
StaticPrefs::dom_security_featurePolicy_enabled()) {
@@ -236,41 +255,29 @@ HTMLIFrameElement::Policy() const
}
nsresult
HTMLIFrameElement::GetFeaturePolicyDefaultOrigin(nsAString& aDefaultOrigin) const
HTMLIFrameElement::GetFeaturePolicyDefaultOrigin(nsIPrincipal** aPrincipal) const
{
aDefaultOrigin.Truncate();
nsCOMPtr<nsIPrincipal> principal;
nsresult rv;
nsAutoString src;
GetURIAttr(nsGkAtoms::src, nullptr, src);
if (HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc)) {
principal = NodePrincipal();
}
if (!principal) {
nsCOMPtr<nsIURI> nodeURI;
if (!src.IsEmpty()) {
nsCOMPtr<nsIURI> baseURI = OwnerDoc()->GetBaseURI();
rv = NS_NewURI(getter_AddRefs(nodeURI), src,
OwnerDoc()->GetDocumentCharacterSet(),
baseURI);
if (NS_WARN_IF(NS_FAILED(rv))) {
nodeURI = nullptr;
if (GetURIAttr(nsGkAtoms::src, nullptr, getter_AddRefs(nodeURI)) &&
nodeURI) {
principal =
BasePrincipal::CreateCodebasePrincipal(nodeURI,
BasePrincipal::Cast(NodePrincipal())->OriginAttributesRef());
}
}
if (!nodeURI) {
if (OwnerDoc()->GetSandboxFlags() & SANDBOXED_ORIGIN) {
return NS_OK;
if (!principal) {
principal = NodePrincipal();
}
nodeURI = OwnerDoc()->GetDocumentURI();
}
nsAutoString origin;
rv = nsContentUtils::GetUTFOrigin(nodeURI, origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
aDefaultOrigin.Assign(origin);
principal.forget(aPrincipal);
return NS_OK;
}
@@ -281,29 +288,22 @@ HTMLIFrameElement::RefreshFeaturePolicy()
mFeaturePolicy->ResetDeclaredPolicy();
// The origin can change if 'src' attribute changes.
nsAutoString origin;
nsresult rv = GetFeaturePolicyDefaultOrigin(origin);
nsCOMPtr<nsIPrincipal> origin;
nsresult rv = GetFeaturePolicyDefaultOrigin(getter_AddRefs(origin));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
MOZ_ASSERT(origin);
mFeaturePolicy->SetDefaultOrigin(origin);
nsAutoString allow;
GetAttr(nsGkAtoms::allow, allow);
if (!allow.IsEmpty()) {
nsAutoString documentOrigin;
if (OwnerDoc()->GetSandboxFlags() ^ SANDBOXED_ORIGIN) {
nsresult rv = nsContentUtils::GetUTFOrigin(NodePrincipal(), documentOrigin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
}
// Set or reset the FeaturePolicy directives.
mFeaturePolicy->SetDeclaredPolicy(OwnerDoc(), allow, documentOrigin,
origin, true /* 'src' enabled */);
mFeaturePolicy->SetDeclaredPolicy(OwnerDoc(), allow, NodePrincipal(),
origin);
}
mFeaturePolicy->InheritPolicy(OwnerDoc()->Policy());

View File

@@ -8,6 +8,7 @@
#define mozilla_dom_HTMLIFrameElement_h
#include "mozilla/Attributes.h"
#include "mozilla/dom/FeaturePolicy.h"
#include "nsGenericHTMLFrameElement.h"
#include "nsDOMTokenList.h"
@@ -23,7 +24,8 @@ public:
NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLIFrameElement, iframe)
// nsISupports
NS_INLINE_DECL_REFCOUNTING_INHERITED(HTMLIFrameElement,
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLIFrameElement,
nsGenericHTMLFrameElement)
// Element
@@ -223,8 +225,13 @@ private:
void RefreshFeaturePolicy();
// Implements the declared-origin algorithm as described in Feature-Policy
// spec: https://wicg.github.io/feature-policy/#declared-origin
// If this iframe has a 'src' attribute, the origin will be the parsing of its
// value as URL. If the URL is invalid, or 'src' attribute doesn't exist, the
// origin will be the document's origin.
nsresult
GetFeaturePolicyDefaultOrigin(nsAString& aDefaultOrigin) const;
GetFeaturePolicyDefaultOrigin(nsIPrincipal** aDefaultOrigin) const;
/**
* This function is called by AfterSetAttr and OnAttrSetButNotChanged.
@@ -236,6 +243,8 @@ private:
* @param aNotify Whether we plan to notify document observers.
*/
void AfterMaybeChangeAttr(int32_t aNamespaceID, nsAtom* aName, bool aNotify);
RefPtr<mozilla::dom::FeaturePolicy> mFeaturePolicy;
};
} // namespace dom

View File

@@ -35,7 +35,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement,
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOpenerWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserElementAPI)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFeaturePolicy)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGenericHTMLFrameElement,
@@ -47,7 +46,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGenericHTMLFrameElement,
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameLoader)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpenerWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserElementAPI)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFeaturePolicy)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(nsGenericHTMLFrameElement,

View File

@@ -10,7 +10,6 @@
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/nsBrowserElement.h"
#include "mozilla/dom/FeaturePolicy.h"
#include "nsFrameLoader.h"
#include "nsGenericHTMLElement.h"
@@ -128,9 +127,6 @@ protected:
nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal;
// Used by <iframe> only.
RefPtr<mozilla::dom::FeaturePolicy> mFeaturePolicy;
/**
* True if we have already loaded the frame's original src
*/

View File

@@ -5,18 +5,20 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Feature.h"
#include "mozilla/BasePrincipal.h"
using namespace mozilla::dom;
namespace mozilla {
namespace dom {
void
Feature::GetWhiteListedOrigins(nsTArray<nsString>& aList) const
Feature::GetAllowList(nsTArray<nsCOMPtr<nsIPrincipal>>& aList) const
{
MOZ_ASSERT(mPolicy == eWhiteList);
aList.AppendElements(mWhiteListedOrigins);
MOZ_ASSERT(mPolicy == eAllowList);
aList.AppendElements(mAllowList);
}
bool
Feature::Allows(const nsAString& aOrigin) const
Feature::Allows(nsIPrincipal* aPrincipal) const
{
if (mPolicy == eNone) {
return false;
@@ -26,18 +28,12 @@ Feature::Allows(const nsAString& aOrigin) const
return true;
}
for (const nsString& whiteListedOrigin : mWhiteListedOrigins) {
if (whiteListedOrigin.Equals(aOrigin)) {
return true;
}
}
return false;
return AllowListContains(aPrincipal);
}
Feature::Feature(const nsAString& aFeatureName)
: mFeatureName(aFeatureName)
, mPolicy(eWhiteList)
, mPolicy(eAllowList)
{}
Feature::~Feature() = default;
@@ -52,7 +48,7 @@ void
Feature::SetAllowsNone()
{
mPolicy = eNone;
mWhiteListedOrigins.Clear();
mAllowList.Clear();
}
bool
@@ -65,7 +61,7 @@ void
Feature::SetAllowsAll()
{
mPolicy = eAll;
mWhiteListedOrigins.Clear();
mAllowList.Clear();
}
bool
@@ -75,24 +71,38 @@ Feature::AllowsAll() const
}
void
Feature::AppendOriginToWhiteList(const nsAString& aOrigin)
Feature::AppendToAllowList(nsIPrincipal* aPrincipal)
{
mPolicy = eWhiteList;
mWhiteListedOrigins.AppendElement(aOrigin);
MOZ_ASSERT(aPrincipal);
mPolicy = eAllowList;
mAllowList.AppendElement(aPrincipal);
}
bool
Feature::WhiteListContains(const nsAString& aOrigin) const
Feature::AllowListContains(nsIPrincipal* aPrincipal) const
{
if (!IsWhiteList()) {
MOZ_ASSERT(aPrincipal);
if (!HasAllowList()) {
return false;
}
return mWhiteListedOrigins.Contains(aOrigin);
for (nsIPrincipal* principal : mAllowList) {
if (BasePrincipal::Cast(principal)->Subsumes(aPrincipal,
BasePrincipal::ConsiderDocumentDomain)) {
return true;
}
}
return false;
}
bool
Feature::IsWhiteList() const
Feature::HasAllowList() const
{
return mPolicy == eWhiteList;
return mPolicy == eAllowList;
}
} // dom namespace
} // mozilla namespace

View File

@@ -11,6 +11,8 @@
#include "nsTArray.h"
#include "nsCOMPtr.h"
class nsIPrincipal;
namespace mozilla {
namespace dom {
@@ -37,19 +39,19 @@ public:
AllowsAll() const;
void
AppendOriginToWhiteList(const nsAString& aOrigin);
AppendToAllowList(nsIPrincipal* aPrincipal);
void
GetWhiteListedOrigins(nsTArray<nsString>& aList) const;
GetAllowList(nsTArray<nsCOMPtr<nsIPrincipal>>& aList) const;
bool
WhiteListContains(const nsAString& aOrigin) const;
AllowListContains(nsIPrincipal* aPrincipal) const;
bool
IsWhiteList() const;
HasAllowList() const;
bool
Allows(const nsAString& aOrigin) const;
Allows(nsIPrincipal* aPrincipal) const;
private:
nsString mFeatureName;
@@ -62,12 +64,12 @@ private:
eAll,
// denotes a policy of "feature bar.com foo.com"
eWhiteList,
eAllowList,
};
Policy mPolicy;
nsTArray<nsString> mWhiteListedOrigins;
nsTArray<nsCOMPtr<nsIPrincipal>> mAllowList;
};
} // dom namespace

View File

@@ -9,8 +9,10 @@
#include "mozilla/dom/FeaturePolicyParser.h"
#include "mozilla/dom/FeaturePolicyUtils.h"
#include "nsContentUtils.h"
#include "nsNetUtil.h"
using namespace mozilla::dom;
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FeaturePolicy, mParentNode)
NS_IMPL_CYCLE_COLLECTING_ADDREF(FeaturePolicy)
@@ -34,7 +36,7 @@ FeaturePolicy::InheritPolicy(FeaturePolicy* aParentPolicy)
RefPtr<FeaturePolicy> dest = this;
RefPtr<FeaturePolicy> src = aParentPolicy;
nsString origin = mDefaultOrigin;
nsCOMPtr<nsIPrincipal> origin = mDefaultOrigin;
FeaturePolicyUtils::ForEachFeature([dest, src, origin](const char* aFeatureName) {
nsString featureName;
featureName.AppendASCII(aFeatureName);
@@ -86,9 +88,8 @@ FeaturePolicy::HasDeclaredFeature(const nsAString& aFeatureName) const
void
FeaturePolicy::SetDeclaredPolicy(nsIDocument* aDocument,
const nsAString& aPolicyString,
const nsAString& aSelfOrigin,
const nsAString& aSrcOrigin,
bool aSrcEnabled)
nsIPrincipal* aSelfOrigin,
nsIPrincipal* aSrcOrigin)
{
ResetDeclaredPolicy();
@@ -96,7 +97,6 @@ FeaturePolicy::SetDeclaredPolicy(nsIDocument* aDocument,
aDocument,
aSelfOrigin,
aSrcOrigin,
aSrcEnabled,
mFeatures));
}
@@ -116,16 +116,32 @@ bool
FeaturePolicy::AllowsFeature(const nsAString& aFeatureName,
const Optional<nsAString>& aOrigin) const
{
return AllowsFeatureInternal(aFeatureName,
aOrigin.WasPassed()
? aOrigin.Value()
: mDefaultOrigin);
nsCOMPtr<nsIPrincipal> origin;
if (aOrigin.WasPassed()) {
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), aOrigin.Value());
if (NS_FAILED(rv)) {
return false;
}
origin = BasePrincipal::CreateCodebasePrincipal(uri,
BasePrincipal::Cast(mDefaultOrigin)->OriginAttributesRef());
} else {
origin = mDefaultOrigin;
}
if (NS_WARN_IF(!origin)) {
return false;
}
return AllowsFeatureInternal(aFeatureName, origin);
}
bool
FeaturePolicy::AllowsFeatureInternal(const nsAString& aFeatureName,
const nsAString& aOrigin) const
nsIPrincipal* aOrigin) const
{
MOZ_ASSERT(aOrigin);
// Let's see if have to disable this feature because inherited policy.
if (HasInheritedDeniedFeature(aFeatureName)) {
return false;
@@ -137,8 +153,22 @@ FeaturePolicy::AllowsFeatureInternal(const nsAString& aFeatureName,
}
}
return FeaturePolicyUtils::AllowDefaultFeature(aFeatureName, mDefaultOrigin,
aOrigin);
switch (FeaturePolicyUtils::DefaultAllowListFeature(aFeatureName)) {
case FeaturePolicyUtils::FeaturePolicyValue::eAll:
return true;
case FeaturePolicyUtils::FeaturePolicyValue::eSelf:
return BasePrincipal::Cast(mDefaultOrigin)->Subsumes(aOrigin,
BasePrincipal::ConsiderDocumentDomain);
case FeaturePolicyUtils::FeaturePolicyValue::eNone:
return false;
default:
MOZ_CRASH("Unknown default value");
}
return false;
}
void
@@ -170,16 +200,44 @@ FeaturePolicy::GetAllowlistForFeature(const nsAString& aFeatureName,
return;
}
feature.GetWhiteListedOrigins(aList);
nsTArray<nsCOMPtr<nsIPrincipal>> list;
feature.GetAllowList(list);
for (nsIPrincipal* principal : list) {
nsAutoCString originNoSuffix;
nsresult rv = principal->GetOriginNoSuffix(originNoSuffix);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
aList.AppendElement(NS_ConvertUTF8toUTF16(originNoSuffix));
}
return;
}
}
nsString defaultAllowList;
FeaturePolicyUtils::DefaultAllowListFeature(aFeatureName, mDefaultOrigin,
defaultAllowList);
if (!defaultAllowList.IsEmpty()) {
aList.AppendElement(defaultAllowList);
switch (FeaturePolicyUtils::DefaultAllowListFeature(aFeatureName)) {
case FeaturePolicyUtils::FeaturePolicyValue::eAll:
aList.AppendElement(NS_LITERAL_STRING("*"));
return;
case FeaturePolicyUtils::FeaturePolicyValue::eSelf:
{
nsAutoCString originNoSuffix;
nsresult rv = mDefaultOrigin->GetOriginNoSuffix(originNoSuffix);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
aList.AppendElement(NS_ConvertUTF8toUTF16(originNoSuffix));
return;
}
case FeaturePolicyUtils::FeaturePolicyValue::eNone:
return;
default:
MOZ_CRASH("Unknown default value");
}
}
@@ -197,3 +255,6 @@ FeaturePolicy::MaybeSetAllowedPolicy(const nsAString& aFeatureName)
mFeatures.AppendElement(feature);
}
} // dom namespace
} // mozilla namespace

View File

@@ -30,12 +30,12 @@
* these policies:
* - eNone - the feature is fully disabled.
* - eAll - the feature is allowed.
* - eWhitelist - the feature is allowed for a list of origins.
* - eAllowList - the feature is allowed for a list of origins.
*
* An interesting element of FeaturePolicy is the inheritance: each context
* inherits the feature-policy directives from the parent context, if it exists.
* When a context inherits a policy for feature X, it only knows if that feature
* is allowed or denied (it ignores the list of whitelist origins for instance).
* is allowed or denied (it ignores the list of allowed origins for instance).
* This information is stored in an array of inherited feature strings because
* we care only to know when they are denied.
*
@@ -72,19 +72,17 @@ public:
explicit FeaturePolicy(nsINode* aNode);
// A FeaturePolicy must have a default origin, if not in a sandboxed context.
// A FeaturePolicy must have a default origin.
// This method must be called before any other exposed WebIDL method or before
// checking if a feature is allowed.
void
SetDefaultOrigin(const nsAString& aOrigin)
SetDefaultOrigin(nsIPrincipal* aPrincipal)
{
// aOrigin can be an empty string if this is a opaque origin.
mDefaultOrigin = aOrigin;
mDefaultOrigin = aPrincipal;
}
const nsAString& DefaultOrigin() const
nsIPrincipal* DefaultOrigin() const
{
// Returns an empty string if this is an opaque origin.
return mDefaultOrigin;
}
@@ -97,9 +95,8 @@ public:
void
SetDeclaredPolicy(nsIDocument* aDocument,
const nsAString& aPolicyString,
const nsAString& aSelfOrigin,
const nsAString& aSrcOrigin,
bool aSrcEnabled);
nsIPrincipal* aSelfOrigin,
nsIPrincipal* aSrcOrigin);
// This method creates a policy for aFeatureName allowing it to '*' if it
// doesn't exist yet. It's used by HTMLIFrameElement to enable features by
@@ -140,9 +137,12 @@ public:
private:
~FeaturePolicy() = default;
// This method returns true if the aFeatureName is allowed for aOrigin,
// following the feature-policy directives. See the comment at the top of this
// file.
bool
AllowsFeatureInternal(const nsAString& aFeatureName,
const nsAString& aOrigin) const;
nsIPrincipal* aOrigin) const;
// Inherits a single denied feature from the parent context.
void
@@ -151,6 +151,7 @@ private:
bool
HasInheritedDeniedFeature(const nsAString& aFeatureName) const;
// This returns true if we have a declared feature policy for aFeatureName.
bool
HasDeclaredFeature(const nsAString& aFeatureName) const;
@@ -163,7 +164,7 @@ private:
// Feature policy for the current context.
nsTArray<Feature> mFeatures;
nsString mDefaultOrigin;
nsCOMPtr<nsIPrincipal> mDefaultOrigin;
};
} // dom namespace

View File

@@ -13,8 +13,8 @@
#include "nsIURI.h"
#include "nsNetUtil.h"
using namespace mozilla;
using namespace mozilla::dom;
namespace mozilla {
namespace dom {
namespace {
@@ -65,11 +65,12 @@ ReportToConsoleInvalidAllowValue(nsIDocument* aDocument,
/* static */ bool
FeaturePolicyParser::ParseString(const nsAString& aPolicy,
nsIDocument* aDocument,
const nsAString& aSelfOrigin,
const nsAString& aSrcOrigin,
bool aSrcEnabled,
nsIPrincipal* aSelfOrigin,
nsIPrincipal* aSrcOrigin,
nsTArray<Feature>& aParsedFeatures)
{
MOZ_ASSERT(aSelfOrigin);
nsTArray<nsTArray<nsString>> tokens;
PolicyTokenizer::tokenizePolicy(aPolicy, tokens);
@@ -88,9 +89,8 @@ FeaturePolicyParser::ParseString(const nsAString& aPolicy,
Feature feature(featureTokens[0]);
if (featureTokens.Length() == 1) {
if (aSrcEnabled) {
// Note that this src origin can be empty if opaque.
feature.AppendOriginToWhiteList(aSrcOrigin);
if (aSrcOrigin) {
feature.AppendToAllowList(aSrcOrigin);
} else {
ReportToConsoleInvalidEmptyAllowValue(aDocument, featureTokens[0]);
continue;
@@ -110,18 +110,12 @@ FeaturePolicyParser::ParseString(const nsAString& aPolicy,
}
if (curVal.LowerCaseEqualsASCII("'self'")) {
// Opaque origins are passed as empty string.
if (!aSelfOrigin.IsEmpty()) {
feature.AppendOriginToWhiteList(aSelfOrigin);
}
feature.AppendToAllowList(aSelfOrigin);
continue;
}
if (aSrcEnabled && curVal.LowerCaseEqualsASCII("'src'")) {
// Opaque origins are passed as empty string.
if (!aSrcOrigin.IsEmpty()) {
feature.AppendOriginToWhiteList(aSrcOrigin);
}
if (aSrcOrigin && curVal.LowerCaseEqualsASCII("'src'")) {
feature.AppendToAllowList(aSrcOrigin);
continue;
}
@@ -132,14 +126,15 @@ FeaturePolicyParser::ParseString(const nsAString& aPolicy,
continue;
}
nsAutoString origin;
rv = nsContentUtils::GetUTFOrigin(uri, origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
nsCOMPtr<nsIPrincipal> origin =
BasePrincipal::CreateCodebasePrincipal(uri,
BasePrincipal::Cast(aSelfOrigin)->OriginAttributesRef());
if (NS_WARN_IF(!origin)) {
ReportToConsoleInvalidAllowValue(aDocument, curVal);
continue;
}
feature.AppendOriginToWhiteList(origin);
feature.AppendToAllowList(origin);
}
}
@@ -160,3 +155,6 @@ FeaturePolicyParser::ParseString(const nsAString& aPolicy,
aParsedFeatures.SwapElements(parsedFeatures);
return true;
}
} // dom namespace
} // mozilla namespace

View File

@@ -10,7 +10,7 @@
#include "nsString.h"
class nsIDocument;
class nsIURI;
class nsIPrincipal;
namespace mozilla {
namespace dom {
@@ -20,14 +20,13 @@ class Feature;
class FeaturePolicyParser final
{
public:
// aSelfOrigin must not be empty. if aSrcOrigin is empty, the parsing will not
// aSelfOrigin must not be null. if aSrcOrigin is null, the parsing will not
// support 'src' as valid allow directive value.
static bool
ParseString(const nsAString& aPolicy,
nsIDocument* aDocument,
const nsAString& aSelfOrigin,
const nsAString& aSrcOrigin,
bool aSrcEnabled,
nsIPrincipal* aSelfOrigin,
nsIPrincipal* aSrcOrigin,
nsTArray<Feature>& aParsedFeatures);
};

View File

@@ -9,15 +9,12 @@
#include "mozilla/StaticPrefs.h"
#include "nsIDocument.h"
using namespace mozilla::dom;
namespace mozilla {
namespace dom {
struct FeatureMap {
const char* mFeatureName;
enum {
eAll,
eSelf,
} mDefaultAllowList;
FeaturePolicyUtils::FeaturePolicyValue mDefaultAllowList;
};
/*
@@ -25,17 +22,17 @@ struct FeatureMap {
* DOM Security peer!
*/
static FeatureMap sSupportedFeatures[] = {
{ "autoplay", FeatureMap::eAll },
{ "camera", FeatureMap::eAll },
{ "encrypted-media", FeatureMap::eAll },
{ "fullscreen", FeatureMap::eAll },
{ "geolocation", FeatureMap::eAll },
{ "microphone", FeatureMap::eAll },
{ "midi", FeatureMap::eAll },
{ "payment", FeatureMap::eAll },
{ "autoplay", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "camera", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "encrypted-media", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "fullscreen", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "geolocation", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "microphone", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "midi", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "payment", FeaturePolicyUtils::FeaturePolicyValue::eAll },
// TODO: not supported yet!!!
{ "speaker", FeatureMap::eAll },
{ "vr", FeatureMap::eAll },
{ "speaker", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "vr", FeaturePolicyUtils::FeaturePolicyValue::eAll },
};
/* static */ bool
@@ -59,51 +56,17 @@ FeaturePolicyUtils::ForEachFeature(const std::function<void(const char*)>& aCall
}
}
/* static */ void
FeaturePolicyUtils::DefaultAllowListFeature(const nsAString& aFeatureName,
const nsAString& aDefaultOrigin,
nsAString& aDefaultAllowList)
/* static */ FeaturePolicyUtils::FeaturePolicyValue
FeaturePolicyUtils::DefaultAllowListFeature(const nsAString& aFeatureName)
{
uint32_t numFeatures = (sizeof(sSupportedFeatures) / sizeof(sSupportedFeatures[0]));
for (uint32_t i = 0; i < numFeatures; ++i) {
if (aFeatureName.LowerCaseEqualsASCII(sSupportedFeatures[i].mFeatureName)) {
switch (sSupportedFeatures[i].mDefaultAllowList) {
case FeatureMap::eAll:
aDefaultAllowList.AppendASCII("*");
return;
case FeatureMap::eSelf:
aDefaultAllowList = aDefaultOrigin;
return;
default:
MOZ_CRASH("Unknown default value");
}
}
return sSupportedFeatures[i].mDefaultAllowList;
}
}
/* static */ bool
FeaturePolicyUtils::AllowDefaultFeature(const nsAString& aFeatureName,
const nsAString& aDefaultOrigin,
const nsAString& aOrigin)
{
uint32_t numFeatures = (sizeof(sSupportedFeatures) / sizeof(sSupportedFeatures[0]));
for (uint32_t i = 0; i < numFeatures; ++i) {
if (aFeatureName.LowerCaseEqualsASCII(sSupportedFeatures[i].mFeatureName)) {
switch (sSupportedFeatures[i].mDefaultAllowList) {
case FeatureMap::eAll:
return true;
case FeatureMap::eSelf:
return aDefaultOrigin == aOrigin;
default:
MOZ_CRASH("Unknown default value");
}
return true;
}
}
return false;
return FeaturePolicyValue::eNone;
}
/* static */ bool
@@ -125,3 +88,6 @@ FeaturePolicyUtils::IsFeatureAllowed(nsIDocument* aDocument,
return policy->AllowsFeatureInternal(aFeatureName, policy->DefaultOrigin());
}
} // dom namespace
} // mozilla namespace

View File

@@ -18,25 +18,36 @@ namespace dom {
class FeaturePolicyUtils final
{
public:
enum FeaturePolicyValue
{
// Feature always allowed.
eAll,
// Feature allowed for documents that are same-origin with this one.
eSelf,
// Feature denied.
eNone,
};
// This method returns true if aFeatureName is allowed for aDocument.
// Use this method everywhere you need to check feature-policy directives.
static bool
IsFeatureAllowed(nsIDocument* aDocument,
const nsAString& aFeatureName);
// Returns true if aFeatureName is a known feature policy name.
static bool
IsSupportedFeature(const nsAString& aFeatureName);
// Runs aCallback for each known feature policy, with the feature name as
// argument.
static void
ForEachFeature(const std::function<void(const char*)>& aCallback);
static void
DefaultAllowListFeature(const nsAString& aFeatureName,
const nsAString& aDefaultOrigin,
nsAString& aDefaultAllowList);
static bool
AllowDefaultFeature(const nsAString& aFeatureName,
const nsAString& aDefaultOrigin,
const nsAString& aOrigin);
// Returns the default policy value for aFeatureName.
static FeaturePolicyValue
DefaultAllowListFeature(const nsAString& aFeatureName);
};
} // dom namespace

View File

@@ -5,27 +5,30 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/dom/Feature.h"
#include "mozilla/dom/FeaturePolicyParser.h"
#include "nsNetUtil.h"
#include "nsTArray.h"
using namespace mozilla;
using namespace mozilla::dom;
#define URL_SELF NS_LITERAL_STRING("https://example.com")
#define URL_EXAMPLE_COM NS_LITERAL_STRING("http://example.com")
#define URL_EXAMPLE_NET NS_LITERAL_STRING("http://example.net")
#define URL_SELF NS_LITERAL_CSTRING("https://example.com")
#define URL_EXAMPLE_COM NS_LITERAL_CSTRING("http://example.com")
#define URL_EXAMPLE_NET NS_LITERAL_CSTRING("http://example.net")
void
CheckParser(const nsAString& aInput, bool aExpectedResults,
uint32_t aExpectedFeatures, nsTArray<Feature>& aParsedFeatures)
{
nsCOMPtr<nsIPrincipal> principal =
mozilla::BasePrincipal::CreateCodebasePrincipal(URL_SELF);
nsTArray<Feature> parsedFeatures;
ASSERT_TRUE(FeaturePolicyParser::ParseString(aInput,
nullptr,
URL_SELF,
EmptyString(),
true, // 'src' enabled
principal,
principal,
parsedFeatures) == aExpectedResults);
ASSERT_TRUE(parsedFeatures.Length() == aExpectedFeatures);
@@ -34,6 +37,13 @@ CheckParser(const nsAString& aInput, bool aExpectedResults,
TEST(FeaturePolicyParser, Basic)
{
nsCOMPtr<nsIPrincipal> selfPrincipal =
mozilla::BasePrincipal::CreateCodebasePrincipal(URL_SELF);
nsCOMPtr<nsIPrincipal> exampleComPrincipal =
mozilla::BasePrincipal::CreateCodebasePrincipal(URL_EXAMPLE_COM);
nsCOMPtr<nsIPrincipal> exampleNetPrincipal =
mozilla::BasePrincipal::CreateCodebasePrincipal(URL_EXAMPLE_NET);
nsTArray<Feature> parsedFeatures;
// Empty string is a valid policy.
@@ -50,70 +60,70 @@ TEST(FeaturePolicyParser, Basic)
// Existing feature with no allowed values
CheckParser(NS_LITERAL_STRING("camera"), true, 1, parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].IsWhiteList());
ASSERT_TRUE(parsedFeatures[0].HasAllowList());
// Some spaces.
CheckParser(NS_LITERAL_STRING(" camera "), true, 1, parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].IsWhiteList());
ASSERT_TRUE(parsedFeatures[0].HasAllowList());
// A random ;
CheckParser(NS_LITERAL_STRING("camera;"), true, 1, parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].IsWhiteList());
ASSERT_TRUE(parsedFeatures[0].HasAllowList());
// Another random ;
CheckParser(NS_LITERAL_STRING(";camera;"), true, 1, parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].IsWhiteList());
ASSERT_TRUE(parsedFeatures[0].HasAllowList());
// 2 features
CheckParser(NS_LITERAL_STRING("camera;microphone"), true, 2, parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].IsWhiteList());
ASSERT_TRUE(parsedFeatures[0].HasAllowList());
ASSERT_TRUE(parsedFeatures[1].Name().Equals(NS_LITERAL_STRING("microphone")));
ASSERT_TRUE(parsedFeatures[1].IsWhiteList());
ASSERT_TRUE(parsedFeatures[1].HasAllowList());
// 2 features with spaces
CheckParser(NS_LITERAL_STRING(" camera ; microphone "), true, 2,
parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].IsWhiteList());
ASSERT_TRUE(parsedFeatures[0].HasAllowList());
ASSERT_TRUE(parsedFeatures[1].Name().Equals(NS_LITERAL_STRING("microphone")));
ASSERT_TRUE(parsedFeatures[1].IsWhiteList());
ASSERT_TRUE(parsedFeatures[1].HasAllowList());
// 3 features, but only 2 exist.
CheckParser(NS_LITERAL_STRING("camera;microphone;foobar"), true, 2,
parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].IsWhiteList());
ASSERT_TRUE(parsedFeatures[0].HasAllowList());
ASSERT_TRUE(parsedFeatures[1].Name().Equals(NS_LITERAL_STRING("microphone")));
ASSERT_TRUE(parsedFeatures[1].IsWhiteList());
ASSERT_TRUE(parsedFeatures[1].HasAllowList());
// Multiple spaces around the value
CheckParser(NS_LITERAL_STRING("camera 'self'"), true, 1,
parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].WhiteListContains(URL_SELF));
ASSERT_TRUE(parsedFeatures[0].AllowListContains(selfPrincipal));
// Multiple spaces around the value
CheckParser(NS_LITERAL_STRING("camera 'self' "), true, 1,
parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].WhiteListContains(URL_SELF));
ASSERT_TRUE(parsedFeatures[0].AllowListContains(selfPrincipal));
// No final '
CheckParser(NS_LITERAL_STRING("camera 'self"), true, 1,
parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].IsWhiteList());
ASSERT_TRUE(!parsedFeatures[0].WhiteListContains(URL_SELF));
ASSERT_TRUE(parsedFeatures[0].HasAllowList());
ASSERT_TRUE(!parsedFeatures[0].AllowListContains(selfPrincipal));
// Lowercase/Uppercase
CheckParser(NS_LITERAL_STRING("camera 'selF'"), true, 1,
parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].WhiteListContains(URL_SELF));
ASSERT_TRUE(parsedFeatures[0].AllowListContains(selfPrincipal));
// Lowercase/Uppercase
CheckParser(NS_LITERAL_STRING("camera * 'self' none' a.com 123"), true, 1,
@@ -136,23 +146,23 @@ TEST(FeaturePolicyParser, Basic)
// 'self'
CheckParser(NS_LITERAL_STRING("camera 'self'"), true, 1, parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].WhiteListContains(URL_SELF));
ASSERT_TRUE(parsedFeatures[0].AllowListContains(selfPrincipal));
// A couple of URLs
CheckParser(NS_LITERAL_STRING("camera http://example.com http://example.net"), true, 1,
parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(!parsedFeatures[0].WhiteListContains(URL_SELF));
ASSERT_TRUE(parsedFeatures[0].WhiteListContains(URL_EXAMPLE_COM));
ASSERT_TRUE(parsedFeatures[0].WhiteListContains(URL_EXAMPLE_NET));
ASSERT_TRUE(!parsedFeatures[0].AllowListContains(selfPrincipal));
ASSERT_TRUE(parsedFeatures[0].AllowListContains(exampleComPrincipal));
ASSERT_TRUE(parsedFeatures[0].AllowListContains(exampleNetPrincipal));
// A couple of URLs + self
CheckParser(NS_LITERAL_STRING("camera http://example.com 'self' http://example.net"), true, 1,
parsedFeatures);
ASSERT_TRUE(parsedFeatures[0].Name().Equals(NS_LITERAL_STRING("camera")));
ASSERT_TRUE(parsedFeatures[0].WhiteListContains(URL_SELF));
ASSERT_TRUE(parsedFeatures[0].WhiteListContains(URL_EXAMPLE_COM));
ASSERT_TRUE(parsedFeatures[0].WhiteListContains(URL_EXAMPLE_NET));
ASSERT_TRUE(parsedFeatures[0].AllowListContains(selfPrincipal));
ASSERT_TRUE(parsedFeatures[0].AllowListContains(exampleComPrincipal));
ASSERT_TRUE(parsedFeatures[0].AllowListContains(exampleNetPrincipal));
// A couple of URLs but then *
CheckParser(NS_LITERAL_STRING("camera http://example.com 'self' http://example.net *"), true, 1,

View File

@@ -31,4 +31,3 @@
[Test frame policy on cross origin iframe with allow = "'self' https://www.web-platform.test:8443 https://www.example.com" and allowfullscreen.]
expected: FAIL

View File

@@ -10,11 +10,12 @@
var cross_origin = 'https://{{domains[www]}}:{{ports[https][0]}}';
var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html';
var cross_origin_src = cross_origin + same_origin_src;
var data_src = 'data:text/html,<h1>data: URL</h1>';
var policies = [
{allow: "*", sameOriginTestExpect: true, crossOriginTestExpect: true},
{allow: "'self'", sameOriginTestExpect: true, crossOriginTestExpect: false},
{allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false},
{allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: true, crossOriginTestExpect: true}];
{allow: "*", sameOriginTestExpect: true, crossOriginTestExpect: true, dataOriginTestExpect: true},
{allow: "'self'", sameOriginTestExpect: true, crossOriginTestExpect: false, dataOriginTestExpect: false},
{allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false, dataOriginTestExpect: false},
{allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: true, crossOriginTestExpect: true, dataOriginTestExpect: false}];
var pipe_front = '?pipe=sub|header(Feature-Policy,fullscreen ';
var pipe_end = ';)';
var header_policies = ["*", "'self'", "'none'"];
@@ -22,24 +23,58 @@
// Test that frame.policy inherits from parent's header policy when allow
// attribute is not specified.
test(function() {
test_frame_policy('fullscreen', same_origin_src, true);
test_frame_policy('fullscreen', same_origin_src, undefined, true);
}, 'Test frame policy on same origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', cross_origin_src, true);
test_frame_policy('fullscreen', cross_origin_src, undefined, true);
}, 'Test frame policy on cross origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', undefined, true, true);
}, 'Test frame policy on srcdoc iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', same_origin_src, true, true);
}, 'Test frame policy on srcdoc+ same origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', cross_origin_src, true, true);
}, 'Test frame policy on srcdoc+ cross origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', data_src, undefined, true);
}, 'Test frame policy on data: URL cross origin iframe inherit from header policy.');
// Test frame policy with allow attribute set to be one of the policies above.
for (var i = 0; i < policies.length; i++) {
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
'fullscreen', same_origin_src, undefined,
policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
'fullscreen', cross_origin_src, undefined,
policies[i].crossOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', undefined, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc + same origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc + cross origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', data_src, undefined, policies[i].dataOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on data: URL cross origin iframe with allow = "' + policies[i].allow + '".');
}
// Test that the header policy of the iframe document does not change the
@@ -50,7 +85,7 @@
test_frame_policy(
'fullscreen',
same_origin_src + pipe_front + header_policies[j] + pipe_end,
policies[i].sameOriginTestExpect,
undefined, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
'" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
@@ -58,7 +93,7 @@
test_frame_policy(
'fullscreen',
cross_origin_src + pipe_front + header_policies[j] + pipe_end,
policies[i].crossOriginTestExpect,
undefined, policies[i].crossOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
'" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
@@ -69,16 +104,42 @@
for (var i = 0; i < policies.length; i++) {
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
'fullscreen', same_origin_src, undefined,
policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
'fullscreen', cross_origin_src, undefined,
policies[i].crossOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', undefined, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc + same origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc + cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', data_src, undefined, policies[i].dataOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on data: URL cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
}
</script>
</body>

View File

@@ -10,11 +10,12 @@
var cross_origin = 'https://{{domains[www]}}:{{ports[https][0]}}';
var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html';
var cross_origin_src = cross_origin + same_origin_src;
var data_src = 'data:text/html,<h1>data: URL</h1>';
var policies = [
{allow: "*", sameOriginTestExpect: true, crossOriginTestExpect: true},
{allow: "'self'", sameOriginTestExpect: true, crossOriginTestExpect: false},
{allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false},
{allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: true, crossOriginTestExpect: true}];
{allow: "*", sameOriginTestExpect: true, crossOriginTestExpect: true, dataOriginTestExpect: false},
{allow: "'self'", sameOriginTestExpect: true, crossOriginTestExpect: false, dataOriginTestExpect: false},
{allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false, dataOriginTestExpect: false},
{allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: true, crossOriginTestExpect: true, dataOriginTestExpect: false}];
var pipe_front = '?pipe=sub|header(Feature-Policy,fullscreen ';
var pipe_end = ';)';
var header_policies = ["*", "'self'", "'none'"];
@@ -22,42 +23,92 @@
// Test that frame.policy inherits from parent's header policy when allow
// attribute is not specified.
test(function() {
test_frame_policy('fullscreen', same_origin_src, true);
test_frame_policy('fullscreen', same_origin_src, undefined, true);
}, 'Test frame policy on same origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', cross_origin_src, false);
test_frame_policy('fullscreen', cross_origin_src, undefined, false);
}, 'Test frame policy on cross origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', undefined, true, true);
}, 'Test frame policy on srcdoc iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', same_origin_src, true, true);
}, 'Test frame policy on srcdoc + same origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', cross_origin_src, true, true);
}, 'Test frame policy on srcdoc + cross origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', data_src, undefined, false);
}, 'Test frame policy on data: URL cross origin iframe inherit from header policy.');
// Test that frame policy can be used for sandboxed frames
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, false, undefined, false, true);
'fullscreen', same_origin_src, undefined, false, undefined, false, true);
}, 'Test frame policy on sandboxed iframe with no allow attribute.');
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, true, 'fullscreen', false, true);
'fullscreen', same_origin_src, undefined, true, 'fullscreen', false, true);
}, 'Test frame policy on sandboxed iframe with allow="fullscreen".');
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, true, 'fullscreen \'src\'', false, true);
'fullscreen', same_origin_src, undefined, true, 'fullscreen \'src\'', false, true);
}, 'Test frame policy on sandboxed iframe with allow="fullscreen \'src\'".');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, false, 'fullscreen ' + cross_origin, false, true);
'fullscreen', cross_origin_src, undefined, false, 'fullscreen ' + cross_origin, false, true);
}, 'Test frame policy on sandboxed iframe with allow="fullscreen ' + cross_origin + '".');
test(function() {
test_frame_policy(
'fullscreen', undefined, true, true, 'fullscreen', false, true);
}, 'Test frame policy on srcdoc sandboxed iframe with allow="fullscreen".');
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, true, true, 'fullscreen', false, true);
}, 'Test frame policy on srcdoc + same origin sandboxed iframe with allow="fullscreen".');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, true, true, 'fullscreen', false, true);
}, 'Test frame policy on srcdoc + cross origin sandboxed iframe with allow="fullscreen".');
test(function() {
test_frame_policy(
'fullscreen', data_src, undefined, false, 'fullscreen ' + cross_origin, false, true);
}, 'Test frame policy on sandboxed srcdoc iframe with allow="fullscreen ' + cross_origin + '".');
// Test frame policy with allow attribute set to be one of the policies above.
for (var i = 0; i < policies.length; i++) {
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
'fullscreen', same_origin_src, undefined,
policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
'fullscreen', cross_origin_src, undefined,
policies[i].crossOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', undefined, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc + same origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc + cross origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', data_src, undefined, policies[i].dataOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on data: URL origin iframe with allow = "' + policies[i].allow + '".');
}
// Test that the header policy of the iframe document does not change the
@@ -68,7 +119,7 @@
test_frame_policy(
'fullscreen',
same_origin_src + pipe_front + header_policies[j] + pipe_end,
policies[i].sameOriginTestExpect,
undefined, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
'" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
@@ -76,7 +127,7 @@
test_frame_policy(
'fullscreen',
cross_origin_src + pipe_front + header_policies[j] + pipe_end,
policies[i].crossOriginTestExpect,
undefined, policies[i].crossOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
'" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
@@ -87,16 +138,42 @@
for (var i = 0; i < policies.length; i++) {
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
'fullscreen', same_origin_src, undefined,
policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
'fullscreen', cross_origin_src, undefined,
policies[i].crossOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', undefined, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc + same origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc + cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', data_src, undefined, policies[i].dataOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on data: URL origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
}
</script>
</body>

View File

@@ -12,12 +12,13 @@
var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html';
var cross_origin_src = cross_origin + same_origin_src;
var cross_origin_src1 = cross_origin1 + same_origin_src;
var data_src = 'data:text/html,<h1>data: URL</h1>';
// Test feature policy with same_origin_src and cross_origin_src.
var policies = [
{allow: "*", sameOriginTestExpect: true, crossOriginTestExpect: true, crossOrigin1TestExpect: true},
{allow: "'self'", sameOriginTestExpect: true, crossOriginTestExpect: false, crossOrigin1TestExpect: false},
{allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false, crossOrigin1TestExpect: false},
{allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: true, crossOriginTestExpect: true, crossOrigin1TestExpect: false}];
{allow: "*", sameOriginTestExpect: true, crossOriginTestExpect: true, crossOrigin1TestExpect: true, dataOriginTestExpect: false},
{allow: "'self'", sameOriginTestExpect: true, crossOriginTestExpect: false, crossOrigin1TestExpect: false, dataOriginTestExpect: false},
{allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false, crossOrigin1TestExpect: false, dataOriginTestExpect: false},
{allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: true, crossOriginTestExpect: true, crossOrigin1TestExpect: false, dataOriginTestExpect: false}];
var pipe_front = '?pipe=sub|header(Feature-Policy,fullscreen ';
var pipe_end = ';)';
var header_policies = ["*", "'self'", "'none'"];
@@ -25,32 +26,75 @@
// Test that frame.policy inherits from parent's header policy when allow
// attribute is not specified.
test(function() {
test_frame_policy('fullscreen', same_origin_src, true);
test_frame_policy('fullscreen', same_origin_src, undefined, true);
}, 'Test frame policy on same origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', cross_origin_src, true);
test_frame_policy('fullscreen', cross_origin_src, undefined, true);
}, 'Test frame policy on cross origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', cross_origin_src1, false);
test_frame_policy('fullscreen', cross_origin_src1, undefined, false);
}, 'Test frame policy on another cross origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', undefined, true, true);
}, 'Test frame policy on srcdoc iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', same_origin_src, true, true);
}, 'Test frame policy on srcdoc + same origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', cross_origin_src, true, true);
}, 'Test frame policy on srcdoc + cross origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', cross_origin_src1, true, true);
}, 'Test frame policy on srcdoc + another cross origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', data_src, undefined, false);
}, 'Test frame policy on data: URL cross origin iframe inherit from header policy.');
// Test frame policy with allow attribute set to be one of the policies above.
for (var i = 0; i < policies.length; i++) {
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
'fullscreen', same_origin_src, undefined,
policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
'fullscreen', cross_origin_src, undefined,
policies[i].crossOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src1, policies[i].crossOrigin1TestExpect,
'fullscreen', cross_origin_src1, undefined,
policies[i].crossOrigin1TestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on another cross origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', undefined, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc + same origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc + cross origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src1, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc + another cross origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', data_src, undefined, policies[i].dataOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on data: URL cross origin iframe with allow = "' + policies[i].allow + '".');
}
// Test that the header policy of the iframe document does not change the
@@ -61,7 +105,7 @@
test_frame_policy(
'fullscreen',
same_origin_src + pipe_front + header_policies[j] + pipe_end,
policies[i].sameOriginTestExpect,
undefined, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
'" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
@@ -69,7 +113,7 @@
test_frame_policy(
'fullscreen',
cross_origin_src + pipe_front + header_policies[j] + pipe_end,
policies[i].crossOriginTestExpect,
undefined, policies[i].crossOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
'" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
@@ -77,7 +121,7 @@
test_frame_policy(
'fullscreen',
cross_origin_src1 + pipe_front + header_policies[j] + pipe_end,
policies[i].crossOrigin1TestExpect,
undefined, policies[i].crossOrigin1TestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on another cross origin iframe with allow = "' + policies[i].allow +
'" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
@@ -88,22 +132,55 @@
for (var i = 0; i < policies.length; i++) {
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
'fullscreen', same_origin_src, undefined,
policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
'fullscreen', cross_origin_src, undefined,
policies[i].crossOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src1, policies[i].crossOrigin1TestExpect,
'fullscreen', cross_origin_src1, undefined,
policies[i].crossOrigin1TestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on another cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', undefined, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc + same origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc + cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src1, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc + another cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', data_src, undefined, policies[i].dataOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on data: URL cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
}
</script>
</body>

View File

@@ -10,11 +10,12 @@
var cross_origin = 'https://{{domains[www]}}:{{ports[https][0]}}';
var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html';
var cross_origin_src = cross_origin + same_origin_src;
var data_src = 'data:text/html,<h1>data: URL</h1>';
var policies = [
{allow: "*", sameOriginTestExpect: false, crossOriginTestExpect: false},
{allow: "'self'", sameOriginTestExpect: false, crossOriginTestExpect: false},
{allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false},
{allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: false, crossOriginTestExpect: false}];
{allow: "*", sameOriginTestExpect: false, crossOriginTestExpect: false, dataOriginTestExpect: false},
{allow: "'self'", sameOriginTestExpect: false, crossOriginTestExpect: false, dataOriginTestExpect: false},
{allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false, dataOriginTestExpect: false},
{allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: false, crossOriginTestExpect: false, dataOriginTestExpect: false}];
var pipe_front = '?pipe=sub|header(Feature-Policy,fullscreen ';
var pipe_end = ';)';
var header_policies = ["*", "'self'", "'none'"];
@@ -22,24 +23,58 @@
// Test that frame.policy inherits from parent's header policy when allow
// attribute is not specified.
test(function() {
test_frame_policy('fullscreen', same_origin_src, false);
test_frame_policy('fullscreen', same_origin_src, undefined, false);
}, 'Test frame policy on same origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', cross_origin_src, false);
test_frame_policy('fullscreen', cross_origin_src, undefined, false);
}, 'Test frame policy on cross origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', undefined, true, false);
}, 'Test frame policy on srcdoc iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', same_origin_src, true, false);
}, 'Test frame policy on srcdoc + same origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', cross_origin_src, true, false);
}, 'Test frame policy on srcdoc + cross origin iframe inherit from header policy.');
test(function() {
test_frame_policy('fullscreen', data_src, undefined, false);
}, 'Test frame policy on data: URL cross origin iframe inherit from header policy.');
// Test frame policy with allow attribute set to be one of the policies above.
for (var i = 0; i < policies.length; i++) {
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
'fullscreen', same_origin_src, undefined,
policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
'fullscreen', cross_origin_src, undefined,
policies[i].crossOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', undefined, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc + same origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on srcdoc + cross origin iframe with allow = "' + policies[i].allow + '".');
test(function() {
test_frame_policy(
'fullscreen', data_src, undefined, policies[i].dataOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on data: URL cross origin iframe with allow = "' + policies[i].allow + '".');
}
// Test that the header policy of the iframe document does not change the
@@ -50,7 +85,7 @@
test_frame_policy(
'fullscreen',
same_origin_src + pipe_front + header_policies[j] + pipe_end,
policies[i].sameOriginTestExpect,
undefined, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
'" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
@@ -58,7 +93,7 @@
test_frame_policy(
'fullscreen',
cross_origin_src + pipe_front + header_policies[j] + pipe_end,
policies[i].crossOriginTestExpect,
undefined, policies[i].crossOriginTestExpect,
'fullscreen ' + policies[i].allow + ';');
}, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
'" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
@@ -69,16 +104,42 @@
for (var i = 0; i < policies.length; i++) {
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
'fullscreen', same_origin_src, undefined,
policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
'fullscreen', cross_origin_src, undefined,
policies[i].crossOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', undefined, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', same_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc + same origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', cross_origin_src, true, policies[i].sameOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on srcdoc + cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
test(function() {
test_frame_policy(
'fullscreen', data_src, undefined, policies[i].dataOriginTestExpect,
'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
}, 'Test frame policy on data: URL cross origin iframe with allow = "' + policies[i].allow +
'" and allowfullscreen.');
}
</script>
</body>

View File

@@ -396,14 +396,15 @@ function test_subframe_header_policy(
// by iframe allow attribute.
// Arguments:
// feature: feature name.
// src: the URL to load in the frame.
// src: the URL to load in the frame. If undefined, the iframe will have a
// srcdoc="" attribute
// test_expect: boolean value of whether the feature should be allowed.
// allow: optional, the allow attribute (container policy) of the iframe.
// allowfullscreen: optional, boolean value of allowfullscreen attribute.
// sandbox: optional boolean. If true, the frame will be sandboxed (with
// allow-scripts, so that tests can run in it.)
function test_frame_policy(
feature, src, test_expect, allow, allowfullscreen, sandbox) {
feature, src, srcdoc, test_expect, allow, allowfullscreen, sandbox) {
let frame = document.createElement('iframe');
document.body.appendChild(frame);
// frame_policy should be dynamically updated as allow and allowfullscreen is
@@ -418,7 +419,12 @@ function test_frame_policy(
if (!!sandbox) {
frame.setAttribute('sandbox', 'allow-scripts');
}
if (!!src) {
frame.src = src;
}
if (!!srcdoc) {
frame.srcdoc = "<h1>Hello world!</h1>";
}
if (test_expect) {
assert_true(frame_policy.allowedFeatures().includes(feature));
} else {