Skip to content

Commit

Permalink
Reland "Implement permissions policy parser"
Browse files Browse the repository at this point in the history
This reverts commit 9a47d28.

Original change's description:
> Revert "Implement permissions policy parser"
>
> This reverts commit a96776d.
>
> Reason for revert: Broke Linux bots:
> https://ci.chromium.org/p/chromium/builders/ci/linux-blink-cors-rel/6631
> https://ci.chromium.org/p/chromium/builders/ci/Cast%20Linux/95081
>
> Original change's description:
> > Implement permissions policy parser
> >
> > Implement permissions policy parser based on this proposal:
> > w3c/webappsec-permissions-policy#376
> >
> > Change-Id: I50e160afa0f2e3039b67388c71bf5879957ad784
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2240900
> > Commit-Queue: Charlie Hu <[email protected]>
> > Reviewed-by: Ian Clelland <[email protected]>
> > Cr-Commit-Position: refs/heads/master@{#783581}
>
> [email protected],[email protected]
>
> Change-Id: Iee0cbaa33aff49f2473c374d5c0af5d0e04e6985
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2273604
> Reviewed-by: Dale Curtis <[email protected]>
> Commit-Queue: Dale Curtis <[email protected]>
> Cr-Commit-Position: refs/heads/master@{#783606}

[email protected],[email protected],[email protected]

Change-Id: I852afc10dee493b15f02c083762b9f2dae4d0f2c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2273082
Reviewed-by: Charlie Hu <[email protected]>
Reviewed-by: Ian Clelland <[email protected]>
Commit-Queue: Charlie Hu <[email protected]>
Cr-Commit-Position: refs/heads/master@{#783694}
  • Loading branch information
Charlie Hu authored and Commit Bot committed Jun 29, 2020
1 parent 80ff439 commit 3f1b882
Show file tree
Hide file tree
Showing 4 changed files with 364 additions and 109 deletions.
121 changes: 101 additions & 20 deletions third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <bitset>
#include "base/metrics/histogram_macros.h"
#include "net/http/structured_headers.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
Expand Down Expand Up @@ -50,12 +51,11 @@ class ParsingContext {

~ParsingContext() = default;

ParsedFeaturePolicy Parse(const String& policy);

private:
ParsedFeaturePolicy ParseIR(const internal::FeaturePolicyNode& root);
internal::FeaturePolicyNode ParseToIR(const String& policy);
internal::FeaturePolicyNode ParseFeaturePolicyToIR(const String& policy);
internal::FeaturePolicyNode ParsePermissionsPolicyToIR(const String& policy);

private:
// normally 1 char = 1 byte
// max length to parse = 2^16 = 64 kB
static constexpr wtf_size_t MAX_LENGTH_PARSE = 1 << 16;
Expand Down Expand Up @@ -328,10 +328,6 @@ base::Optional<ParsedFeaturePolicyDeclaration> ParsingContext::ParseFeature(
return parsed_feature;
}

ParsedFeaturePolicy ParsingContext::Parse(const String& policy) {
return ParseIR(ParseToIR(policy));
}

ParsedFeaturePolicy ParsingContext::ParseIR(
const internal::FeaturePolicyNode& root) {
ParsedFeaturePolicy parsed_policy;
Expand All @@ -347,7 +343,8 @@ ParsedFeaturePolicy ParsingContext::ParseIR(
return parsed_policy;
}

internal::FeaturePolicyNode ParsingContext::ParseToIR(const String& policy) {
internal::FeaturePolicyNode ParsingContext::ParseFeaturePolicyToIR(
const String& policy) {
internal::FeaturePolicyNode root;

if (policy.length() > MAX_LENGTH_PARSE) {
Expand Down Expand Up @@ -403,15 +400,87 @@ internal::FeaturePolicyNode ParsingContext::ParseToIR(const String& policy) {
return root;
}

internal::FeaturePolicyNode ParsingContext::ParsePermissionsPolicyToIR(
const String& policy) {
auto root = net::structured_headers::ParseDictionary(policy.Utf8());
if (!root) {
logger_.Error(
"Parse of permission policy failed because of errors reported by "
"strctured header parser.");
return {};
}

internal::FeaturePolicyNode ir_root;
for (const auto& feature_entry : root.value()) {
const auto& key = feature_entry.first;
const char* feature_name = key.c_str();
const auto& value = feature_entry.second;

if (!value.params.empty()) {
logger_.Warn(
String::Format("Feature %s's parameters are ignored.", feature_name));
}

Vector<String> allowlist;
for (const auto& parameterized_item : value.member) {
if (!parameterized_item.params.empty()) {
logger_.Warn(String::Format("Feature %s's parameters are ignored.",
feature_name));
}

String allowlist_item;
if (parameterized_item.item.is_token()) {
// All special keyword appears as token, i.e. self, src and *.
const std::string& token_value = parameterized_item.item.GetString();
if (token_value != "*" && token_value != "self") {
logger_.Warn(String::Format(
"Invalid allowlist item(%s) for feature %s. Allowlist item "
"must be *, self or quoted url.",
token_value.c_str(), feature_name));
continue;
}

if (token_value == "*") {
allowlist_item = "*";
} else {
allowlist_item = String::Format("'%s'", token_value.c_str());
}
} else if (parameterized_item.item.is_string()) {
allowlist_item = parameterized_item.item.GetString().c_str();
} else {
logger_.Warn(
String::Format("Invalid allowlist item for feature %s. Allowlist "
"item must be *, self, or quoted url.",
feature_name));
continue;
}
allowlist.push_back(allowlist_item);
}

if (allowlist.IsEmpty())
allowlist.push_back("'none'");

ir_root.push_back(
internal::FeaturePolicyDeclarationNode{feature_name, allowlist});
}

return ir_root;
}

} // namespace

ParsedFeaturePolicy FeaturePolicyParser::ParseHeader(
const String& policy,
const String& feature_policy_header,
scoped_refptr<const SecurityOrigin> origin,
PolicyParserMessageBuffer& logger,
FeaturePolicyParserDelegate* delegate) {
return Parse(policy, origin, nullptr, logger, GetDefaultFeatureNameMap(),
delegate);
FeaturePolicyParserDelegate* delegate,
const String& permissions_policy_header) {
ParsingContext context(logger, origin, nullptr, GetDefaultFeatureNameMap(),
delegate);
auto policy_ir =
context.ParsePermissionsPolicyToIR(permissions_policy_header);
policy_ir.AppendVector(context.ParseFeaturePolicyToIR(feature_policy_header));
return context.ParseIR(policy_ir);
}

ParsedFeaturePolicy FeaturePolicyParser::ParseAttribute(
Expand All @@ -420,21 +489,33 @@ ParsedFeaturePolicy FeaturePolicyParser::ParseAttribute(
scoped_refptr<const SecurityOrigin> src_origin,
PolicyParserMessageBuffer& logger,
FeaturePolicyParserDelegate* delegate) {
return Parse(policy, self_origin, src_origin, logger,
GetDefaultFeatureNameMap(), delegate);
ParsingContext context(logger, self_origin, src_origin,
GetDefaultFeatureNameMap(), delegate);
return context.ParseIR(context.ParseFeaturePolicyToIR(policy));
}

ParsedFeaturePolicy FeaturePolicyParser::ParseFeaturePolicyForTest(
const String& policy,
scoped_refptr<const SecurityOrigin> self_origin,
scoped_refptr<const SecurityOrigin> src_origin,
PolicyParserMessageBuffer& logger,
const FeatureNameMap& feature_names,
FeaturePolicyParserDelegate* delegate) {
ParsingContext context(logger, self_origin, src_origin, feature_names,
delegate);
return context.ParseIR(context.ParseFeaturePolicyToIR(policy));
}

// static
ParsedFeaturePolicy FeaturePolicyParser::Parse(
ParsedFeaturePolicy FeaturePolicyParser::ParsePermissionsPolicyForTest(
const String& policy,
scoped_refptr<const SecurityOrigin> self_origin,
scoped_refptr<const SecurityOrigin> src_origin,
PolicyParserMessageBuffer& logger,
const FeatureNameMap& feature_names,
FeaturePolicyParserDelegate* delegate) {
return ParsingContext(logger, self_origin, src_origin, feature_names,
delegate)
.Parse(policy);
ParsingContext context(logger, self_origin, src_origin, feature_names,
delegate);
return context.ParseIR(context.ParsePermissionsPolicyToIR(policy));
}

bool IsFeatureDeclared(mojom::blink::FeaturePolicyFeature feature,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,11 @@ class CORE_EXPORT FeaturePolicyParser {
// parsing. Example of a feature policy string:
// "vibrate a.com b.com; fullscreen 'none'; payment 'self', payment *".
static ParsedFeaturePolicy ParseHeader(
const String& policy,
const String& feature_policy_header,
scoped_refptr<const SecurityOrigin>,
PolicyParserMessageBuffer& logger,
FeaturePolicyParserDelegate* delegate = nullptr);
FeaturePolicyParserDelegate* delegate = nullptr,
const String& permission_policy_header = g_empty_string);

// Converts a container policy string into a vector of allowlists, given self
// and src origins provided, one for each feature specified. Unrecognized
Expand All @@ -75,20 +76,23 @@ class CORE_EXPORT FeaturePolicyParser {
PolicyParserMessageBuffer& logger,
FeaturePolicyParserDelegate* delegate = nullptr);

// Converts a feature policy string into a vector of allowlists (see comments
// above), with an explicit FeatureNameMap. This algorithm is called by both
// header policy parsing and container policy parsing. |self_origin|,
// |src_origin|, and |execution_context| are nullable. The optional
// ExecutionContext is used to determine if any origin trials affect the
// parsing.
static ParsedFeaturePolicy Parse(
static ParsedFeaturePolicy ParseFeaturePolicyForTest(
const String& policy,
scoped_refptr<const SecurityOrigin> self_origin,
scoped_refptr<const SecurityOrigin> src_origin,
PolicyParserMessageBuffer& logger,
const FeatureNameMap& feature_names,
FeaturePolicyParserDelegate* delegate = nullptr);

static ParsedFeaturePolicy ParsePermissionsPolicyForTest(
const String& policy,
scoped_refptr<const SecurityOrigin> self_origin,
scoped_refptr<const SecurityOrigin> src_origin,
PolicyParserMessageBuffer& logger,
const FeatureNameMap& feature_names,
FeaturePolicyParserDelegate* delegate = nullptr);
};

// Returns true iff any declaration in the policy is for the given feature.
CORE_EXPORT bool IsFeatureDeclared(mojom::blink::FeaturePolicyFeature,
const ParsedFeaturePolicy&);
Expand Down
Loading

0 comments on commit 3f1b882

Please sign in to comment.