blob: 9e506b555012b3cd354e953e9fadb7faa3a46564 [file] [log] [blame]
// 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.
#ifndef NET_COOKIES_COOKIE_INCLUSION_STATUS_H_
#define NET_COOKIES_COOKIE_INCLUSION_STATUS_H_
#include <string>
#include <vector>
#include "net/base/net_export.h"
class GURL;
namespace net {
// This class represents if a cookie was included or excluded in a cookie get or
// set operation, and if excluded why. It holds a vector of reasons for
// exclusion, where cookie inclusion is represented by the absence of any
// exclusion reasons. Also marks whether a cookie should be warned about, e.g.
// for deprecation or intervention reasons.
class NET_EXPORT CookieInclusionStatus {
public:
// Types of reasons why a cookie might be excluded.
// If adding a ExclusionReason, please also update the GetDebugString()
// method.
enum ExclusionReason {
EXCLUDE_UNKNOWN_ERROR = 0,
EXCLUDE_HTTP_ONLY = 1,
EXCLUDE_SECURE_ONLY = 2,
EXCLUDE_DOMAIN_MISMATCH = 3,
EXCLUDE_NOT_ON_PATH = 4,
EXCLUDE_SAMESITE_STRICT = 5,
EXCLUDE_SAMESITE_LAX = 6,
// The following two are used for the SameSiteByDefaultCookies experiment,
// where if the SameSite attribute is not specified, it will be treated as
// SameSite=Lax by default.
EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX = 7,
// This is used if SameSite=None is specified, but the cookie is not
// Secure.
EXCLUDE_SAMESITE_NONE_INSECURE = 8,
EXCLUDE_USER_PREFERENCES = 9,
// Statuses specific to setting cookies
EXCLUDE_FAILURE_TO_STORE = 10,
EXCLUDE_NONCOOKIEABLE_SCHEME = 11,
EXCLUDE_OVERWRITE_SECURE = 12,
EXCLUDE_OVERWRITE_HTTP_ONLY = 13,
EXCLUDE_INVALID_DOMAIN = 14,
EXCLUDE_INVALID_PREFIX = 15,
// This should be kept last.
NUM_EXCLUSION_REASONS
};
// Reason to warn about a cookie. Any information contained in WarningReason
// of an included cookie may be passed to an untrusted renderer.
// If you add one, please update GetDebugString().
enum WarningReason {
// Of the following 3 SameSite warnings, there will be, at most, a single
// active one.
// Warn if a cookie with unspecified SameSite attribute is used in a
// cross-site context.
WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT = 0,
// Warn if a cookie with SameSite=None is not Secure.
WARN_SAMESITE_NONE_INSECURE = 1,
// Warn if a cookie with unspecified SameSite attribute is defaulted into
// Lax and is sent on a request with unsafe method, only because it is new
// enough to activate the Lax-allow-unsafe intervention.
WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE = 2,
// The following warnings indicate that an included cookie with an effective
// SameSite is experiencing a SameSiteCookieContext::|context| ->
// SameSiteCookieContext::|schemeful_context| downgrade that will prevent
// its access schemefully.
// This situation means that a cookie is accessible when the
// SchemefulSameSite feature is disabled but not when it's enabled,
// indicating changed behavior and potential breakage.
//
// For example, a Strict to Lax downgrade for an effective SameSite=Strict
// cookie:
// This cookie would be accessible in the Strict context as its SameSite
// value is Strict. However its context for schemeful same-site becomes Lax.
// A strict cookie cannot be accessed in a Lax context and therefore the
// behavior has changed.
// As a counterexample, a Strict to Lax downgrade for an effective
// SameSite=Lax cookie: A Lax cookie can be accessed in both Strict and Lax
// contexts so there is no behavior change (and we don't warn about it).
//
// The warnings are in the following format:
// WARN_{context}_{schemeful_context}_DOWNGRADE_{samesite_value}_SAMESITE
//
// Of the following 5 SameSite warnings, there will be, at most, a single
// active one.
// Strict to Lax downgrade for an effective SameSite=Strict cookie.
// This warning is only applicable for cookies being sent because a Strict
// cookie will be set in both Strict and Lax Contexts so the downgrade will
// not affect it.
WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE = 3,
// Strict to Cross-site downgrade for an effective SameSite=Strict cookie.
// This also applies to Strict to Lax Unsafe downgrades due to Lax Unsafe
// behaving like Cross-site.
WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE = 4,
// Strict to Cross-site downgrade for an effective SameSite=Lax cookie.
// This also applies to Strict to Lax Unsafe downgrades due to Lax Unsafe
// behaving like Cross-site.
WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE = 5,
// Lax to Cross-site downgrade for an effective SameSite=Strict cookie.
// This warning is only applicable for cookies being set because a Strict
// cookie will not be sent in a Lax context so the downgrade would not
// affect it.
WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE = 6,
// Lax to Cross-site downgrade for an effective SameSite=Lax cookie.
WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE = 7,
// This is applied to a cookie that may be part of a "double cookie" pair
// used for compatibility reasons. These pairs consist of one cookie that
// has "SameSite=None; Secure" and a duplicate cookie that leaves SameSite
// unspecified to maintain compatibility with browsers that do not support
// the "SameSite=None" attribute. This warning is applied to both
// members of the pair. See cookie_util::IsSameSiteCompatPair().
//
// If computing this for a cookie access attempt from a non-network context
// (i.e. script), this should not be applied if either member of the pair is
// HttpOnly, to avoid leaking information about the name and value of
// HttpOnly cookies to an untrusted renderer.
//
// This is only relevant if WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT is
// present on the same status or a status for a cookie accessed at the same
// time, so it may not be applied at other times (e.g. when the context is
// same-site).
WARN_SAMESITE_COMPAT_PAIR = 8,
// This should be kept last.
NUM_WARNING_REASONS
};
// These enums encode the context downgrade warnings + the secureness of the
// url sending/setting the cookie. They're used for metrics only. The format
// is {context}_{schemeful_context}_{samesite_value}_{securness}.
// NO_DOWNGRADE_{securness} indicates that a cookie didn't have a breaking
// context downgrade and was A) included B) excluded only due to insufficient
// same-site context. I.e. the cookie wasn't excluded due to other reasons
// such as third-party cookie blocking. Keep this in line with
// SameSiteCookieContextBreakingDowngradeWithSecureness in enums.xml.
enum ContextDowngradeMetricValues {
NO_DOWNGRADE_INSECURE = 0,
NO_DOWNGRADE_SECURE = 1,
STRICT_LAX_STRICT_INSECURE = 2,
STRICT_CROSS_STRICT_INSECURE = 3,
STRICT_CROSS_LAX_INSECURE = 4,
LAX_CROSS_STRICT_INSECURE = 5,
LAX_CROSS_LAX_INSECURE = 6,
STRICT_LAX_STRICT_SECURE = 7,
STRICT_CROSS_STRICT_SECURE = 8,
STRICT_CROSS_LAX_SECURE = 9,
LAX_CROSS_STRICT_SECURE = 10,
LAX_CROSS_LAX_SECURE = 11,
// Keep last.
kMaxValue = LAX_CROSS_LAX_SECURE
};
// Makes a status that says include and should not warn.
CookieInclusionStatus();
// Make a status that contains the given exclusion reason.
explicit CookieInclusionStatus(ExclusionReason reason);
// Makes a status that contains the given exclusion reason and warning.
CookieInclusionStatus(ExclusionReason reason, WarningReason warning);
bool operator==(const CookieInclusionStatus& other) const;
bool operator!=(const CookieInclusionStatus& other) const;
// Whether the status is to include the cookie, and has no other reasons for
// exclusion.
bool IsInclude() const;
// Whether the given reason for exclusion is present.
bool HasExclusionReason(ExclusionReason status_type) const;
// Whether the given reason for exclusion is present, and is the ONLY reason
// for exclusion.
bool HasOnlyExclusionReason(ExclusionReason status_type) const;
// Add an exclusion reason.
void AddExclusionReason(ExclusionReason status_type);
// Remove an exclusion reason.
void RemoveExclusionReason(ExclusionReason reason);
// If the cookie would have been excluded for reasons other than
// SAMESITE_UNSPECIFIED_TREATED_AS_LAX or SAMESITE_NONE_INSECURE, don't bother
// warning about it (clear the warning).
void MaybeClearSameSiteWarning();
// Whether to record the breaking downgrade metrics if the cookie is included
// or if it's only excluded because of insufficient same-site context.
bool ShouldRecordDowngradeMetrics() const;
// Whether the cookie should be warned about.
bool ShouldWarn() const;
// Whether the given reason for warning is present.
bool HasWarningReason(WarningReason reason) const;
// Whether a schemeful downgrade warning is present.
// A schemeful downgrade means that an included cookie with an effective
// SameSite is experiencing a SameSiteCookieContext::|context| ->
// SameSiteCookieContext::|schemeful_context| downgrade that will prevent its
// access schemefully. If the function returns true and |reason| is valid then
// |reason| will contain which warning was found.
bool HasDowngradeWarning(
CookieInclusionStatus::WarningReason* reason = nullptr) const;
// Add an warning reason.
void AddWarningReason(WarningReason reason);
// Remove an warning reason.
void RemoveWarningReason(WarningReason reason);
// Used for serialization/deserialization.
uint32_t exclusion_reasons() const { return exclusion_reasons_; }
void set_exclusion_reasons(uint32_t exclusion_reasons) {
exclusion_reasons_ = exclusion_reasons;
}
uint32_t warning_reasons() const { return warning_reasons_; }
void set_warning_reasons(uint32_t warning_reasons) {
warning_reasons_ = warning_reasons;
}
ContextDowngradeMetricValues GetBreakingDowngradeMetricsEnumValue(
const GURL& url) const;
// Get exclusion reason(s) and warning in string format.
std::string GetDebugString() const;
// Checks that the underlying bit vector representation doesn't contain any
// extraneous bits that are not mapped to any enum values. Does not check
// for reasons which semantically cannot coexist.
bool IsValid() const;
// Checks whether the exclusion reasons are exactly the set of exclusion
// reasons in the vector. (Ignores warnings.)
bool HasExactlyExclusionReasonsForTesting(
std::vector<ExclusionReason> reasons) const;
// Checks whether the warning reasons are exactly the set of warning
// reasons in the vector. (Ignores exclusions.)
bool HasExactlyWarningReasonsForTesting(
std::vector<WarningReason> reasons) const;
// Makes a status that contains the given exclusion reasons and warning.
static CookieInclusionStatus MakeFromReasonsForTesting(
std::vector<ExclusionReason> reasons,
std::vector<WarningReason> warnings = std::vector<WarningReason>());
private:
// A bit vector of the applicable exclusion reasons.
uint32_t exclusion_reasons_ = 0u;
// A bit vector of the applicable warning reasons.
uint32_t warning_reasons_ = 0u;
};
NET_EXPORT inline std::ostream& operator<<(std::ostream& os,
const CookieInclusionStatus status) {
return os << status.GetDebugString();
}
} // namespace net
#endif // NET_COOKIES_COOKIE_INCLUSION_STATUS_H_