summaryrefslogtreecommitdiffstats
path: root/dom/security/featurepolicy/FeaturePolicy.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/security/featurepolicy/FeaturePolicy.h204
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