Index: content/common/feature_policy/feature_policy.cc |
diff --git a/content/common/feature_policy/feature_policy.cc b/content/common/feature_policy/feature_policy.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b51bee50b30949fab7dc872c4fdb26d5df6b11ca |
--- /dev/null |
+++ b/content/common/feature_policy/feature_policy.cc |
@@ -0,0 +1,201 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/common/feature_policy/feature_policy.h" |
+ |
+#include "base/macros.h" |
+#include "base/memory/ptr_util.h" |
+ |
+namespace content { |
+ |
+namespace { |
+ |
+// Given a string name, return the matching feature struct, or nullptr if it is |
+// not the name of a policy-controlled feature. |
+blink::WebFeaturePolicyFeature FeatureForName( |
+ std::string feature_name, |
+ const FeaturePolicy::FeatureList& features) { |
+ for (const auto& feature_mapping : features) { |
+ if (feature_name == feature_mapping.second->feature_name) |
+ return feature_mapping.first; |
+ } |
+ return blink::WebFeaturePolicyFeature::NotFound; |
+} |
+ |
+// Definitions of all features controlled by Feature Policy should appear here. |
+const FeaturePolicy::Feature kDocumentCookie{ |
+ "cookie", FeaturePolicy::FeatureDefault::EnableForAll}; |
+const FeaturePolicy::Feature kDocumentDomain{ |
+ "domain", FeaturePolicy::FeatureDefault::EnableForAll}; |
+const FeaturePolicy::Feature kDocumentWrite{ |
+ "docwrite", FeaturePolicy::FeatureDefault::EnableForAll}; |
+const FeaturePolicy::Feature kFullscreenFeature{ |
+ "fullscreen", FeaturePolicy::FeatureDefault::EnableForSelf}; |
+const FeaturePolicy::Feature kGeolocationFeature{ |
+ "geolocation", FeaturePolicy::FeatureDefault::EnableForSelf}; |
+const FeaturePolicy::Feature kMidiFeature{ |
+ "midi", FeaturePolicy::FeatureDefault::EnableForAll}; |
+const FeaturePolicy::Feature kNotificationsFeature{ |
+ "notifications", FeaturePolicy::FeatureDefault::EnableForAll}; |
+const FeaturePolicy::Feature kPaymentFeature{ |
+ "payment", FeaturePolicy::FeatureDefault::EnableForSelf}; |
+const FeaturePolicy::Feature kPushFeature{ |
+ "push", FeaturePolicy::FeatureDefault::EnableForAll}; |
+const FeaturePolicy::Feature kSyncScript{ |
+ "sync-script", FeaturePolicy::FeatureDefault::EnableForAll}; |
+const FeaturePolicy::Feature kSyncXHR{ |
+ "sync-xhr", FeaturePolicy::FeatureDefault::EnableForAll}; |
+const FeaturePolicy::Feature kUsermedia{ |
+ "usermedia", FeaturePolicy::FeatureDefault::EnableForAll}; |
+const FeaturePolicy::Feature kVibrateFeature{ |
+ "vibrate", FeaturePolicy::FeatureDefault::EnableForSelf}; |
+const FeaturePolicy::Feature kWebRTC{ |
+ "webrtc", FeaturePolicy::FeatureDefault::EnableForAll}; |
+ |
+// Extracts a Whitelist from a FeaturePolicyParsedDeclaration |
+std::unique_ptr<FeaturePolicy::Whitelist> WhitelistFromDeclaration( |
+ const FeaturePolicyParsedDeclaration& parsed_declaration) { |
+ std::unique_ptr<FeaturePolicy::Whitelist> result = |
+ base::WrapUnique(new FeaturePolicy::Whitelist()); |
+ if (parsed_declaration.matches_all_origins) |
+ result->AddAll(); |
+ for (const auto& origin : parsed_declaration.origins) |
+ result->Add(origin); |
+ return result; |
+} |
+ |
+} // namespace |
+ |
+FeaturePolicyParsedDeclaration::FeaturePolicyParsedDeclaration() |
+ : matches_all_origins(false) {} |
+ |
+FeaturePolicyParsedDeclaration::FeaturePolicyParsedDeclaration( |
+ std::string feature_name, |
+ bool matches_all_origins, |
+ std::vector<url::Origin> origins) |
+ : feature_name(feature_name), |
+ matches_all_origins(matches_all_origins), |
+ origins(origins) {} |
+ |
+FeaturePolicyParsedDeclaration::FeaturePolicyParsedDeclaration( |
+ const FeaturePolicyParsedDeclaration& rhs) = default; |
+ |
+FeaturePolicyParsedDeclaration::~FeaturePolicyParsedDeclaration() {} |
+ |
+FeaturePolicy::Whitelist::Whitelist() : matches_all_origins_(false) {} |
+FeaturePolicy::Whitelist::~Whitelist() = default; |
+ |
+void FeaturePolicy::Whitelist::Add(const url::Origin& origin) { |
+ origins_.push_back(origin); |
+} |
+ |
+void FeaturePolicy::Whitelist::AddAll() { |
+ matches_all_origins_ = true; |
+} |
+ |
+bool FeaturePolicy::Whitelist::Contains(const url::Origin& origin) const { |
+ if (matches_all_origins_) |
+ return true; |
+ for (const auto& targetOrigin : origins_) { |
+ if (targetOrigin.IsSameOriginWith(origin)) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+// static |
+std::unique_ptr<FeaturePolicy> FeaturePolicy::CreateFromParentPolicy( |
+ const FeaturePolicy* parent_policy, |
+ url::Origin origin) { |
+ return CreateFromParentPolicy(parent_policy, origin, getDefaultFeatureList()); |
+} |
+ |
+bool FeaturePolicy::IsFeatureEnabledForOrigin( |
+ blink::WebFeaturePolicyFeature feature, |
+ url::Origin origin) const { |
+ DCHECK(feature_list_.count(feature)); |
+ const FeaturePolicy::Feature* feature_definition = feature_list_.at(feature); |
+ DCHECK(inherited_policies_.count(feature)); |
+ if (!inherited_policies_.at(feature)) { |
+ return false; |
+ } |
+ if (whitelists_.count(feature)) { |
+ return whitelists_.at(feature)->Contains(origin); |
+ } |
+ if (feature_definition->default_policy == |
+ FeaturePolicy::FeatureDefault::EnableForAll) { |
+ return true; |
+ } |
+ if (feature_definition->default_policy == |
+ FeaturePolicy::FeatureDefault::EnableForSelf) { |
+ return origin_.IsSameOriginWith(origin); |
+ } |
+ return false; |
+} |
+ |
+bool FeaturePolicy::IsFeatureEnabled( |
+ blink::WebFeaturePolicyFeature feature) const { |
+ return IsFeatureEnabledForOrigin(feature, origin_); |
+} |
+ |
+void FeaturePolicy::SetHeaderPolicy(const FeaturePolicyHeader& parsed_header) { |
+ DCHECK(whitelists_.empty()); |
+ for (const FeaturePolicyParsedDeclaration& parsed_declaration : |
+ parsed_header) { |
+ blink::WebFeaturePolicyFeature feature = |
+ FeatureForName(parsed_declaration.feature_name, feature_list_); |
+ if (feature == blink::WebFeaturePolicyFeature::NotFound) |
+ continue; |
+ whitelists_[feature] = WhitelistFromDeclaration(parsed_declaration); |
+ } |
+} |
+ |
+FeaturePolicy::FeaturePolicy(url::Origin origin, |
+ const FeatureList& feature_list) |
+ : origin_(origin), feature_list_(feature_list) {} |
+FeaturePolicy::FeaturePolicy(url::Origin origin) |
+ : origin_(origin), feature_list_(getDefaultFeatureList()) {} |
+FeaturePolicy::~FeaturePolicy() {} |
+ |
+// static |
+std::unique_ptr<FeaturePolicy> FeaturePolicy::CreateFromParentPolicy( |
+ const FeaturePolicy* parent_policy, |
+ url::Origin origin, |
+ const FeaturePolicy::FeatureList& features) { |
+ std::unique_ptr<FeaturePolicy> newPolicy = |
+ base::WrapUnique(new FeaturePolicy(origin, features)); |
+ for (const auto& feature : features) { |
+ if (!parent_policy || |
+ parent_policy->IsFeatureEnabledForOrigin(feature.first, origin)) { |
+ newPolicy->inherited_policies_[feature.first] = true; |
+ } else { |
+ newPolicy->inherited_policies_[feature.first] = false; |
+ } |
+ } |
+ return newPolicy; |
+} |
+ |
+// static |
+const FeaturePolicy::FeatureList& FeaturePolicy::getDefaultFeatureList() { |
+ // TODO: See if this should use lazy_instance instead |
+ CR_DEFINE_STATIC_LOCAL( |
+ FeatureList, defaultFeatureList, |
+ ({{blink::WebFeaturePolicyFeature::DocumentCookie, &kDocumentCookie}, |
+ {blink::WebFeaturePolicyFeature::DocumentDomain, &kDocumentDomain}, |
+ {blink::WebFeaturePolicyFeature::DocumentWrite, &kDocumentWrite}, |
+ {blink::WebFeaturePolicyFeature::Fullscreen, &kFullscreenFeature}, |
+ {blink::WebFeaturePolicyFeature::Geolocation, &kGeolocationFeature}, |
+ {blink::WebFeaturePolicyFeature::MidiFeature, &kMidiFeature}, |
+ {blink::WebFeaturePolicyFeature::Notifications, &kNotificationsFeature}, |
+ {blink::WebFeaturePolicyFeature::Payment, &kPaymentFeature}, |
+ {blink::WebFeaturePolicyFeature::Push, &kPushFeature}, |
+ {blink::WebFeaturePolicyFeature::SyncScript, &kSyncScript}, |
+ {blink::WebFeaturePolicyFeature::SyncXHR, &kSyncXHR}, |
+ {blink::WebFeaturePolicyFeature::Usermedia, &kUsermedia}, |
+ {blink::WebFeaturePolicyFeature::Vibrate, &kVibrateFeature}, |
+ {blink::WebFeaturePolicyFeature::WebRTC, &kWebRTC}})); |
+ return defaultFeatureList; |
+} |
+ |
+} // namespace content |