blob: 7dae83c41768f3566034a0eecae290dbf7b03590 [file] [log] [blame]
// Copyright 2019 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.
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_FEATURE_POLICY_DOCUMENT_POLICY_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_FEATURE_POLICY_DOCUMENT_POLICY_H_
#include <memory>
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "third_party/blink/public/common/common_export.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/document_policy_feature.mojom.h"
#include "third_party/blink/public/mojom/feature_policy/policy_value.mojom.h"
namespace blink {
// Document Policy is a mechanism for controlling the behaviour of web platform
// features in a document, and for requesting such changes in embedded frames.
// (The specific changes which are made depend on the feature; see the
// specification for details).
//
// Policies can be defined in the HTTP header stream, with the |Document-Policy|
// HTTP header, or can be set by the |policy| attributes on the iframe element
// which embeds the document.
//
// See
// https://github.com/w3c/webappsec-permissions-policy/blob/master/document-policy-explainer.md
//
// Key concepts:
//
// Features
// --------
// Features which can be controlled by policy are defined by instances of enum
// mojom::DocumentPolicyFeature, declared in |document_policy_feature.mojom|.
//
// Declarations
// ------------
// A document policy declaration is a mapping of a feature name to a policy
// value. A set of such declarations is a declared policy. The declared policy
// is attached to a document.
//
// Required Policy
// ----------------
// In addition to the declared policy (which may be empty), every frame has
// an required policy, which is set by the embedding document (or inherited
// from its parent). Any document loaded into a frame with a required policy
// must have a declared policy which is compatible with it. Frames may add new
// requirements to their own subframes, but cannot relax any existing ones.
//
// Advertised Policy
// -----------------
// If a frame has a non-empty required policy, the requirements will be
// advertised on the outgoing HTTP request for any document to be loaded in that
// frame, in the Sec-Required-Document-Policy HTTP header.
//
// Defaults
// --------
// Each defined feature has a default policy, which determines the threshold
// value to use when no policy has been declared.
class BLINK_COMMON_EXPORT DocumentPolicy {
public:
// Mapping of feature to endpoint group.
// https://w3c.github.io/reporting/#endpoint-group
using FeatureEndpointMap =
base::flat_map<mojom::DocumentPolicyFeature, std::string>;
struct ParsedDocumentPolicy {
DocumentPolicyFeatureState feature_state;
FeatureEndpointMap endpoint_map;
};
static std::unique_ptr<DocumentPolicy> CreateWithHeaderPolicy(
const ParsedDocumentPolicy& header_policy);
static std::unique_ptr<DocumentPolicy> CopyStateFrom(const DocumentPolicy*);
// Returns true if the feature is unrestricted (has its default value for the
// platform)
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::DocumentPolicyFeature feature,
const PolicyValue& threshold_value) const;
// Returns the value of the given feature on the given origin.
PolicyValue GetFeatureValue(mojom::DocumentPolicyFeature feature) const;
// Returns the endpoint the given feature should report to.
// Returns base::nullopt if the endpoint is unspecified for given feature.
const base::Optional<std::string> GetFeatureEndpoint(
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.
static bool IsPolicyCompatible(
const DocumentPolicyFeatureState& required_policy,
const DocumentPolicyFeatureState& incoming_policy);
// Serialize document policy according to http_structured_header.
// returns base::nullopt when http structured header serializer encounters
// problems, e.g. double value out of the range supported.
static base::Optional<std::string> Serialize(
const DocumentPolicyFeatureState& policy);
static base::Optional<std::string> SerializeInternal(
const DocumentPolicyFeatureState& policy,
const DocumentPolicyFeatureInfoMap&);
// Merge two FeatureState map.
// When there is conflict:
// - take the stricter value if PolicyValue is comparable
// - take override_policy's value if PolicyValue is not comparable
static DocumentPolicyFeatureState MergeFeatureState(
const DocumentPolicyFeatureState& base_policy,
const DocumentPolicyFeatureState& override_policy);
private:
friend class DocumentPolicyTest;
DocumentPolicy(const DocumentPolicyFeatureState& header_policy,
const FeatureEndpointMap& endpoint_map,
const DocumentPolicyFeatureState& defaults);
static std::unique_ptr<DocumentPolicy> CreateWithHeaderPolicy(
const DocumentPolicyFeatureState& header_policy,
const FeatureEndpointMap& endpoint_map,
const DocumentPolicyFeatureState& defaults);
void UpdateFeatureState(const DocumentPolicyFeatureState& feature_state);
// Internal feature state is represented as an array to avoid overhead
// of indexing into map like structure.
std::array<PolicyValue,
static_cast<size_t>(mojom::DocumentPolicyFeature::kMaxValue) + 1>
internal_feature_state_;
FeatureEndpointMap endpoint_map_;
DISALLOW_COPY_AND_ASSIGN(DocumentPolicy);
};
bool inline operator==(const DocumentPolicy::ParsedDocumentPolicy& lhs,
const DocumentPolicy::ParsedDocumentPolicy& rhs) {
return std::tie(lhs.feature_state, lhs.endpoint_map) ==
std::tie(rhs.feature_state, rhs.endpoint_map);
}
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_FEATURE_POLICY_DOCUMENT_POLICY_H_