FeaturePolicy.h (8217B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_FeaturePolicy_h 8 #define mozilla_dom_FeaturePolicy_h 9 10 #include "nsCycleCollectionParticipant.h" 11 #include "nsIPrincipal.h" 12 #include "nsStringFwd.h" 13 #include "nsTArray.h" 14 #include "nsWrapperCache.h" 15 16 /** 17 * FeaturePolicy 18 * ~~~~~~~~~~~~~ 19 * 20 * Each document and each HTMLIFrameElement have a FeaturePolicy object which is 21 * used to allow or deny features in their contexts. 22 * 23 * FeaturePolicy is composed by a set of directives configured by the 24 * 'Feature-Policy' HTTP Header and the 'allow' attribute in HTMLIFrameElements. 25 * Both header and attribute are parsed by FeaturePolicyParser which returns an 26 * array of Feature objects. Each Feature object has a feature name and one of 27 * these policies: 28 * - eNone - the feature is fully disabled. 29 * - eAll - the feature is allowed. 30 * - eAllowList - the feature is allowed for a list of origins. 31 * 32 * An interesting element of FeaturePolicy is the inheritance: each context 33 * inherits the feature-policy directives from the parent context, if it exists. 34 * When a context inherits a policy for feature X, it only knows if that feature 35 * is allowed or denied (it ignores the list of allowed origins for instance). 36 * This information is stored in an array of inherited feature strings because 37 * we care only to know when they are denied. 38 * 39 * FeaturePolicy can be reset if the 'allow' or 'src' attributes change in 40 * HTMLIFrameElements. 'src' attribute is important to compute correcly 41 * the features via FeaturePolicy 'src' keyword. 42 * 43 * When FeaturePolicy must decide if feature X is allowed or denied for the 44 * current origin, it checks if the parent context denied that feature. 45 * If not, it checks if there is a Feature object for that 46 * feature named X and if the origin is allowed or not. 47 * 48 * From a C++ point of view, use FeaturePolicyUtils to obtain the list of 49 * features and to check if they are allowed in the current context. 50 * 51 * dom.security.featurePolicy.header.enabled pref can be used to disable the 52 * HTTP header support. 53 **/ 54 55 class nsINode; 56 57 namespace mozilla::dom { 58 class Document; 59 class BrowsingContext; 60 class Feature; 61 template <typename T> 62 class Optional; 63 64 class FeaturePolicyUtils; 65 66 struct FeaturePolicyInfo final { 67 CopyableTArray<nsString> mInheritedDeniedFeatureNames; 68 CopyableTArray<nsString> mAttributeEnabledFeatureNames; 69 nsString mDeclaredString; 70 nsCOMPtr<nsIPrincipal> mDefaultOrigin; 71 nsCOMPtr<nsIPrincipal> mSelfOrigin; 72 nsCOMPtr<nsIPrincipal> mSrcOrigin; 73 }; 74 75 using MaybeFeaturePolicyInfo = Maybe<FeaturePolicyInfo>; 76 77 class FeaturePolicy final : public nsISupports, public nsWrapperCache { 78 friend class FeaturePolicyUtils; 79 80 public: 81 NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL 82 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(FeaturePolicy) 83 84 explicit FeaturePolicy(nsINode* aNode); 85 86 // A FeaturePolicy must have a default origin. 87 // This method must be called before any other exposed WebIDL method or before 88 // checking if a feature is allowed. 89 void SetDefaultOrigin(nsIPrincipal* aPrincipal) { 90 mDefaultOrigin = aPrincipal; 91 } 92 93 void SetSrcOrigin(nsIPrincipal* aPrincipal) { mSrcOrigin = aPrincipal; } 94 95 nsIPrincipal* DefaultOrigin() const { return mDefaultOrigin; } 96 97 // Inherits the policy from the 'parent' context if it exists. 98 void InheritPolicy(FeaturePolicy* aParentFeaturePolicy); 99 100 // Inherits the policy from the 'parent' context if it exists. 101 void InheritPolicy(const FeaturePolicyInfo& aContainerFeaturePolicyInfo); 102 103 // Sets the declarative part of the policy. This can be from the HTTP header 104 // or for the 'allow' HTML attribute. 105 void SetDeclaredPolicy(mozilla::dom::Document* aDocument, 106 const nsAString& aPolicyString, 107 nsIPrincipal* aSelfOrigin, nsIPrincipal* aSrcOrigin); 108 109 // This method creates a policy for aFeatureName allowing it to '*' if it 110 // doesn't exist yet. It's used by HTMLIFrameElement to enable features by 111 // attributes. 112 void MaybeSetAllowedPolicy(const nsAString& aFeatureName); 113 114 // Clears all the declarative policy directives. This is needed when the 115 // 'allow' attribute or the 'src' attribute change for HTMLIFrameElement's 116 // policy. 117 void ResetDeclaredPolicy(); 118 119 // This method appends a feature to in-chain declared allowlist. If the name's 120 // feature existed in the list, we only need to append the allowlist of new 121 // feature to the existed one. 122 void AppendToDeclaredAllowInAncestorChain(const Feature& aFeature); 123 124 // This method returns true if aFeatureName is declared as "*" (allow all) 125 // in parent. 126 bool HasFeatureUnsafeAllowsAll(const nsAString& aFeatureName) const; 127 128 // This method returns true if the aFeatureName is allowed for aOrigin 129 // explicitly in ancestor chain, 130 bool AllowsFeatureExplicitlyInAncestorChain(const nsAString& aFeatureName, 131 nsIPrincipal* aOrigin) const; 132 133 bool IsSameOriginAsSrc(nsIPrincipal* aPrincipal) const; 134 135 // WebIDL internal methods. 136 137 JSObject* WrapObject(JSContext* aCx, 138 JS::Handle<JSObject*> aGivenProto) override; 139 140 nsINode* GetParentObject() const { return mParentNode; } 141 142 // WebIDL explosed methods. 143 144 bool AllowsFeature(const nsAString& aFeatureName, 145 const Optional<nsAString>& aOrigin) const; 146 147 void Features(nsTArray<nsString>& aFeatures); 148 149 void AllowedFeatures(nsTArray<nsString>& aAllowedFeatures); 150 151 void GetAllowlistForFeature(const nsAString& aFeatureName, 152 nsTArray<nsString>& aList) const; 153 154 const nsTArray<nsString>& InheritedDeniedFeatureNames() const { 155 return mInheritedDeniedFeatureNames; 156 } 157 158 const nsTArray<nsString>& AttributeEnabledFeatureNames() const { 159 return mAttributeEnabledFeatureNames; 160 } 161 162 void SetInheritedDeniedFeatureNames( 163 const nsTArray<nsString>& aInheritedDeniedFeatureNames) { 164 mInheritedDeniedFeatureNames = aInheritedDeniedFeatureNames.Clone(); 165 } 166 167 const nsAString& DeclaredString() const { return mDeclaredString; } 168 169 nsIPrincipal* GetSelfOrigin() const { return mSelfOrigin; } 170 nsIPrincipal* GetSrcOrigin() const { return mSrcOrigin; } 171 172 FeaturePolicyInfo ToFeaturePolicyInfo() const; 173 174 private: 175 ~FeaturePolicy() = default; 176 177 // This method returns true if the aFeatureName is allowed for aOrigin, 178 // following the feature-policy directives. See the comment at the top of this 179 // file. 180 bool AllowsFeatureInternal(const nsAString& aFeatureName, 181 nsIPrincipal* aOrigin) const; 182 183 // Inherits a single denied feature from the parent context. 184 void SetInheritedDeniedFeature(const nsAString& aFeatureName); 185 186 bool HasInheritedDeniedFeature(const nsAString& aFeatureName) const; 187 188 // This returns true if we have a declared feature policy for aFeatureName. 189 bool HasDeclaredFeature(const nsAString& aFeatureName) const; 190 191 nsINode* mParentNode; 192 193 // This is set in sub-contexts when the parent blocks some feature for the 194 // current context. 195 nsTArray<nsString> mInheritedDeniedFeatureNames; 196 197 // The list of features that have been enabled via MaybeSetAllowedPolicy. 198 nsTArray<nsString> mAttributeEnabledFeatureNames; 199 200 // This is set of feature names when the parent allows all for that feature. 201 nsTArray<nsString> mParentAllowedAllFeatures; 202 203 // The explicitly declared policy contains allowlist as a set of origins 204 // except 'none' and '*'. This set contains all explicitly declared policies 205 // in ancestor chain 206 nsTArray<Feature> mDeclaredFeaturesInAncestorChain; 207 208 // Feature policy for the current context. 209 nsTArray<Feature> mFeatures; 210 211 // Declared string represents Feature policy. 212 nsString mDeclaredString; 213 214 nsCOMPtr<nsIPrincipal> mDefaultOrigin; 215 nsCOMPtr<nsIPrincipal> mSelfOrigin; 216 nsCOMPtr<nsIPrincipal> mSrcOrigin; 217 }; 218 219 } // namespace mozilla::dom 220 221 #endif // mozilla_dom_FeaturePolicy_h