Commit 9594a5d4 authored by Charlie Hu's avatar Charlie Hu Committed by Commit Bot

Add DocumentPolicyFeature enum

This CL separates DocumentPolicyFeature enum from FeaturePolicyFeature
enum, which makes DocumentPolicy and FeaturePolicy independent to each
other. Previous test on document policy and feature policy coexist
is removed. Follow-up CL will replace all usage of migrated features,
i.e. font display and unoptimized-lossless-images so that current wpt
tests on document policy still pass.

Bug: 993790
Change-Id: I730b95efd013c25d97c2d24dd777e12b7b38bbb7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2028666
Commit-Queue: Charlie Hu <chenleihu@google.com>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarIan Clelland <iclelland@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#741609}
parent de075ce6
......@@ -195,6 +195,7 @@
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/feature_policy/document_policy_features.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
......@@ -3360,23 +3361,26 @@ bool RenderFrameHostImpl::IsFeatureEnabled(
bool RenderFrameHostImpl::IsFeatureEnabled(
blink::mojom::FeaturePolicyFeature feature,
blink::PolicyValue threshold_value) {
// Use Document Policy to determine feature availability, but only if all of
// the following are true:
// * The DocumentPolicy RuntimeEnabledFeature is not disabled,
// * Document policy has been set on this object, and
// * Document policy infrastructure actually supports the feature.
// If any of those are false, assume true (enabled) here. Otherwise, check
// this object's policy.
bool document_policy_result =
!base::FeatureList::IsEnabled(features::kDocumentPolicy) ||
!document_policy_ || !document_policy_->IsFeatureSupported(feature) ||
document_policy_->IsFeatureEnabled(feature, threshold_value);
return document_policy_result && feature_policy_ &&
return feature_policy_ &&
feature_policy_->IsFeatureEnabledForOrigin(
feature, GetLastCommittedOrigin(), threshold_value);
}
bool RenderFrameHostImpl::IsFeatureEnabled(
blink::mojom::DocumentPolicyFeature feature) {
blink::mojom::PolicyValueType feature_type =
blink::GetDocumentPolicyFeatureInfoMap().at(feature).default_value.Type();
return IsFeatureEnabled(
feature, blink::PolicyValue::CreateMaxPolicyValue(feature_type));
}
bool RenderFrameHostImpl::IsFeatureEnabled(
blink::mojom::DocumentPolicyFeature feature,
blink::PolicyValue threshold_value) {
return document_policy_ &&
document_policy_->IsFeatureEnabled(feature, threshold_value);
}
void RenderFrameHostImpl::ViewSource() {
delegate_->ViewSource(this);
}
......
......@@ -323,6 +323,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
bool IsFeatureEnabled(blink::mojom::FeaturePolicyFeature feature) override;
bool IsFeatureEnabled(blink::mojom::FeaturePolicyFeature feature,
blink::PolicyValue threshold_value) override;
bool IsFeatureEnabled(blink::mojom::DocumentPolicyFeature feature) override;
bool IsFeatureEnabled(blink::mojom::DocumentPolicyFeature feature,
blink::PolicyValue threshold_value) override;
void ViewSource() override;
mojo::Remote<blink::mojom::PauseSubresourceLoadingHandle>
PauseSubresourceLoading() override;
......
......@@ -25,6 +25,7 @@ import "services/viz/public/mojom/compositing/surface_id.mojom";
import "third_party/blink/public/mojom/blob/blob_url_store.mojom";
import "third_party/blink/public/mojom/commit_result/commit_result.mojom";
import "third_party/blink/public/mojom/devtools/console_message.mojom";
import "third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom";
import "third_party/blink/public/mojom/feature_policy/feature_policy.mojom";
import "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom";
import "third_party/blink/public/mojom/feature_policy/policy_value.mojom";
......@@ -442,7 +443,7 @@ interface FrameHost {
DidSetFramePolicyHeaders(
blink.mojom.WebSandboxFlags sandbox_flags,
array<blink.mojom.ParsedFeaturePolicyDeclaration> feature_policy_header,
map<blink.mojom.FeaturePolicyFeature, blink.mojom.PolicyValue>
map<blink.mojom.DocumentPolicyFeature, blink.mojom.PolicyValue>
document_policy_header);
// If a cross-process navigation was started for the initial history load in
......
......@@ -57,6 +57,7 @@
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
#include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h"
#include "third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/mojom/frame/blocked_navigation_types.mojom.h"
......@@ -124,6 +125,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(network::mojom::CSPDirectiveName,
network::mojom::CSPDirectiveName::kMaxValue)
IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::FeaturePolicyFeature,
blink::mojom::FeaturePolicyFeature::kMaxValue)
IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::DocumentPolicyFeature,
blink::mojom::DocumentPolicyFeature::kMaxValue)
IPC_ENUM_TRAITS_MAX_VALUE(blink::TriggeringEventInfo,
blink::TriggeringEventInfo::kMaxValue)
IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::UserActivationUpdateType,
......
......@@ -23,6 +23,7 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
#include "third_party/blink/public/common/feature_policy/document_policy.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
......@@ -360,11 +361,28 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
// third_party/blink/public/common/feature_policy/feature_policy.h for how to
// compare values of different types. Use this in the browser process to
// determine whether access to a feature is allowed.
//
// TODO(chenleihu): remove this method when policy with non-boolean value
// fully migrated to document policy. After the migration, feature policy
// feature will only only hold boolean type value, and this method signature
// will no longer be needed.
virtual bool IsFeatureEnabled(blink::mojom::FeaturePolicyFeature feature,
blink::PolicyValue threshold_value) = 0;
// Returns true if the queried FeaturePolicyFeature is allowed by
// feature policy.
virtual bool IsFeatureEnabled(blink::mojom::FeaturePolicyFeature feature) = 0;
// Returns true if the given |threshold_value| is below the threshold value
// specified in the policy for |feature| for this RenderFrameHost. See
// third_party/blink/public/common/feature_policy/document_policy.h for how to
// compare values of different types. Use this in the browser process to
// determine whether access to a feature is allowed.
virtual bool IsFeatureEnabled(blink::mojom::DocumentPolicyFeature feature,
blink::PolicyValue threshold_value) = 0;
// Same as above, with |threshold_value| set to the max value the given
// |feature| can have.
virtual bool IsFeatureEnabled(blink::mojom::FeaturePolicyFeature feature) = 0;
virtual bool IsFeatureEnabled(
blink::mojom::DocumentPolicyFeature feature) = 0;
// Opens view-source tab for the document last committed in this
// RenderFrameHost.
......
......@@ -42,7 +42,7 @@ base::Optional<std::string> DocumentPolicy::Serialize(
net::structured_headers::List root;
root.reserve(policy.size());
std::vector<std::pair<mojom::FeaturePolicyFeature, PolicyValue>>
std::vector<std::pair<mojom::DocumentPolicyFeature, PolicyValue>>
sorted_policy(policy.begin(), policy.end());
std::sort(sorted_policy.begin(), sorted_policy.end(),
[](const auto& a, const auto& b) {
......@@ -117,7 +117,7 @@ DocumentPolicy::FeatureState DocumentPolicy::MergeFeatureState(
}
bool DocumentPolicy::IsFeatureEnabled(
mojom::FeaturePolicyFeature feature) const {
mojom::DocumentPolicyFeature feature) const {
mojom::PolicyValueType feature_type =
GetDocumentPolicyFeatureInfoMap().at(feature).default_value.Type();
return IsFeatureEnabled(feature,
......@@ -125,22 +125,22 @@ bool DocumentPolicy::IsFeatureEnabled(
}
bool DocumentPolicy::IsFeatureEnabled(
mojom::FeaturePolicyFeature feature,
mojom::DocumentPolicyFeature feature,
const PolicyValue& threshold_value) const {
return GetFeatureValue(feature) >= threshold_value;
}
PolicyValue DocumentPolicy::GetFeatureValue(
mojom::FeaturePolicyFeature feature) const {
mojom::DocumentPolicyFeature feature) const {
return internal_feature_state_[static_cast<size_t>(feature)];
}
bool DocumentPolicy::IsFeatureSupported(
mojom::FeaturePolicyFeature feature) const {
mojom::DocumentPolicyFeature feature) const {
// TODO(iclelland): Generate this switch block
switch (feature) {
case mojom::FeaturePolicyFeature::kFontDisplay:
case mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages:
case mojom::DocumentPolicyFeature::kFontDisplay:
case mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages:
return true;
default:
return false;
......
......@@ -6,7 +6,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/feature_policy/document_policy_features.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom.h"
#include "third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom.h"
namespace blink {
namespace {
......@@ -19,7 +19,7 @@ DocumentPolicy::FeatureState FeatureState(
std::vector<std::pair<int32_t, T>> literal) {
DocumentPolicy::FeatureState result;
for (const auto& entry : literal) {
result.insert({static_cast<mojom::FeaturePolicyFeature>(entry.first),
result.insert({static_cast<mojom::DocumentPolicyFeature>(entry.first),
PolicyValue(entry.second)});
}
return result;
......@@ -48,8 +48,8 @@ TEST_F(DocumentPolicyTest, MergeFeatureState) {
// policy specifies a value for a feature and incoming policy is missing value
// for that feature.
TEST_F(DocumentPolicyTest, IsPolicyCompatible) {
mojom::FeaturePolicyFeature feature =
mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages;
mojom::DocumentPolicyFeature feature =
mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages;
double default_policy_value =
GetDocumentPolicyFeatureInfoMap().at(feature).default_value.DoubleValue();
// Cap the default_policy_value, as it can be INF.
......
......@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/feature_policy/policy_value.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom.h"
#include "third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom.h"
#include "third_party/blink/public/mojom/feature_policy/policy_value.mojom.h"
namespace blink {
......@@ -34,9 +34,7 @@ namespace blink {
// Features
// --------
// Features which can be controlled by policy are defined by instances of enum
// mojom::FeaturePolicyFeature, declared in |feature_policy_feature.mojom|.
// TODO(iclelland): Make a clear distinction between feature policy features
// and document policy features.
// mojom::DocumentPolicyFeature, declared in |document_policy_feature.mojom|.
//
// Declarations
// ------------
......@@ -65,27 +63,28 @@ namespace blink {
class BLINK_COMMON_EXPORT DocumentPolicy {
public:
using FeatureState = base::flat_map<mojom::FeaturePolicyFeature, PolicyValue>;
using FeatureState =
base::flat_map<mojom::DocumentPolicyFeature, PolicyValue>;
static std::unique_ptr<DocumentPolicy> CreateWithHeaderPolicy(
const FeatureState& header_policy);
// Returns true if the feature is unrestricted (has its default value for the
// platform)
bool IsFeatureEnabled(mojom::FeaturePolicyFeature feature) const;
bool IsFeatureEnabled(mojom::DocumentPolicyFeature feature) const;
// Returns true if the feature is unrestricted, or is not restricted as much
// as the given threshold value.
bool IsFeatureEnabled(mojom::FeaturePolicyFeature feature,
bool IsFeatureEnabled(mojom::DocumentPolicyFeature feature,
const PolicyValue& threshold_value) const;
// Returns true if the feature is being migrated to document policy
// TODO(iclelland): remove this method when those features are fully
// migrated to document policy.
bool IsFeatureSupported(mojom::FeaturePolicyFeature feature) const;
bool IsFeatureSupported(mojom::DocumentPolicyFeature feature) const;
// Returns the value of the given feature on the given origin.
PolicyValue GetFeatureValue(mojom::FeaturePolicyFeature feature) const;
PolicyValue GetFeatureValue(mojom::DocumentPolicyFeature feature) const;
// Returns true if the incoming policy is compatible with the given required
// policy, i.e. incoming policy is at least as strict as required policy.
......@@ -115,7 +114,7 @@ class BLINK_COMMON_EXPORT DocumentPolicy {
// Internal feature state is represented as an array to avoid overhead
// in using container classes.
PolicyValue internal_feature_state_
[static_cast<size_t>(mojom::FeaturePolicyFeature::kMaxValue) + 1];
[static_cast<size_t>(mojom::DocumentPolicyFeature::kMaxValue) + 1];
DISALLOW_COPY_AND_ASSIGN(DocumentPolicy);
};
......
......@@ -8,7 +8,7 @@
#include "base/containers/flat_map.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/feature_policy/policy_value.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-forward.h"
#include "third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom-forward.h"
namespace blink {
......@@ -19,10 +19,10 @@ struct DocumentPolicyFeatureInfo {
};
using DocumentPolicyFeatureInfoMap =
base::flat_map<mojom::FeaturePolicyFeature, DocumentPolicyFeatureInfo>;
base::flat_map<mojom::DocumentPolicyFeature, DocumentPolicyFeatureInfo>;
using DocumentPolicyNameFeatureMap =
base::flat_map<std::string, mojom::FeaturePolicyFeature>;
base::flat_map<std::string, mojom::DocumentPolicyFeature>;
BLINK_COMMON_EXPORT const DocumentPolicyFeatureInfoMap&
GetDocumentPolicyFeatureInfoMap();
......
......@@ -46,6 +46,7 @@ mojom("mojom_platform") {
"devtools/inspector_issue.mojom",
"favicon/favicon_url.mojom",
"feature_observer/feature_observer.mojom",
"feature_policy/document_policy_feature.mojom",
"feature_policy/feature_policy.mojom",
"feature_policy/feature_policy_feature.mojom",
"feature_policy/policy_value.mojom",
......
// Copyright 2020 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.
module blink.mojom;
// These values map to the features which can be controlled by Document Policy.
enum DocumentPolicyFeature {
kNotFound = 0,
// Controls access to font-display attribute in @font-face CSS rule
kFontDisplay = 1,
// When disallowed, these policies require images to have a reasonable byte-to-pixel ratio.
kUnoptimizedLosslessImages = 2,
// Don't change assigned numbers of any item, and don't reuse removed slots.
// Add new features at the end of the enum.
};
......@@ -5,6 +5,7 @@
module blink.mojom;
import "third_party/blink/public/mojom/feature_policy/feature_policy.mojom";
import "third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom";
import "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom";
import "third_party/blink/public/mojom/feature_policy/policy_value.mojom";
......@@ -15,7 +16,7 @@ import "third_party/blink/public/mojom/feature_policy/policy_value.mojom";
struct FramePolicy {
blink.mojom.WebSandboxFlags sandbox_flags;
array<blink.mojom.ParsedFeaturePolicyDeclaration> container_policy;
map<blink.mojom.FeaturePolicyFeature, blink.mojom.PolicyValue> required_document_policy;
map<blink.mojom.DocumentPolicyFeature, blink.mojom.PolicyValue> required_document_policy;
bool allowed_to_download = true;
bool disallow_document_access = false;
};
......@@ -29,15 +29,17 @@ class FeaturePolicyFeatureWriter(json5_generator.Writer):
runtime_features.append(feature)
origin_trials_set = origin_trials(runtime_features)
origin_trial_dependency_map = defaultdict(list)
fp_origin_trial_dependency_map = defaultdict(list)
dp_origin_trial_dependency_map = defaultdict(list)
runtime_to_feature_policy_map = defaultdict(list)
runtime_to_document_policy_map = defaultdict(list)
for feature in feature_policy_features + document_policy_features:
for dependency in feature['depends_on']:
if str(dependency) in origin_trials_set:
deps = origin_trial_dependency_map[feature['name']]
if dependency not in deps:
deps.append(dependency)
if feature['feature_policy_name']:
fp_origin_trial_dependency_map[feature['name']].append(dependency)
else:
dp_origin_trial_dependency_map[feature['name']].append(dependency)
else:
if feature['feature_policy_name']:
runtime_to_feature_policy_map[dependency].append(feature['name'])
......@@ -50,7 +52,8 @@ class FeaturePolicyFeatureWriter(json5_generator.Writer):
'input_files': self._input_files,
'feature_policy_features': feature_policy_features,
'document_policy_features': document_policy_features,
'origin_trial_dependency_map': origin_trial_dependency_map,
'fp_origin_trial_dependency_map': fp_origin_trial_dependency_map,
'dp_origin_trial_dependency_map': dp_origin_trial_dependency_map,
'runtime_to_feature_policy_map': runtime_to_feature_policy_map,
'runtime_to_document_policy_map': runtime_to_document_policy_map
}),
......
......@@ -6,8 +6,9 @@
#include "base/no_destructor.h"
#include "third_party/blink/public/common/feature_policy/document_policy_features.h"
#include "third_party/blink/public/common/feature_policy/policy_value.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom.h"
#include "third_party/blink/public/mojom/feature_policy/policy_value.mojom.h"
#include "third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom.h"
namespace blink {
......@@ -15,7 +16,7 @@ const DocumentPolicyFeatureInfoMap& GetDocumentPolicyFeatureInfoMap() {
static const base::NoDestructor<DocumentPolicyFeatureInfoMap> feature_info_map({
{%- for feature in features %}
{
mojom::FeaturePolicyFeature::k{{feature.name}},
mojom::DocumentPolicyFeature::k{{feature.name}},
{
"{{feature.document_policy_name}}",
"{{feature.value_name}}",
......
......@@ -32,7 +32,7 @@ const FeatureNameMap& GetDefaultFeatureNameMap() {
DEFINE_STATIC_LOCAL(FeatureNameMap, default_feature_name_map, ());
if (default_feature_name_map.IsEmpty()) {
{% for feature in feature_policy_features %}
{% if not feature.depends_on or feature.name in origin_trial_dependency_map %}
{% if not feature.depends_on or feature.name in fp_origin_trial_dependency_map %}
default_feature_name_map.Set(k{{feature.name}}PolicyName,
mojom::FeaturePolicyFeature::k{{feature.name}});
{% endif %}
......@@ -49,18 +49,18 @@ const FeatureNameMap& GetDefaultFeatureNameMap() {
return default_feature_name_map;
}
const FeatureSet& GetAvailableDocumentPolicyFeatures() {
DEFINE_STATIC_LOCAL(FeatureSet, features, ());
const DocumentPolicyFeatureSet& GetAvailableDocumentPolicyFeatures() {
DEFINE_STATIC_LOCAL(DocumentPolicyFeatureSet, features, ());
if (features.IsEmpty()) {
{% for feature in document_policy_features %}
{% if not feature.depends_on or feature.name in origin_trial_dependency_map %}
features.insert(mojom::FeaturePolicyFeature::k{{feature.name}});
{% if not feature.depends_on or feature.name in dp_origin_trial_dependency_map %}
features.insert(mojom::DocumentPolicyFeature::k{{feature.name}});
{% endif %}
{% endfor %}
{% for runtime_feature_name, dependent_features in runtime_to_document_policy_map.items() | sort %}
if (RuntimeEnabledFeatures::{{runtime_feature_name}}Enabled()) {
{% for feature in dependent_features %}
features.insert(mojom::FeaturePolicyFeature::k{{feature}});
features.insert(mojom::DocumentPolicyFeature::k{{feature}});
{% endfor %}
}
{% endfor %}
......@@ -72,7 +72,7 @@ const FeatureSet& GetAvailableDocumentPolicyFeatures() {
// i.e. the feature is considered enabled by origin trial.
bool DisabledByOriginTrial(const String& feature_name,
FeatureContext* feature_context) {
{% for feature_name, dependencies in origin_trial_dependency_map.items() | sort %}
{% for feature_name, dependencies in fp_origin_trial_dependency_map.items() | sort %}
if (feature_name == k{{feature_name}}PolicyName) {
return
{%- for dependency in dependencies %}
......@@ -84,10 +84,10 @@ bool DisabledByOriginTrial(const String& feature_name,
return false;
}
bool DisabledByOriginTrial(mojom::blink::FeaturePolicyFeature feature,
bool DisabledByOriginTrial(mojom::blink::DocumentPolicyFeature feature,
FeatureContext* feature_context) {
{% for feature_name, dependencies in origin_trial_dependency_map.items() | sort %}
if (feature == mojom::FeaturePolicyFeature::k{{feature_name}}) {
{% for feature_name, dependencies in dp_origin_trial_dependency_map.items() | sort %}
if (feature == mojom::DocumentPolicyFeature::k{{feature_name}}) {
return
{%- for dependency in dependencies %}
{%- if not loop.first %} &&{% endif %}
......
......@@ -1207,64 +1207,6 @@ TEST_F(DocumentTest, PrefersColorSchemeChanged) {
EXPECT_TRUE(listener->IsNotified());
}
TEST_F(DocumentTest, DocumentPolicyFeaturePolicyCoexist) {
blink::ScopedDocumentPolicyForTest sdp(true);
const auto test_feature =
blink::mojom::blink::FeaturePolicyFeature::kFontDisplay;
const auto unsupported_feature =
blink::mojom::blink::FeaturePolicyFeature::kSyncScript;
const auto report_option = blink::ReportOptions::kReportOnFailure;
// When document_policy is not specified in response header, default values
// are used for document policy.
NavigateTo(KURL("https://www.example.com/"), "", "");
GetDocument().GetSecurityContext().SetDocumentPolicyForTesting(
DocumentPolicy::CreateWithHeaderPolicy({}));
EXPECT_EQ(
GetDocumentPolicyFeatureInfoMap().at(test_feature).default_value,
GetDocument().GetSecurityContext().GetDocumentPolicy()->GetFeatureValue(
test_feature));
// When document_policy is specified, both feature_policy and
// document_policy need to return true for the feature to be
// enabled.
NavigateTo(KURL("https://www.example.com/"), "font-display-late-swap *", "");
GetDocument().GetSecurityContext().SetDocumentPolicyForTesting(
DocumentPolicy::CreateWithHeaderPolicy(
{{test_feature, blink::PolicyValue(true)}}));
EXPECT_TRUE(GetDocument().IsFeatureEnabled(test_feature, report_option));
GetDocument().GetSecurityContext().SetDocumentPolicyForTesting(
DocumentPolicy::CreateWithHeaderPolicy(
{{test_feature, blink::PolicyValue(false)}}));
EXPECT_FALSE(GetDocument().IsFeatureEnabled(test_feature, report_option));
NavigateTo(KURL("https://www.example.com/"), "font-display-late-swap 'none'",
"");
GetDocument().GetSecurityContext().SetDocumentPolicyForTesting(
DocumentPolicy::CreateWithHeaderPolicy(
{{test_feature, blink::PolicyValue(true)}}));
EXPECT_FALSE(GetDocument().IsFeatureEnabled(test_feature, report_option));
GetDocument().GetSecurityContext().SetDocumentPolicyForTesting(
DocumentPolicy::CreateWithHeaderPolicy(
{{test_feature, blink::PolicyValue(false)}}));
EXPECT_FALSE(GetDocument().IsFeatureEnabled(test_feature, report_option));
// When document policy does not handle a particular feature, it must not
// block it.
NavigateTo(KURL("https://www.example.com/"), "sync-script *", "");
EXPECT_TRUE(
GetDocument().IsFeatureEnabled(unsupported_feature, report_option));
GetDocument().GetSecurityContext().SetDocumentPolicyForTesting(
DocumentPolicy::CreateWithHeaderPolicy(
{{test_feature, blink::PolicyValue(true)}}));
ASSERT_FALSE(GetDocument()
.GetSecurityContext()
.GetDocumentPolicy()
->IsFeatureSupported(unsupported_feature));
EXPECT_TRUE(
GetDocument().IsFeatureEnabled(unsupported_feature, report_option));
}
TEST_F(DocumentTest, FindInPageUkm) {
GetDocument().ukm_recorder_ = std::make_unique<ukm::TestUkmRecorder>();
auto* recorder =
......
......@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "base/metrics/histogram_macros.h"
#include "third_party/blink/public/common/feature_policy/document_policy_features.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
......@@ -401,6 +402,19 @@ bool ExecutionContext::IsFeatureEnabled(
return enabled;
}
bool ExecutionContext::IsFeatureEnabled(
mojom::blink::DocumentPolicyFeature feature) const {
PolicyValue threshold_value = PolicyValue::CreateMaxPolicyValue(
GetDocumentPolicyFeatureInfoMap().at(feature).default_value.Type());
return IsFeatureEnabled(feature, threshold_value);
}
bool ExecutionContext::IsFeatureEnabled(
mojom::blink::DocumentPolicyFeature feature,
PolicyValue threshold_value) const {
return GetSecurityContext().IsFeatureEnabled(feature, threshold_value);
}
bool ExecutionContext::RequireTrustedTypes() const {
return GetSecurityContext().TrustedTypesRequiredByPolicy() &&
RuntimeEnabledFeatures::TrustedDOMTypesEnabled(this);
......
......@@ -322,6 +322,10 @@ class CORE_EXPORT ExecutionContext
ReportOptions report_on_failure = ReportOptions::kDoNotReport,
const String& message = g_empty_string,
const String& source_file = g_empty_string) const;
bool IsFeatureEnabled(mojom::blink::DocumentPolicyFeature) const;
bool IsFeatureEnabled(mojom::blink::DocumentPolicyFeature,
PolicyValue threshold_value) const;
virtual void CountPotentialFeaturePolicyViolation(
mojom::blink::FeaturePolicyFeature) const {}
virtual void ReportFeaturePolicyViolation(
......
......@@ -28,6 +28,7 @@
#include "base/metrics/histogram_macros.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "third_party/blink/public/common/feature_policy/document_policy_features.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
......@@ -184,27 +185,30 @@ bool SecurityContext::IsFeatureEnabled(
mojom::blink::FeaturePolicyFeature feature,
PolicyValue threshold_value,
base::Optional<mojom::FeaturePolicyDisposition>* disposition) const {
// Use Document Policy to determine feature availability, but only if all of
// the following are true:
// * The DocumentPolicy RuntimeEnabledFeature is not disabled,
// * Document policy has been set on this object, and
// * Document policy infrastructure actually supports the feature.
// If any of those are false, assume true (enabled) here. Otherwise, check
// this object's policy.
bool document_policy_result =
!RuntimeEnabledFeatures::DocumentPolicyEnabled() || !document_policy_ ||
!document_policy_->IsFeatureSupported(feature) ||
document_policy_->IsFeatureEnabled(feature, threshold_value);
FeatureEnabledState state = GetFeatureEnabledState(feature, threshold_value);
if (state == FeatureEnabledState::kEnabled)
return document_policy_result;
return true;
if (disposition) {
*disposition = (state == FeatureEnabledState::kReportOnly)
? mojom::FeaturePolicyDisposition::kReport
: mojom::FeaturePolicyDisposition::kEnforce;
}
return (state != FeatureEnabledState::kDisabled) && document_policy_result;
return (state != FeatureEnabledState::kDisabled);
}
bool SecurityContext::IsFeatureEnabled(
mojom::blink::DocumentPolicyFeature feature) const {
return IsFeatureEnabled(
feature,
PolicyValue::CreateMaxPolicyValue(
GetDocumentPolicyFeatureInfoMap().at(feature).default_value.Type()));
}
bool SecurityContext::IsFeatureEnabled(
mojom::blink::DocumentPolicyFeature feature,
PolicyValue threshold_value) const {
DCHECK(document_policy_);
return document_policy_->IsFeatureEnabled(feature, threshold_value);
}
FeatureEnabledState SecurityContext::GetFeatureEnabledState(
......
......@@ -34,6 +34,7 @@
#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
#include "third_party/blink/public/common/feature_policy/document_policy.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
#include "third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
......@@ -167,6 +168,10 @@ class CORE_EXPORT SecurityContext {
PolicyValue threshold_value,
base::Optional<mojom::FeaturePolicyDisposition>* = nullptr) const;
bool IsFeatureEnabled(mojom::blink::DocumentPolicyFeature) const;
bool IsFeatureEnabled(mojom::blink::DocumentPolicyFeature,
PolicyValue threshold_value) const;
protected:
mojom::blink::WebSandboxFlags sandbox_flags_;
scoped_refptr<SecurityOrigin> security_origin_;
......
......@@ -35,7 +35,7 @@ DocumentPolicyParser::ParseInternal(
const String& policy_string,
const DocumentPolicyNameFeatureMap& name_feature_map,
const DocumentPolicyFeatureInfoMap& feature_info_map,
const FeatureSet& available_features) {
const DocumentPolicyFeatureSet& available_features) {
auto root = net::structured_headers::ParseList(policy_string.Ascii());
if (!root)
return base::nullopt;
......@@ -82,7 +82,7 @@ DocumentPolicyParser::ParseInternal(
name_feature_map.end()) // Unrecognized feature name.
return base::nullopt;
const mojom::blink::FeaturePolicyFeature feature =
const mojom::blink::DocumentPolicyFeature feature =
name_feature_map.at(feature_name);
// If feature is not available, i.e. not enabled, ignore the entry.
......
......@@ -26,7 +26,7 @@ class CORE_EXPORT DocumentPolicyParser {
const String& policy_string,
const DocumentPolicyNameFeatureMap& name_feature_map,
const DocumentPolicyFeatureInfoMap& feature_info_map,
const FeatureSet& available_features);
const DocumentPolicyFeatureSet& available_features);
};
} // namespace blink
......
......@@ -36,52 +36,53 @@ const char* const kInvalidPolicies[] = {
// tokens
};
// TODO(chenleihu): find a FeaturePolicyFeature name start with 'f' < c < 'n'
// TODO(chenleihu): find a DocumentPolicyFeature name start with 'f' < c < 'n'
// to further strengthen the test on proving "no-" prefix is not counted as part
// of feature name for ordering.
const std::pair<DocumentPolicy::FeatureState, std::string>
kPolicySerializationTestCases[] = {
{{{blink::mojom::FeaturePolicyFeature::kFontDisplay,
{{{blink::mojom::DocumentPolicyFeature::kFontDisplay,
PolicyValue(false)},
{blink::mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages,
{blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
PolicyValue(1.0)}},
"no-font-display-late-swap, unoptimized-lossless-images;bpp=1.0"},
// Changing ordering of FeatureState element should not affect
// serialization result.
{{{blink::mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages,
{{{blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
PolicyValue(1.0)},
{blink::mojom::FeaturePolicyFeature::kFontDisplay,
{blink::mojom::DocumentPolicyFeature::kFontDisplay,
PolicyValue(false)}},
"no-font-display-late-swap, unoptimized-lossless-images;bpp=1.0"},
// Flipping boolean-valued policy from false to true should not affect
// result ordering of feature.
{{{blink::mojom::FeaturePolicyFeature::kFontDisplay, PolicyValue(true)},
{blink::mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages,
{{{blink::mojom::DocumentPolicyFeature::kFontDisplay,
PolicyValue(true)},
{blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
PolicyValue(1.0)}},
"font-display-late-swap, unoptimized-lossless-images;bpp=1.0"}};
const std::pair<const char*, DocumentPolicy::FeatureState>
kPolicyParseTestCases[] = {
{"no-font-display-late-swap,unoptimized-lossless-images;bpp=1",
{{blink::mojom::FeaturePolicyFeature::kFontDisplay,
{{blink::mojom::DocumentPolicyFeature::kFontDisplay,
PolicyValue(false)},
{blink::mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages,
{blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
PolicyValue(1.0)}}},
// White-space is allowed in some positions in structured-header.
{"no-font-display-late-swap, unoptimized-lossless-images;bpp=1",
{{blink::mojom::FeaturePolicyFeature::kFontDisplay,
{{blink::mojom::DocumentPolicyFeature::kFontDisplay,
PolicyValue(false)},
{blink::mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages,
{blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
PolicyValue(1.0)}}}};
const DocumentPolicy::FeatureState kParsedPolicies[] = {
{}, // An empty policy
{{mojom::FeaturePolicyFeature::kFontDisplay, PolicyValue(false)}},
{{mojom::FeaturePolicyFeature::kFontDisplay, PolicyValue(true)}},
{{mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages,
{{mojom::DocumentPolicyFeature::kFontDisplay, PolicyValue(false)}},
{{mojom::DocumentPolicyFeature::kFontDisplay, PolicyValue(true)}},
{{mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
PolicyValue(1.0)}},
{{mojom::FeaturePolicyFeature::kFontDisplay, PolicyValue(true)},
{mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages,
{{mojom::DocumentPolicyFeature::kFontDisplay, PolicyValue(true)},
{mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
PolicyValue(1.0)}}};
// Serialize and then Parse the result of serialization should cancel each
......
......@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FEATURE_POLICY_FEATURE_POLICY_HELPER_H_
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
......@@ -15,8 +16,9 @@
namespace blink {
using FeatureNameMap = HashMap<String, mojom::blink::FeaturePolicyFeature>;
using FeatureSet = HashSet<mojom::blink::FeaturePolicyFeature,
IntHash<mojom::blink::FeaturePolicyFeature>>;
using DocumentPolicyFeatureSet =
HashSet<mojom::blink::DocumentPolicyFeature,
IntHash<mojom::blink::DocumentPolicyFeature>>;
class FeatureContext;
......@@ -30,15 +32,17 @@ const FeatureNameMap& GetDefaultFeatureNameMap();
// for the Document-Policy HTTP header and the <iframe> "policy" attribute, as
// well as the features which will be recognized by the document or iframe
// policy object.
const FeatureSet& GetAvailableDocumentPolicyFeatures();
const DocumentPolicyFeatureSet& GetAvailableDocumentPolicyFeatures();
// Returns true if this feature is currently disabled by an origin trial (it is
// origin trial controlled, and the origin trial is not enabled).
// Returns true if this FeaturePolicyFeature is currently disabled by an origin
// trial (it is origin trial controlled, and the origin trial is not enabled).
// The first String param should be a name of FeaturePolicyFeature.
bool DisabledByOriginTrial(const String&, FeatureContext*);
// Returns true if this feature is currently disabled by an origin trial (it is
// origin trial controlled, and the origin trial is not enabled).
bool DisabledByOriginTrial(mojom::blink::FeaturePolicyFeature, FeatureContext*);
// Returns true if this DocumentPolicyFeature is currently disabled by an origin
// trial (it is origin trial controlled, and the origin trial is not enabled).
bool DisabledByOriginTrial(mojom::blink::DocumentPolicyFeature,
FeatureContext*);
} // namespace blink
......
......@@ -6122,6 +6122,8 @@ crbug.com/1006759 http/tests/devtools/modules-load-source.js [ Pass Failure ]
# Failing document policy tests
crbug.com/993790 external/wpt/document-policy/required-policy/separate-document-policies.html [ Failure ]
crbug.com/993790 external/wpt/document-policy/font-display/font-display-document-policy-01.tentative.html [ Failure ]
crbug.com/993790 http/tests/images/document-policy-unoptimized-lossless-images.php [ Failure ]
# Temporary suppression to allow devtools-frontend changes
crbug.com/1029489 http/tests/devtools/elements/elements-linkify-attributes.js [ Pass Failure Timeout ]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment