239 lines
9.0 KiB
C++
239 lines
9.0 KiB
C++
// Copyright 2020 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef NET_BASE_SCHEMEFUL_SITE_H_
|
|
#define NET_BASE_SCHEMEFUL_SITE_H_
|
|
|
|
#include <ostream>
|
|
#include <string>
|
|
|
|
#include "base/gtest_prod_util.h"
|
|
#include "net/base/net_export.h"
|
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
|
#include "url/origin.h"
|
|
|
|
class GURL;
|
|
|
|
namespace blink {
|
|
class BlinkSchemefulSite;
|
|
class StorageKey;
|
|
} // namespace blink
|
|
|
|
namespace IPC {
|
|
template <class P>
|
|
struct ParamTraits;
|
|
} // namespace IPC
|
|
|
|
namespace network::mojom {
|
|
class SchemefulSiteDataView;
|
|
} // namespace network::mojom
|
|
|
|
namespace mojo {
|
|
template <typename DataViewType, typename T>
|
|
struct StructTraits;
|
|
} // namespace mojo
|
|
|
|
namespace net {
|
|
|
|
class SiteForCookies;
|
|
|
|
// Class which represents a scheme and etld+1 for an origin, as specified by
|
|
// https://html.spec.whatwg.org/multipage/origin.html#obtain-a-site.
|
|
//
|
|
// A SchemefulSite is obtained from an input origin by normalizing, such that:
|
|
// 1. Opaque origins have distinct SchemefulSites.
|
|
// 2. Origins whose schemes have network hosts have the same SchemefulSite iff
|
|
// they share a scheme, and share a hostname or registrable domain. Origins
|
|
// whose schemes have network hosts include http, https, ws, wss, file, etc.
|
|
// 3. Origins whose schemes do not have a network host have the same
|
|
// SchemefulSite iff they share a scheme and host.
|
|
// 4. Origins which differ only by port have the same SchemefulSite.
|
|
// 5. Websocket origins cannot have a SchemefulSite (they trigger a DCHECK).
|
|
//
|
|
// Note that blink::BlinkSchemefulSite mirrors this class and needs to be kept
|
|
// in sync with any data member changes.
|
|
class NET_EXPORT SchemefulSite {
|
|
public:
|
|
SchemefulSite() = default;
|
|
|
|
// The passed `origin` may not match the resulting internal representation in
|
|
// certain circumstances. See the comment, below, on the `site_as_origin_`
|
|
// member.
|
|
explicit SchemefulSite(const url::Origin& origin);
|
|
|
|
// Using the origin constructor is preferred as this is less efficient.
|
|
// Should only be used if the origin for a given GURL is not readily
|
|
// available.
|
|
explicit SchemefulSite(const GURL& url);
|
|
|
|
SchemefulSite(const SchemefulSite& other);
|
|
SchemefulSite(SchemefulSite&& other) noexcept;
|
|
|
|
SchemefulSite& operator=(const SchemefulSite& other);
|
|
SchemefulSite& operator=(SchemefulSite&& other) noexcept;
|
|
|
|
// Tries to construct an instance from a (potentially untrusted) value of the
|
|
// internal `site_as_origin_` that got received over an RPC.
|
|
//
|
|
// Returns whether successful or not. Doesn't touch |*out| if false is
|
|
// returned. This returning |true| does not mean that whoever sent the values
|
|
// did not lie, merely that they are well-formed.
|
|
static bool FromWire(const url::Origin& site_as_origin, SchemefulSite* out);
|
|
|
|
// Creates a SchemefulSite iff the passed-in origin has a registerable domain.
|
|
static absl::optional<SchemefulSite> CreateIfHasRegisterableDomain(
|
|
const url::Origin&);
|
|
|
|
// If the scheme is ws or wss, it is converted to http or https, respectively.
|
|
// Has no effect on SchemefulSites with any other schemes.
|
|
//
|
|
// See Step 1 of algorithm "establish a WebSocket connection" in
|
|
// https://fetch.spec.whatwg.org/#websocket-opening-handshake.
|
|
void ConvertWebSocketToHttp();
|
|
|
|
// Deserializes a string obtained from `Serialize()` to a `SchemefulSite`.
|
|
// Returns an opaque `SchemefulSite` if the value was invalid in any way.
|
|
static SchemefulSite Deserialize(const std::string& value);
|
|
|
|
// Returns a serialized version of `site_as_origin_`. If the underlying origin
|
|
// is invalid, returns an empty string. If serialization of opaque origins
|
|
// with their associated nonce is necessary, see `SerializeWithNonce()`.
|
|
std::string Serialize() const;
|
|
|
|
// Serializes `site_as_origin_` in cases when it has a 'file' scheme but
|
|
// we want to preserve the Origin's host.
|
|
// This was added to serialize cookie partition keys, which may contain
|
|
// file origins with a host.
|
|
std::string SerializeFileSiteWithHost() const;
|
|
|
|
std::string GetDebugString() const;
|
|
|
|
// Gets the underlying site as a GURL. If the internal Origin is opaque,
|
|
// returns an empty GURL.
|
|
GURL GetURL() const;
|
|
|
|
bool opaque() const { return site_as_origin_.opaque(); }
|
|
|
|
bool has_registrable_domain_or_host() const {
|
|
return !registrable_domain_or_host().empty();
|
|
}
|
|
|
|
// Testing only function which allows tests to access the underlying
|
|
// `site_as_origin_` in order to verify behavior.
|
|
const url::Origin& GetInternalOriginForTesting() const;
|
|
|
|
// Testing-only function which allows access to the private
|
|
// `registrable_domain_or_host` method.
|
|
std::string registrable_domain_or_host_for_testing() const {
|
|
return registrable_domain_or_host();
|
|
}
|
|
|
|
bool operator==(const SchemefulSite& other) const;
|
|
|
|
bool operator!=(const SchemefulSite& other) const;
|
|
|
|
bool operator<(const SchemefulSite& other) const;
|
|
|
|
private:
|
|
// IPC serialization code needs to access internal origin.
|
|
friend struct mojo::StructTraits<network::mojom::SchemefulSiteDataView,
|
|
SchemefulSite>;
|
|
friend struct IPC::ParamTraits<net::SchemefulSite>;
|
|
|
|
friend class blink::BlinkSchemefulSite;
|
|
|
|
// Create SiteForCookies from SchemefulSite needs to access internal origin,
|
|
// and SiteForCookies needs to access private method SchemelesslyEqual.
|
|
friend class SiteForCookies;
|
|
|
|
// Needed to serialize opaque and non-transient NetworkIsolationKeys, which
|
|
// use opaque origins.
|
|
friend class NetworkIsolationKey;
|
|
|
|
// Needed to serialize opaque and non-transient NetworkAnonymizationKeys,
|
|
// which use opaque origins.
|
|
friend class NetworkAnonymizationKey;
|
|
|
|
// Needed to create a bogus origin from a site.
|
|
// TODO(https://crbug.com/1148927): Give IsolationInfos empty origins instead,
|
|
// in this case, and unfriend IsolationInfo.
|
|
friend class IsolationInfo;
|
|
|
|
// Needed to create a bogus origin from a site.
|
|
friend class URLRequest;
|
|
|
|
// Needed because cookies do not account for scheme.
|
|
friend class CookieMonster;
|
|
|
|
// Needed for access to nonce for serialization.
|
|
friend class blink::StorageKey;
|
|
|
|
FRIEND_TEST_ALL_PREFIXES(SchemefulSiteTest, OpaqueSerialization);
|
|
FRIEND_TEST_ALL_PREFIXES(SchemefulSiteTest, InternalValue);
|
|
|
|
struct ObtainASiteResult {
|
|
url::Origin origin;
|
|
bool used_registerable_domain;
|
|
};
|
|
|
|
static ObtainASiteResult ObtainASite(const url::Origin&);
|
|
|
|
explicit SchemefulSite(ObtainASiteResult);
|
|
|
|
// Deserializes a string obtained from `SerializeWithNonce()` to a
|
|
// `SchemefulSite`. Returns nullopt if the value was invalid in any way.
|
|
static absl::optional<SchemefulSite> DeserializeWithNonce(
|
|
const std::string& value);
|
|
|
|
// Returns a serialized version of `site_as_origin_`. For an opaque
|
|
// `site_as_origin_`, this serializes with the nonce. See
|
|
// `url::origin::SerializeWithNonce()` for usage information.
|
|
absl::optional<std::string> SerializeWithNonce();
|
|
|
|
// Returns whether `this` and `other` share a host or registrable domain.
|
|
// Should NOT be used to check equality or equivalence. This is only used
|
|
// for legacy same-site cookie logic that does not check schemes. Private to
|
|
// restrict usage.
|
|
bool SchemelesslyEqual(const SchemefulSite& other) const;
|
|
|
|
// Returns the host of the underlying `origin`, which will usually be the
|
|
// registrable domain. This is private because if it were public, it would
|
|
// trivially allow circumvention of the "Schemeful"-ness of this class.
|
|
// However, the CookieMonster currently needs access to this, since it ignores
|
|
// the schemes of domains.
|
|
std::string registrable_domain_or_host() const {
|
|
return site_as_origin_.host();
|
|
}
|
|
|
|
// This should not be used casually, it's an opaque Origin or an scheme+eTLD+1
|
|
// packed into an Origin. If you extract this value SchemefulSite is not
|
|
// responsible for any unexpected friction you might encounter.
|
|
const url::Origin& internal_value() const { return site_as_origin_; }
|
|
|
|
// Origin which stores the result of running the steps documented at
|
|
// https://html.spec.whatwg.org/multipage/origin.html#obtain-a-site.
|
|
// This is not an arbitrary origin. It must either be an opaque origin, or a
|
|
// scheme + eTLD+1 + default port.
|
|
//
|
|
// The `origin` passed into the SchemefulSite(const url::Origin&) constructor
|
|
// might not match this internal representation used by this class to track
|
|
// the scheme and eTLD+1 representing a schemeful site. This may be the case
|
|
// if, e.g., the passed `origin` has an eTLD+1 that is not equal to its
|
|
// hostname, or if the port number is not the default port for its scheme.
|
|
//
|
|
// In general, this `site_as_origin_` used for the internal representation
|
|
// should NOT be used directly by SchemefulSite consumers.
|
|
url::Origin site_as_origin_;
|
|
};
|
|
|
|
// Provided to allow gtest to create more helpful error messages, instead of
|
|
// printing hex.
|
|
//
|
|
// Also used so that SchemefulSites can be the arguments of DCHECK_EQ.
|
|
NET_EXPORT std::ostream& operator<<(std::ostream& os, const SchemefulSite& ss);
|
|
|
|
} // namespace net
|
|
|
|
#endif // NET_BASE_SCHEMEFUL_SITE_H_
|