diff options
Diffstat (limited to 'dom/security/featurepolicy/FeaturePolicy.h')
-rw-r--r-- | dom/security/featurepolicy/FeaturePolicy.h | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/dom/security/featurepolicy/FeaturePolicy.h b/dom/security/featurepolicy/FeaturePolicy.h new file mode 100644 index 0000000000..65f5259749 --- /dev/null +++ b/dom/security/featurepolicy/FeaturePolicy.h @@ -0,0 +1,204 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_FeaturePolicy_h +#define mozilla_dom_FeaturePolicy_h + +#include "nsCycleCollectionParticipant.h" +#include "nsIPrincipal.h" +#include "nsStringFwd.h" +#include "nsTArray.h" +#include "nsWrapperCache.h" + +/** + * FeaturePolicy + * ~~~~~~~~~~~~~ + * + * Each document and each HTMLIFrameElement have a FeaturePolicy object which is + * used to allow or deny features in their contexts. + * + * FeaturePolicy is composed by a set of directives configured by the + * 'Feature-Policy' HTTP Header and the 'allow' attribute in HTMLIFrameElements. + * Both header and attribute are parsed by FeaturePolicyParser which returns an + * array of Feature objects. Each Feature object has a feature name and one of + * these policies: + * - eNone - the feature is fully disabled. + * - eAll - the feature is allowed. + * - 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 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. + * + * FeaturePolicy can be reset if the 'allow' or 'src' attributes change in + * HTMLIFrameElements. 'src' attribute is important to compute correcly + * the features via FeaturePolicy 'src' keyword. + * + * When FeaturePolicy must decide if feature X is allowed or denied for the + * current origin, it checks if the parent context denied that feature. + * If not, it checks if there is a Feature object for that + * feature named X and if the origin is allowed or not. + * + * From a C++ point of view, use FeaturePolicyUtils to obtain the list of + * features and to check if they are allowed in the current context. + * + * dom.security.featurePolicy.header.enabled pref can be used to disable the + * HTTP header support. + **/ + +class nsINode; + +namespace mozilla::dom { +class Document; +class Feature; +template <typename T> +class Optional; + +class FeaturePolicyUtils; + +class FeaturePolicy final : public nsISupports, public nsWrapperCache { + friend class FeaturePolicyUtils; + + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(FeaturePolicy) + + explicit FeaturePolicy(nsINode* aNode); + + // 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(nsIPrincipal* aPrincipal) { + mDefaultOrigin = aPrincipal; + } + + void SetSrcOrigin(nsIPrincipal* aPrincipal) { mSrcOrigin = aPrincipal; } + + nsIPrincipal* DefaultOrigin() const { return mDefaultOrigin; } + + // Inherits the policy from the 'parent' context if it exists. + void InheritPolicy(FeaturePolicy* aParentFeaturePolicy); + + // Sets the declarative part of the policy. This can be from the HTTP header + // or for the 'allow' HTML attribute. + void SetDeclaredPolicy(mozilla::dom::Document* aDocument, + const nsAString& aPolicyString, + 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 + // attributes. + void MaybeSetAllowedPolicy(const nsAString& aFeatureName); + + // Clears all the declarative policy directives. This is needed when the + // 'allow' attribute or the 'src' attribute change for HTMLIFrameElement's + // policy. + void ResetDeclaredPolicy(); + + // This method appends a feature to in-chain declared allowlist. If the name's + // feature existed in the list, we only need to append the allowlist of new + // feature to the existed one. + void AppendToDeclaredAllowInAncestorChain(const Feature& aFeature); + + // This method returns true if aFeatureName is declared as "*" (allow all) + // in parent. + bool HasFeatureUnsafeAllowsAll(const nsAString& aFeatureName) const; + + // This method returns true if the aFeatureName is allowed for aOrigin + // explicitly in ancestor chain, + bool AllowsFeatureExplicitlyInAncestorChain(const nsAString& aFeatureName, + nsIPrincipal* aOrigin) const; + + bool IsSameOriginAsSrc(nsIPrincipal* aPrincipal) const; + + // WebIDL internal methods. + + JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + + nsINode* GetParentObject() const { return mParentNode; } + + // WebIDL explosed methods. + + bool AllowsFeature(const nsAString& aFeatureName, + const Optional<nsAString>& aOrigin) const; + + void Features(nsTArray<nsString>& aFeatures); + + void AllowedFeatures(nsTArray<nsString>& aAllowedFeatures); + + void GetAllowlistForFeature(const nsAString& aFeatureName, + nsTArray<nsString>& aList) const; + + const nsTArray<nsString>& InheritedDeniedFeatureNames() const { + return mInheritedDeniedFeatureNames; + } + + const nsTArray<nsString>& AttributeEnabledFeatureNames() const { + return mAttributeEnabledFeatureNames; + } + + void SetInheritedDeniedFeatureNames( + const nsTArray<nsString>& aInheritedDeniedFeatureNames) { + mInheritedDeniedFeatureNames = aInheritedDeniedFeatureNames.Clone(); + } + + const nsAString& DeclaredString() const { return mDeclaredString; } + + nsIPrincipal* GetSelfOrigin() const { return mSelfOrigin; } + nsIPrincipal* GetSrcOrigin() const { return mSrcOrigin; } + + 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, + nsIPrincipal* aOrigin) const; + + // Inherits a single denied feature from the parent context. + void SetInheritedDeniedFeature(const nsAString& aFeatureName); + + bool HasInheritedDeniedFeature(const nsAString& aFeatureName) const; + + // This returns true if we have a declared feature policy for aFeatureName. + bool HasDeclaredFeature(const nsAString& aFeatureName) const; + + nsINode* mParentNode; + + // This is set in sub-contexts when the parent blocks some feature for the + // current context. + nsTArray<nsString> mInheritedDeniedFeatureNames; + + // The list of features that have been enabled via MaybeSetAllowedPolicy. + nsTArray<nsString> mAttributeEnabledFeatureNames; + + // This is set of feature names when the parent allows all for that feature. + nsTArray<nsString> mParentAllowedAllFeatures; + + // The explicitly declared policy contains allowlist as a set of origins + // except 'none' and '*'. This set contains all explicitly declared policies + // in ancestor chain + nsTArray<Feature> mDeclaredFeaturesInAncestorChain; + + // Feature policy for the current context. + nsTArray<Feature> mFeatures; + + // Declared string represents Feature policy. + nsString mDeclaredString; + + nsCOMPtr<nsIPrincipal> mDefaultOrigin; + nsCOMPtr<nsIPrincipal> mSelfOrigin; + nsCOMPtr<nsIPrincipal> mSrcOrigin; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_FeaturePolicy_h |