1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
// Copyright 2019 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_COOKIES_SITE_FOR_COOKIES_H_
#define NET_COOKIES_SITE_FOR_COOKIES_H_
#include <string>
#include "base/gtest_prod_util.h"
#include "net/base/net_export.h"
#include "net/base/schemeful_site.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace net {
// Represents which origins are to be considered same-site for a given
// context (e.g. frame). There may be none.
//
// The currently implemented policy ("schemeful") is that
// two valid URLs would be considered same-site if either:
// 1) They both have compatible schemes along with non-empty and equal
// registrable domains or hostnames/IPs. Two schemes are compatible if they
// are either equal, or are both in {http, ws}, or are both in {https, wss}.
// E.x. "https://example.com" and "wss://example.com"
// 2) They both have empty hostnames and exactly equal schemes. E.x. "file://"
// and "file://"
//
// With the SchemefulSameSite feature disabled the policy ("schemeless") is that
// two valid URLs would be considered the same site if either: 1) They both have
// non-empty and equal registrable domains or hostnames/IPs. E.x. "example.com"
// and "example.com" 2) They both have empty hostnames and equal schemes. E.x.
// "file://" and "file://"
//
//
// Invalid URLs are never same-site to anything.
class NET_EXPORT SiteForCookies {
public:
// Matches nothing.
SiteForCookies();
SiteForCookies(const SiteForCookies& other);
SiteForCookies(SiteForCookies&& other);
explicit SiteForCookies(const SchemefulSite& schemeful_site);
~SiteForCookies();
SiteForCookies& operator=(const SiteForCookies& other);
SiteForCookies& operator=(SiteForCookies&& other);
// Tries to construct an instance from (potentially untrusted) values of
// site() and schemefully_same() 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 SchemefulSite& site,
bool schemefully_same,
SiteForCookies* out);
// If the origin is opaque, returns SiteForCookies that matches nothing.
//
// If it's not opaque, returns one that matches URLs which are considered to
// be same-party as URLs from `origin`.
static SiteForCookies FromOrigin(const url::Origin& origin);
// Equivalent to FromOrigin(url::Origin::Create(url)).
static SiteForCookies FromUrl(const GURL& url);
// Returns a string with the values of the member variables.
// `schemefully_same` being false does not change the output.
std::string ToDebugString() const;
// Returns true if `url` should be considered first-party to the context
// `this` represents.
bool IsFirstParty(const GURL& url) const;
// Don't use this function unless you know what you're doing, if you're unsure
// you probably want IsFirstParty().
//
// If `compute_schemefully` is true this function will return true if `url`
// should be considered first-party to the context `this` represents when the
// compatibility of the schemes are taken into account.
//
// If `compute_schemefully` is false this function will return true if `url`
// should be considered first-party to the context `this` represents when the
// compatibility of the scheme are not taken into account. Note that schemes
// are still compared for exact equality if neither `this` nor `url` have a
// registered domain.
bool IsFirstPartyWithSchemefulMode(const GURL& url,
bool compute_schemefully) const;
// Returns true if `other.IsFirstParty()` is true for exactly the same URLs
// as `this->IsFirstParty` (potentially none). Two SFCs are also considered
// equivalent if neither ever returns true for `IsFirstParty()`. I.e., both
// are null.
bool IsEquivalent(const SiteForCookies& other) const;
// Compares a "candidate" SFC, `this`, with an origin (represented as a
// SchemefulSite) from the frame tree and revises `this` to be null as
// required.
//
// This method is used when a sub-frame needs to have its SiteForCookies
// computed, which is dependent on all of its ancestors' origins (`other`). If
// its or any of its ancestors' frame's origins are not first-party with the
// top-level origin then this frame's SFC should be null. Otherwise, if it and
// all its ancestors are first-party with the top-level frame, the frame's
// SFC is the same as the top-level.
//
// This computation gets a bit tricky when considering "Schemeful Same-Site"
// as we don't know ahead of time if `this` is going to be used for a
// schemeful or schemeless computation later down the line, so we need to
// be careful to not completely nullify the entire SFC just because an `other`
// isn't schemefully first-party. If the computation is schemelessly
// first-party but *not schemefully* first-party then only the
// `schemefully_same_` flag will be cleared (which informs other functions to
// treat `this` as null for schemeful purposes). If the computation is not
// schemelessly first-party then `this` will have an opaque `site_` which
// completely nullifies it.
//
// This function should be called on all ancestors up to the top-level frame
// unless it returns false in which case `this` has been completely nullified
// and the caller may stop early.
//
// (This function's return value is the same as IsEquivalent() when "Schemeful
// Same-Site" is disabled.)
bool CompareWithFrameTreeSiteAndRevise(const SchemefulSite& other);
// Converts an Origin into a SchemefulSite and then calls
//`CompareWithFrameTreeSiteAndRevise(SchemefulSite)`
//
// If possible, prefer `CompareWithFrameTreeSiteAndRevise(SchemefulSite)`
// for performance reasons.
bool CompareWithFrameTreeOriginAndRevise(const url::Origin& other);
// Returns a URL that's first party to this SiteForCookies (an empty URL if
// none) --- that is, it has the property that
// site_for_cookies.IsEquivalent(
// SiteForCookies::FromUrl(site_for_cookies.RepresentativeUrl()));
//
// The convention used here (empty for nothing) is equivalent to that
// used before SiteForCookies existed as a type; this method is mostly
// meant to help incrementally migrate towards the type. New code probably
// should not need this.
GURL RepresentativeUrl() const;
const SchemefulSite& site() const { return site_; }
// Guaranteed to be lowercase.
const std::string& scheme() const { return site_.site_as_origin_.scheme(); }
const std::string& registrable_domain() const {
return site_.site_as_origin_.host();
}
// Used for serialization/deserialization. This value is irrelevant if
// site().opaque() is true.
bool schemefully_same() const { return schemefully_same_; }
void SetSchemefullySameForTesting(bool schemefully_same) {
schemefully_same_ = schemefully_same;
}
// Returns true if this SiteForCookies matches nothing.
// If the SchemefulSameSite feature is enabled then !schemefully_same_ causes
// this function to return true.
bool IsNull() const;
// Allows SiteForCookies to be used as a key in STL (for example, a std::set
// or std::map).
NET_EXPORT friend bool operator<(const SiteForCookies& lhs,
const SiteForCookies& rhs);
private:
FRIEND_TEST_ALL_PREFIXES(SiteForCookiesTest, SameScheme);
FRIEND_TEST_ALL_PREFIXES(SiteForCookiesTest, SameSchemeOpaque);
bool IsSchemefullyFirstParty(const GURL& url) const;
bool IsSchemelesslyFirstParty(const GURL& url) const;
// Sets the schemefully_same_ flag to false if other`'s scheme is
// cross-scheme to `this`. Schemes are considered cross-scheme if they're not
// compatible. Two schemes are compatible if they are either equal, or are
// both in {http, ws}, or are both in {https, wss}.
void MarkIfCrossScheme(const SchemefulSite& other);
// Represents the scheme and registrable domain of the site. The scheme should
// not be a WebSocket scheme; instead, ws is normalized to http, and
// wss is normalized to https upon construction.
SchemefulSite site_;
// Used to indicate if the SiteForCookies would be the same if computed
// schemefully. A schemeful computation means to take the scheme as well as
// the registrable_domain into account when determining same-siteness.
// See the class-level comment for more details on schemeless vs schemeful.
//
// True means to treat `this` as-is while false means that `this` should be
// treated as if it matches nothing i.e. IsNull() returns true.
//
// This value is important in the case where the SiteForCookies is being used
// to assess the first-partyness of a sub-frame in a document.
//
// For a SiteForCookies with !site_.opaque() this value starts as true and
// will only go false via MarkIfCrossScheme(), otherwise this value is
// irrelevant (For tests this value can also be modified by
// SetSchemefullySameForTesting()).
bool schemefully_same_ = false;
};
} // namespace net
#endif // NET_COOKIES_SITE_FOR_COOKIES_H_
|