| 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 | 
| index a8204daa5021e845062c11360d561311959145d3..c4875a9c01fc463b1327854fbc880fff326ea103 100644 | 
| --- a/content/common/feature_policy/feature_policy.cc | 
| +++ b/content/common/feature_policy/feature_policy.cc | 
| @@ -4,8 +4,70 @@ | 
|  | 
| #include "content/common/feature_policy/feature_policy.h" | 
|  | 
| +#include "base/macros.h" | 
| +#include "base/memory/ptr_util.h" | 
| +#include "base/stl_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( | 
| +    const 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 ParsedFeaturePolicyDeclaration. | 
| +std::unique_ptr<FeaturePolicy::Whitelist> WhitelistFromDeclaration( | 
| +    const ParsedFeaturePolicyDeclaration& 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 | 
| + | 
| ParsedFeaturePolicyDeclaration::ParsedFeaturePolicyDeclaration() | 
| : matches_all_origins(false) {} | 
|  | 
| @@ -22,4 +84,121 @@ ParsedFeaturePolicyDeclaration::ParsedFeaturePolicyDeclaration( | 
|  | 
| ParsedFeaturePolicyDeclaration::~ParsedFeaturePolicyDeclaration() {} | 
|  | 
| +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, | 
| +    const url::Origin& origin) { | 
| +  return CreateFromParentPolicy(parent_policy, origin, GetDefaultFeatureList()); | 
| +} | 
| + | 
| +bool FeaturePolicy::IsFeatureEnabledForOrigin( | 
| +    blink::WebFeaturePolicyFeature feature, | 
| +    const url::Origin& origin) const { | 
| +  DCHECK(base::ContainsKey(feature_list_, feature)); | 
| +  const FeaturePolicy::Feature* feature_definition = feature_list_.at(feature); | 
| +  DCHECK(base::ContainsKey(inherited_policies_, feature)); | 
| +  if (!inherited_policies_.at(feature)) | 
| +    return false; | 
| +  auto whitelist = whitelists_.find(feature); | 
| +  if (whitelist != whitelists_.end()) | 
| +    return whitelist->second->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 ParsedFeaturePolicyHeader& parsed_header) { | 
| +  DCHECK(whitelists_.empty()); | 
| +  for (const ParsedFeaturePolicyDeclaration& 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, | 
| +    const url::Origin& origin, | 
| +    const FeaturePolicy::FeatureList& features) { | 
| +  std::unique_ptr<FeaturePolicy> new_policy = | 
| +      base::WrapUnique(new FeaturePolicy(origin, features)); | 
| +  for (const auto& feature : features) { | 
| +    if (!parent_policy || | 
| +        parent_policy->IsFeatureEnabledForOrigin(feature.first, origin)) { | 
| +      new_policy->inherited_policies_[feature.first] = true; | 
| +    } else { | 
| +      new_policy->inherited_policies_[feature.first] = false; | 
| +    } | 
| +  } | 
| +  return new_policy; | 
| +} | 
| + | 
| +// static | 
| +const FeaturePolicy::FeatureList& FeaturePolicy::GetDefaultFeatureList() { | 
| +  CR_DEFINE_STATIC_LOCAL( | 
| +      FeatureList, default_feature_list, | 
| +      ({{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 default_feature_list; | 
| +} | 
| + | 
| }  // namespace content | 
|  |