Avi Drissman | 3e1a26c | 2022-09-15 20:26:03 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef URL_ORIGIN_H_ |
| 6 | #define URL_ORIGIN_H_ |
| 7 | |
avi | c0c6031 | 2015-12-21 21:03:50 | [diff] [blame] | 8 | #include <stdint.h> |
| 9 | |
Robert Ogden | dd74d73 | 2020-03-12 17:33:19 | [diff] [blame] | 10 | #include <memory> |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 11 | #include <string> |
David Benjamin | bf75caf | 2023-09-29 04:39:59 | [diff] [blame] | 12 | #include <string_view> |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 13 | |
Arthur Sonzogni | 75165b8 | 2023-11-07 18:25:47 | [diff] [blame] | 14 | #include <optional> |
Staphany Park | 6fd74a2 | 2018-12-04 21:15:41 | [diff] [blame] | 15 | #include "base/component_export.h" |
Lukasz Anforowicz | 3d58b939 | 2018-01-05 20:56:22 | [diff] [blame] | 16 | #include "base/debug/alias.h" |
Lukasz Anforowicz | 731c39c | 2020-02-07 23:35:58 | [diff] [blame] | 17 | #include "base/debug/crash_logging.h" |
Ari Chivukula | 2e5fd08 | 2023-01-25 05:34:59 | [diff] [blame] | 18 | #include "base/gtest_prod_util.h" |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 19 | #include "base/strings/string_util.h" |
Stefano Duo | d54f6988 | 2023-04-03 15:45:54 | [diff] [blame] | 20 | #include "base/trace_event/base_tracing_forward.h" |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 21 | #include "base/unguessable_token.h" |
Rouslan Solomakhin | 63cdb148 | 2019-09-30 21:53:14 | [diff] [blame] | 22 | #include "build/build_config.h" |
David Sanders | f0ac4c9 | 2022-04-20 03:09:00 | [diff] [blame] | 23 | #include "build/buildflag.h" |
Andrew Grieve | 5cec639 | 2023-09-06 14:46:01 | [diff] [blame] | 24 | #include "build/robolectric_buildflags.h" |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 25 | #include "url/scheme_host_port.h" |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 26 | |
Andrew Grieve | 5cec639 | 2023-09-06 14:46:01 | [diff] [blame] | 27 | #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_ROBOLECTRIC) |
| 28 | #include "base/android/jni_android.h" |
| 29 | #endif |
Rouslan Solomakhin | 63cdb148 | 2019-09-30 21:53:14 | [diff] [blame] | 30 | |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 31 | class GURL; |
| 32 | |
Nasko Oskov | 99445acd | 2018-10-10 16:46:00 | [diff] [blame] | 33 | namespace blink { |
| 34 | class SecurityOrigin; |
Daniel Cheng | 8cc87021 | 2022-02-04 20:52:27 | [diff] [blame] | 35 | class SecurityOriginTest; |
Ari Chivukula | 2e5fd08 | 2023-01-25 05:34:59 | [diff] [blame] | 36 | class StorageKey; |
| 37 | class StorageKeyTest; |
Nasko Oskov | 99445acd | 2018-10-10 16:46:00 | [diff] [blame] | 38 | } // namespace blink |
| 39 | |
Sharon Yang | b670da6b | 2023-11-21 02:01:20 | [diff] [blame] | 40 | namespace content { |
| 41 | class SiteInfo; |
| 42 | } // namespace content |
| 43 | |
Stefano Duo | e4f33c5 | 2022-12-07 13:44:35 | [diff] [blame] | 44 | namespace IPC { |
| 45 | template <class P> |
| 46 | struct ParamTraits; |
| 47 | } // namespace IPC |
| 48 | |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 49 | namespace ipc_fuzzer { |
| 50 | template <class T> |
| 51 | struct FuzzTraits; |
| 52 | } // namespace ipc_fuzzer |
| 53 | |
Nasko Oskov | d9e41d5 | 2018-09-27 23:12:42 | [diff] [blame] | 54 | namespace mojo { |
| 55 | template <typename DataViewType, typename T> |
| 56 | struct StructTraits; |
Nasko Oskov | 99445acd | 2018-10-10 16:46:00 | [diff] [blame] | 57 | struct UrlOriginAdapter; |
Nasko Oskov | d9e41d5 | 2018-09-27 23:12:42 | [diff] [blame] | 58 | } // namespace mojo |
| 59 | |
Robert Ogden | dd74d73 | 2020-03-12 17:33:19 | [diff] [blame] | 60 | namespace net { |
John Delaney | 513e53f | 2020-10-29 20:16:04 | [diff] [blame] | 61 | class SchemefulSite; |
Robert Ogden | dd74d73 | 2020-03-12 17:33:19 | [diff] [blame] | 62 | } // namespace net |
| 63 | |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 64 | namespace url { |
| 65 | |
Nasko Oskov | d9e41d5 | 2018-09-27 23:12:42 | [diff] [blame] | 66 | namespace mojom { |
| 67 | class OriginDataView; |
| 68 | } // namespace mojom |
| 69 | |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 70 | // Per https://html.spec.whatwg.org/multipage/origin.html#origin, an origin is |
| 71 | // either: |
| 72 | // - a tuple origin of (scheme, host, port) as described in RFC 6454. |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 73 | // - an opaque origin with an internal value, and a memory of the tuple origin |
| 74 | // from which it was derived. |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 75 | // |
| 76 | // TL;DR: If you need to make a security-relevant decision, use 'url::Origin'. |
| 77 | // If you only need to extract the bits of a URL which are relevant for a |
| 78 | // network connection, use 'url::SchemeHostPort'. |
| 79 | // |
| 80 | // STL;SDR: If you aren't making actual network connections, use 'url::Origin'. |
| 81 | // |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 82 | // This class ought to be used when code needs to determine if two resources |
| 83 | // are "same-origin", and when a canonical serialization of an origin is |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 84 | // required. Note that the canonical serialization of an origin *must not* be |
| 85 | // used to determine if two resources are same-origin. |
| 86 | // |
| 87 | // A tuple origin, like 'SchemeHostPort', is composed of a tuple of (scheme, |
| 88 | // host, port), but contains a number of additional concepts which make it |
| 89 | // appropriate for use as a security boundary and access control mechanism |
| 90 | // between contexts. Two tuple origins are same-origin if the tuples are equal. |
| 91 | // A tuple origin may also be re-created from its serialization. |
| 92 | // |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 93 | // An opaque origin has an internal globally unique identifier. When creating a |
| 94 | // new opaque origin from a URL, a fresh globally unique identifier is |
| 95 | // generated. However, if an opaque origin is copied or moved, the internal |
| 96 | // globally unique identifier is preserved. Two opaque origins are same-origin |
| 97 | // iff the globally unique identifiers match. Unlike tuple origins, an opaque |
| 98 | // origin cannot be re-created from its serialization, which is always the |
| 99 | // string "null". |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 100 | // |
| 101 | // IMPORTANT: Since opaque origins always serialize as the string "null", it is |
| 102 | // *never* safe to use the serialization for security checks! |
| 103 | // |
| 104 | // A tuple origin and an opaque origin are never same-origin. |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 105 | // |
| 106 | // There are a few subtleties to note: |
| 107 | // |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 108 | // * A default constructed Origin is opaque, with no precursor origin. |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 109 | // |
| 110 | // * Invalid and non-standard GURLs are parsed as opaque origins. This includes |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 111 | // non-hierarchical URLs like 'data:text/html,...' and 'javascript:alert(1)'. |
| 112 | // |
| 113 | // * GURLs with schemes of 'filesystem' or 'blob' parse the origin out of the |
| 114 | // internals of the URL. That is, 'filesystem:https://example.com/temporary/f' |
| 115 | // is parsed as ('https', 'example.com', 443). |
| 116 | // |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 117 | // * GURLs with a 'file' scheme are tricky. They are parsed as ('file', '', 0), |
| 118 | // but their behavior may differ from embedder to embedder. |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 119 | // TODO(dcheng): This behavior is not consistent with Blink's notion of file |
| 120 | // URLs, which always creates an opaque origin. |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 121 | // |
| 122 | // * The host component of an IPv6 address includes brackets, just like the URL |
| 123 | // representation. |
| 124 | // |
Lukasz Anforowicz | cfe9b2f6 | 2022-05-25 15:47:16 | [diff] [blame] | 125 | // * Constructing origins from GURLs (or from SchemeHostPort) is typically a red |
| 126 | // flag (this is true for `url::Origin::Create` but also to some extent for |
| 127 | // `url::Origin::Resolve`). See docs/security/origin-vs-url.md for more. |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 128 | // |
| 129 | // * To answer the question "Are |this| and |that| "same-origin" with each |
| 130 | // other?", use |Origin::IsSameOriginWith|: |
| 131 | // |
| 132 | // if (this.IsSameOriginWith(that)) { |
| 133 | // // Amazingness goes here. |
| 134 | // } |
Staphany Park | 6fd74a2 | 2018-12-04 21:15:41 | [diff] [blame] | 135 | class COMPONENT_EXPORT(URL) Origin { |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 136 | public: |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 137 | // Creates an opaque Origin with a nonce that is different from all previously |
| 138 | // existing origins. |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 139 | Origin(); |
| 140 | |
Lukasz Anforowicz | cfe9b2f6 | 2022-05-25 15:47:16 | [diff] [blame] | 141 | // WARNING: Converting an URL into an Origin is usually a red flag. See |
| 142 | // //docs/security/origin-vs-url.md for more details. Some discussion about |
| 143 | // deprecating the Create method can be found in https://crbug.com/1270878. |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 144 | // |
Lukasz Anforowicz | cfe9b2f6 | 2022-05-25 15:47:16 | [diff] [blame] | 145 | // Creates an Origin from `url`, as described at |
| 146 | // https://url.spec.whatwg.org/#origin, with the following additions: |
| 147 | // 1. If `url` is invalid or non-standard, an opaque Origin is constructed. |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 148 | // 2. 'filesystem' URLs behave as 'blob' URLs (that is, the origin is parsed |
| 149 | // out of everything in the URL which follows the scheme). |
| 150 | // 3. 'file' URLs all parse as ("file", "", 0). |
Lukasz Anforowicz | fd7834ec | 2020-03-04 02:11:57 | [diff] [blame] | 151 | // |
Lukasz Anforowicz | cfe9b2f6 | 2022-05-25 15:47:16 | [diff] [blame] | 152 | // WARNING: `url::Origin::Create(url)` can give unexpected results if: |
| 153 | // 1) `url` is "about:blank", or "about:srcdoc" (returning unique, opaque |
| 154 | // origin rather than the real origin of the frame) |
| 155 | // 2) `url` comes from a sandboxed frame (potentially returning a non-opaque |
| 156 | // origin, when an opaque one is needed; see also |
| 157 | // https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/) |
| 158 | // 3) Wrong `url` is used - e.g. in some navigations `base_url_for_data_url` |
| 159 | // might need to be used instead of relying on |
| 160 | // `content::NavigationHandle::GetURL`. |
| 161 | // |
| 162 | // WARNING: The returned Origin may have a different scheme and host from |
| 163 | // `url` (e.g. in case of blob URLs - see OriginTest.ConstructFromGURL). |
| 164 | // |
| 165 | // WARNING: data: URLs will be correctly be translated into opaque origins, |
| 166 | // but the precursor origin will be lost (unlike with `url::Origin::Resolve`). |
Daniel Cheng | 88186bd5 | 2017-10-20 08:14:46 | [diff] [blame] | 167 | static Origin Create(const GURL& url); |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 168 | |
Lukasz Anforowicz | cfe9b2f6 | 2022-05-25 15:47:16 | [diff] [blame] | 169 | // Creates an Origin for the resource `url` as if it were requested |
| 170 | // from the context of `base_origin`. If `url` is standard |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 171 | // (in the sense that it embeds a complete origin, like http/https), |
| 172 | // this returns the same value as would Create(). |
| 173 | // |
Lukasz Anforowicz | cfe9b2f6 | 2022-05-25 15:47:16 | [diff] [blame] | 174 | // If `url` is "about:blank" or "about:srcdoc", this returns a copy of |
| 175 | // `base_origin`. |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 176 | // |
Lukasz Anforowicz | cfe9b2f6 | 2022-05-25 15:47:16 | [diff] [blame] | 177 | // Otherwise, returns a new opaque origin derived from `base_origin`. |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 178 | // In this case, the resulting opaque origin will inherit the tuple |
Lukasz Anforowicz | cfe9b2f6 | 2022-05-25 15:47:16 | [diff] [blame] | 179 | // (or precursor tuple) of `base_origin`, but will not be same origin |
| 180 | // with `base_origin`, even if `base_origin` is already opaque. |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 181 | static Origin Resolve(const GURL& url, const Origin& base_origin); |
| 182 | |
John Mellor | ef62bce | 2017-10-04 11:25:33 | [diff] [blame] | 183 | // Copyable and movable. |
Daniel Cheng | 6ae11ad7 | 2017-10-17 20:42:33 | [diff] [blame] | 184 | Origin(const Origin&); |
| 185 | Origin& operator=(const Origin&); |
Victor Costan | 7c9d0b148 | 2020-07-07 14:13:03 | [diff] [blame] | 186 | Origin(Origin&&) noexcept; |
| 187 | Origin& operator=(Origin&&) noexcept; |
John Mellor | ef62bce | 2017-10-04 11:25:33 | [diff] [blame] | 188 | |
Takashi Toyoshima | 5641d755 | 2018-02-09 08:57:52 | [diff] [blame] | 189 | // Creates an Origin from a |scheme|, |host|, and |port|. All the parameters |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 190 | // must be valid and canonicalized. Returns nullopt if any parameter is not |
| 191 | // canonical, or if all the parameters are empty. |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 192 | // |
| 193 | // This constructor should be used in order to pass 'Origin' objects back and |
| 194 | // forth over IPC (as transitioning through GURL would risk potentially |
| 195 | // dangerous recanonicalization); other potential callers should prefer the |
| 196 | // 'GURL'-based constructor. |
Arthur Sonzogni | 75165b8 | 2023-11-07 18:25:47 | [diff] [blame] | 197 | static std::optional<Origin> UnsafelyCreateTupleOriginWithoutNormalization( |
David Benjamin | bf75caf | 2023-09-29 04:39:59 | [diff] [blame] | 198 | std::string_view scheme, |
| 199 | std::string_view host, |
Takashi Toyoshima | 5641d755 | 2018-02-09 08:57:52 | [diff] [blame] | 200 | uint16_t port); |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 201 | |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 202 | // Creates an origin without sanity checking that the host is canonicalized. |
| 203 | // This should only be used when converting between already normalized types, |
csharrison | f07ac3c | 2016-12-13 04:15:02 | [diff] [blame] | 204 | // and should NOT be used for IPC. Method takes std::strings for use with move |
| 205 | // operators to avoid copies. |
Takashi Toyoshima | 5641d755 | 2018-02-09 08:57:52 | [diff] [blame] | 206 | static Origin CreateFromNormalizedTuple(std::string scheme, |
| 207 | std::string host, |
| 208 | uint16_t port); |
jww | 908428c | 2016-10-26 21:51:46 | [diff] [blame] | 209 | |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 210 | ~Origin(); |
| 211 | |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 212 | // For opaque origins, these return ("", "", 0). |
| 213 | const std::string& scheme() const { |
Chris Palmer | ab5e5b5 | 2018-09-28 19:19:30 | [diff] [blame] | 214 | return !opaque() ? tuple_.scheme() : base::EmptyString(); |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 215 | } |
| 216 | const std::string& host() const { |
Chris Palmer | ab5e5b5 | 2018-09-28 19:19:30 | [diff] [blame] | 217 | return !opaque() ? tuple_.host() : base::EmptyString(); |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 218 | } |
Chris Palmer | ab5e5b5 | 2018-09-28 19:19:30 | [diff] [blame] | 219 | uint16_t port() const { return !opaque() ? tuple_.port() : 0; } |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 220 | |
Chris Palmer | ab5e5b5 | 2018-09-28 19:19:30 | [diff] [blame] | 221 | bool opaque() const { return nonce_.has_value(); } |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 222 | |
| 223 | // An ASCII serialization of the Origin as per Section 6.2 of RFC 6454, with |
| 224 | // the addition that all Origins with a 'file' scheme serialize to "file://". |
| 225 | std::string Serialize() const; |
| 226 | |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 227 | // Two non-opaque Origins are "same-origin" if their schemes, hosts, and ports |
| 228 | // are exact matches. Two opaque origins are same-origin only if their |
| 229 | // internal nonce values match. A non-opaque origin is never same-origin with |
| 230 | // an opaque origin. |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 231 | bool IsSameOriginWith(const Origin& other) const; |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 232 | bool operator==(const Origin& other) const { return IsSameOriginWith(other); } |
| 233 | bool operator!=(const Origin& other) const { |
| 234 | return !IsSameOriginWith(other); |
| 235 | } |
| 236 | |
Lukasz Anforowicz | d00c1ed | 2022-01-13 05:25:10 | [diff] [blame] | 237 | // Non-opaque origin is "same-origin" with `url` if their schemes, hosts, and |
Lukasz Anforowicz | cfe9b2f6 | 2022-05-25 15:47:16 | [diff] [blame] | 238 | // ports are exact matches. Opaque origin is never "same-origin" with any |
Lukasz Anforowicz | d00c1ed | 2022-01-13 05:25:10 | [diff] [blame] | 239 | // `url`. about:blank, about:srcdoc, and invalid GURLs are never |
Lukasz Anforowicz | cfe9b2f6 | 2022-05-25 15:47:16 | [diff] [blame] | 240 | // "same-origin" with any origin. This method is a shorthand for |
Lukasz Anforowicz | d00c1ed | 2022-01-13 05:25:10 | [diff] [blame] | 241 | // `origin.IsSameOriginWith(url::Origin::Create(url))`. |
| 242 | // |
| 243 | // See also CanBeDerivedFrom. |
| 244 | bool IsSameOriginWith(const GURL& url) const; |
| 245 | |
Nasko Oskov | 97e305f | 2019-01-05 03:52:10 | [diff] [blame] | 246 | // This method returns true for any |url| which if navigated to could result |
| 247 | // in an origin compatible with |this|. |
| 248 | bool CanBeDerivedFrom(const GURL& url) const; |
| 249 | |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 250 | // Get the scheme, host, and port from which this origin derives. For |
| 251 | // a tuple Origin, this gives the same values as calling scheme(), host() |
| 252 | // and port(). For an opaque Origin that was created by calling |
| 253 | // Origin::DeriveNewOpaqueOrigin() on a precursor or Origin::Resolve(), |
| 254 | // this returns the tuple inherited from the precursor. |
| 255 | // |
| 256 | // If this Origin is opaque and was created via the default constructor or |
| 257 | // Origin::Create(), the precursor origin is unknown. |
| 258 | // |
| 259 | // Use with great caution: opaque origins should generally not inherit |
| 260 | // privileges from the origins they derive from. However, in some cases |
| 261 | // (such as restrictions on process placement, or determining the http lock |
| 262 | // icon) this information may be relevant to ensure that entering an |
| 263 | // opaque origin does not grant privileges initially denied to the original |
| 264 | // non-opaque origin. |
| 265 | // |
| 266 | // This method has a deliberately obnoxious name to prompt caution in its use. |
| 267 | const SchemeHostPort& GetTupleOrPrecursorTupleIfOpaque() const { |
| 268 | return tuple_; |
mek | 0126c13 | 2016-02-17 23:50:59 | [diff] [blame] | 269 | } |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 270 | |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 271 | // Efficiently returns what GURL(Serialize()) would without re-parsing the |
| 272 | // URL. This can be used for the (rare) times a GURL representation is needed |
| 273 | // for an Origin. |
| 274 | // Note: The returned URL will not necessarily be serialized to the same value |
| 275 | // as the Origin would. The GURL will have an added "/" path for Origins with |
| 276 | // valid SchemeHostPorts and file Origins. |
Charles Harrison | c5f8c91b | 2017-08-22 18:08:24 | [diff] [blame] | 277 | // |
| 278 | // Try not to use this method under normal circumstances, as it loses type |
| 279 | // information. Downstream consumers can mistake the returned GURL with a full |
| 280 | // URL (e.g. with a path component). |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 281 | GURL GetURL() const; |
| 282 | |
Chris Palmer | ab5e5b5 | 2018-09-28 19:19:30 | [diff] [blame] | 283 | // Same as GURL::DomainIs. If |this| origin is opaque, then returns false. |
David Benjamin | bf75caf | 2023-09-29 04:39:59 | [diff] [blame] | 284 | bool DomainIs(std::string_view canonical_domain) const; |
pkalinnikov | 054f403 | 2016-08-31 10:54:17 | [diff] [blame] | 285 | |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 286 | // Allows Origin to be used as a key in STL (for example, a std::set or |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 287 | // std::map). |
| 288 | bool operator<(const Origin& other) const; |
| 289 | |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 290 | // Creates a new opaque origin that is guaranteed to be cross-origin to all |
| 291 | // currently existing origins. An origin created by this method retains its |
| 292 | // identity across copies. Copies are guaranteed to be same-origin to each |
| 293 | // other, e.g. |
| 294 | // |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 295 | // url::Origin page = Origin::Create(GURL("http://example.com")) |
| 296 | // url::Origin a = page.DeriveNewOpaqueOrigin(); |
| 297 | // url::Origin b = page.DeriveNewOpaqueOrigin(); |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 298 | // url::Origin c = a; |
| 299 | // url::Origin d = b; |
| 300 | // |
| 301 | // |a| and |c| are same-origin, since |c| was copied from |a|. |b| and |d| are |
| 302 | // same-origin as well, since |d| was copied from |b|. All other combinations |
| 303 | // of origins are considered cross-origin, e.g. |a| is cross-origin to |b| and |
| 304 | // |d|, |b| is cross-origin to |a| and |c|, |c| is cross-origin to |b| and |
| 305 | // |d|, and |d| is cross-origin to |a| and |c|. |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 306 | Origin DeriveNewOpaqueOrigin() const; |
| 307 | |
Sharon Yang | b670da6b | 2023-11-21 02:01:20 | [diff] [blame] | 308 | // Returns the nonce associated with the origin, if it is opaque, or nullptr |
| 309 | // otherwise. This is only for use in tests. |
| 310 | const base::UnguessableToken* GetNonceForTesting() const; |
| 311 | |
Nasko Oskov | 1ed4e8f | 2019-02-13 01:39:19 | [diff] [blame] | 312 | // Creates a string representation of the object that can be used for logging |
| 313 | // and debugging. It serializes the internal state, such as the nonce value |
| 314 | // and precursor information. |
Lukasz Anforowicz | 949141f | 2020-07-08 19:45:34 | [diff] [blame] | 315 | std::string GetDebugString(bool include_nonce = true) const; |
Nasko Oskov | 1ed4e8f | 2019-02-13 01:39:19 | [diff] [blame] | 316 | |
Andrew Grieve | 5cec639 | 2023-09-06 14:46:01 | [diff] [blame] | 317 | #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_ROBOLECTRIC) |
| 318 | base::android::ScopedJavaLocalRef<jobject> ToJavaObject() const; |
Rouslan Solomakhin | 63cdb148 | 2019-09-30 21:53:14 | [diff] [blame] | 319 | static Origin FromJavaObject( |
| 320 | const base::android::JavaRef<jobject>& java_origin); |
Michael Thiessen | 6f03acb | 2022-11-01 03:19:47 | [diff] [blame] | 321 | static jlong CreateNative(JNIEnv* env, |
| 322 | const base::android::JavaRef<jstring>& java_scheme, |
| 323 | const base::android::JavaRef<jstring>& java_host, |
| 324 | uint16_t port, |
| 325 | bool is_opaque, |
| 326 | uint64_t tokenHighBits, |
| 327 | uint64_t tokenLowBits); |
Xiaohan Wang | 3b01513a | 2022-01-20 03:22:55 | [diff] [blame] | 328 | #endif // BUILDFLAG(IS_ANDROID) |
Rouslan Solomakhin | 63cdb148 | 2019-09-30 21:53:14 | [diff] [blame] | 329 | |
Alexander Timin | 1b6b272 | 2021-04-21 01:34:27 | [diff] [blame] | 330 | void WriteIntoTrace(perfetto::TracedValue context) const; |
Alexander Timin | e4fc848 | 2021-02-10 15:27:46 | [diff] [blame] | 331 | |
Xiaochen Zhou | 4350e46 | 2023-08-21 15:06:12 | [diff] [blame] | 332 | // Estimates dynamic memory usage. |
| 333 | // See base/trace_event/memory_usage_estimator.h for more info. |
| 334 | size_t EstimateMemoryUsage() const; |
| 335 | |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 336 | private: |
Andrew Grieve | 5cec639 | 2023-09-06 14:46:01 | [diff] [blame] | 337 | #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_ROBOLECTRIC) |
| 338 | friend Origin CreateOpaqueOriginForAndroid( |
| 339 | const std::string& scheme, |
| 340 | const std::string& host, |
| 341 | uint16_t port, |
| 342 | const base::UnguessableToken& nonce_token); |
| 343 | #endif |
Nasko Oskov | 99445acd | 2018-10-10 16:46:00 | [diff] [blame] | 344 | friend class blink::SecurityOrigin; |
Daniel Cheng | 8cc87021 | 2022-02-04 20:52:27 | [diff] [blame] | 345 | friend class blink::SecurityOriginTest; |
Ari Chivukula | 2e5fd08 | 2023-01-25 05:34:59 | [diff] [blame] | 346 | friend class blink::StorageKey; |
Sharon Yang | b670da6b | 2023-11-21 02:01:20 | [diff] [blame] | 347 | // SiteInfo needs the nonce to compute the site URL for some opaque origins, |
| 348 | // like data: URLs. |
| 349 | friend class content::SiteInfo; |
John Delaney | 513e53f | 2020-10-29 20:16:04 | [diff] [blame] | 350 | // SchemefulSite needs access to the serialization/deserialization logic which |
| 351 | // includes the nonce. |
| 352 | friend class net::SchemefulSite; |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 353 | friend class OriginTest; |
Nasko Oskov | 99445acd | 2018-10-10 16:46:00 | [diff] [blame] | 354 | friend struct mojo::UrlOriginAdapter; |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 355 | friend struct ipc_fuzzer::FuzzTraits<Origin>; |
Nasko Oskov | d9e41d5 | 2018-09-27 23:12:42 | [diff] [blame] | 356 | friend struct mojo::StructTraits<url::mojom::OriginDataView, url::Origin>; |
Nasko Oskov | 99445acd | 2018-10-10 16:46:00 | [diff] [blame] | 357 | friend IPC::ParamTraits<url::Origin>; |
Staphany Park | 6fd74a2 | 2018-12-04 21:15:41 | [diff] [blame] | 358 | friend COMPONENT_EXPORT(URL) std::ostream& operator<<(std::ostream& out, |
| 359 | const Origin& origin); |
Ari Chivukula | 2e5fd08 | 2023-01-25 05:34:59 | [diff] [blame] | 360 | friend class blink::StorageKeyTest; |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 361 | |
| 362 | // Origin::Nonce is a wrapper around base::UnguessableToken that generates |
| 363 | // the random value only when the value is first accessed. The lazy generation |
| 364 | // allows Origin to be default-constructed quickly, without spending time |
| 365 | // in random number generation. |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 366 | // |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 367 | // TODO(nick): Should this optimization move into UnguessableToken, once it no |
| 368 | // longer treats the Null case specially? |
Staphany Park | 6fd74a2 | 2018-12-04 21:15:41 | [diff] [blame] | 369 | class COMPONENT_EXPORT(URL) Nonce { |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 370 | public: |
| 371 | // Creates a nonce to hold a newly-generated UnguessableToken. The actual |
| 372 | // token value will be generated lazily. |
| 373 | Nonce(); |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 374 | |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 375 | // Creates a nonce to hold an already-generated UnguessableToken value. This |
| 376 | // constructor should only be used for IPC serialization and testing -- |
| 377 | // regular code should never need to touch the UnguessableTokens directly, |
| 378 | // and the default constructor is faster. |
| 379 | explicit Nonce(const base::UnguessableToken& token); |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 380 | |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 381 | // Accessor, which lazily initializes the underlying |token_| member. |
| 382 | const base::UnguessableToken& token() const; |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 383 | |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 384 | // Do not use in cases where lazy initialization is expected! This |
| 385 | // accessor does not initialize the |token_| member. |
| 386 | const base::UnguessableToken& raw_token() const; |
| 387 | |
| 388 | // Copyable and movable. Copying a Nonce triggers lazy-initialization, |
| 389 | // moving it does not. |
| 390 | Nonce(const Nonce&); |
| 391 | Nonce& operator=(const Nonce&); |
Victor Costan | 7c9d0b148 | 2020-07-07 14:13:03 | [diff] [blame] | 392 | Nonce(Nonce&&) noexcept; |
| 393 | Nonce& operator=(Nonce&&) noexcept; |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 394 | |
| 395 | // Note that operator<, used by maps type containers, will trigger |token_| |
| 396 | // lazy-initialization. Equality comparisons do not. |
| 397 | bool operator<(const Nonce& other) const; |
| 398 | bool operator==(const Nonce& other) const; |
| 399 | bool operator!=(const Nonce& other) const; |
| 400 | |
| 401 | private: |
| 402 | friend class OriginTest; |
| 403 | |
| 404 | // mutable to support lazy generation. |
| 405 | mutable base::UnguessableToken token_; |
| 406 | }; |
| 407 | |
| 408 | // This needs to be friended within Origin as well, since Nonce is a private |
| 409 | // nested class of Origin. |
Staphany Park | 6fd74a2 | 2018-12-04 21:15:41 | [diff] [blame] | 410 | friend COMPONENT_EXPORT(URL) std::ostream& operator<<(std::ostream& out, |
| 411 | const Nonce& nonce); |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 412 | |
| 413 | // Creates an origin without sanity checking that the host is canonicalized. |
| 414 | // This should only be used when converting between already normalized types, |
| 415 | // and should NOT be used for IPC. Method takes std::strings for use with move |
| 416 | // operators to avoid copies. |
| 417 | static Origin CreateOpaqueFromNormalizedPrecursorTuple( |
| 418 | std::string precursor_scheme, |
| 419 | std::string precursor_host, |
| 420 | uint16_t precursor_port, |
| 421 | const Nonce& nonce); |
| 422 | |
| 423 | // Creates an opaque Origin with the identity given by |nonce|, and an |
| 424 | // optional precursor origin given by |precursor_scheme|, |precursor_host| and |
| 425 | // |precursor_port|. Returns nullopt if any parameter is not canonical. When |
| 426 | // the precursor is unknown, the precursor parameters should be ("", "", 0). |
| 427 | // |
| 428 | // This factory method should be used in order to pass opaque Origin objects |
| 429 | // back and forth over IPC (as transitioning through GURL would risk |
| 430 | // potentially dangerous recanonicalization). |
Arthur Sonzogni | 75165b8 | 2023-11-07 18:25:47 | [diff] [blame] | 431 | static std::optional<Origin> UnsafelyCreateOpaqueOriginWithoutNormalization( |
David Benjamin | bf75caf | 2023-09-29 04:39:59 | [diff] [blame] | 432 | std::string_view precursor_scheme, |
| 433 | std::string_view precursor_host, |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 434 | uint16_t precursor_port, |
| 435 | const Nonce& nonce); |
| 436 | |
| 437 | // Constructs a non-opaque tuple origin. |tuple| must be valid. |
Takashi Toyoshima | 5641d755 | 2018-02-09 08:57:52 | [diff] [blame] | 438 | explicit Origin(SchemeHostPort tuple); |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 439 | |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 440 | // Constructs an opaque origin derived from the |precursor| tuple, with the |
| 441 | // given |nonce|. |
| 442 | Origin(const Nonce& nonce, SchemeHostPort precursor); |
| 443 | |
Daniel Cheng | b38154b3 | 2022-03-03 19:46:21 | [diff] [blame] | 444 | // Get the nonce associated with this origin, if it is opaque, or nullptr |
| 445 | // otherwise. This should be used only when trying to send an Origin across an |
| 446 | // IPC pipe. |
| 447 | const base::UnguessableToken* GetNonceForSerialization() const; |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 448 | |
Robert Ogden | dd74d73 | 2020-03-12 17:33:19 | [diff] [blame] | 449 | // Serializes this Origin, including its nonce if it is opaque. If an opaque |
John Delaney | 513e53f | 2020-10-29 20:16:04 | [diff] [blame] | 450 | // origin's |tuple_| is invalid nullopt is returned. If the nonce is not |
| 451 | // initialized, a nonce of 0 is used. Use of this method should be limited as |
| 452 | // an opaque origin will never be matchable in future browser sessions. |
Arthur Sonzogni | 75165b8 | 2023-11-07 18:25:47 | [diff] [blame] | 453 | std::optional<std::string> SerializeWithNonce() const; |
Robert Ogden | dd74d73 | 2020-03-12 17:33:19 | [diff] [blame] | 454 | |
John Delaney | 513e53f | 2020-10-29 20:16:04 | [diff] [blame] | 455 | // Like SerializeWithNonce(), but forces |nonce_| to be initialized prior to |
| 456 | // serializing. |
Arthur Sonzogni | 75165b8 | 2023-11-07 18:25:47 | [diff] [blame] | 457 | std::optional<std::string> SerializeWithNonceAndInitIfNeeded(); |
John Delaney | 513e53f | 2020-10-29 20:16:04 | [diff] [blame] | 458 | |
Arthur Sonzogni | 75165b8 | 2023-11-07 18:25:47 | [diff] [blame] | 459 | std::optional<std::string> SerializeWithNonceImpl() const; |
John Delaney | 513e53f | 2020-10-29 20:16:04 | [diff] [blame] | 460 | |
Robert Ogden | dd74d73 | 2020-03-12 17:33:19 | [diff] [blame] | 461 | // Deserializes an origin from |ToValueWithNonce|. Returns nullopt if the |
| 462 | // value was invalid in any way. |
Arthur Sonzogni | 75165b8 | 2023-11-07 18:25:47 | [diff] [blame] | 463 | static std::optional<Origin> Deserialize(const std::string& value); |
Robert Ogden | dd74d73 | 2020-03-12 17:33:19 | [diff] [blame] | 464 | |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 465 | // The tuple is used for both tuple origins (e.g. https://example.com:80), as |
| 466 | // well as for opaque origins, where it tracks the tuple origin from which |
| 467 | // the opaque origin was initially derived (we call this the "precursor" |
| 468 | // origin). |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 469 | SchemeHostPort tuple_; |
Daniel Cheng | 62ff018 | 2018-08-25 07:59:33 | [diff] [blame] | 470 | |
| 471 | // The nonce is used for maintaining identity of an opaque origin. This |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 472 | // nonce is preserved when an opaque origin is copied or moved. An Origin |
| 473 | // is considered opaque if and only if |nonce_| holds a value. |
Arthur Sonzogni | 75165b8 | 2023-11-07 18:25:47 | [diff] [blame] | 474 | std::optional<Nonce> nonce_; |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 475 | }; |
| 476 | |
Nasko Oskov | 9277dfc | 2018-09-17 23:20:54 | [diff] [blame] | 477 | // Pretty-printers for logging. These expose the internal state of the nonce. |
Staphany Park | 6fd74a2 | 2018-12-04 21:15:41 | [diff] [blame] | 478 | COMPONENT_EXPORT(URL) |
| 479 | std::ostream& operator<<(std::ostream& out, const Origin& origin); |
| 480 | COMPONENT_EXPORT(URL) |
| 481 | std::ostream& operator<<(std::ostream& out, const Origin::Nonce& origin); |
palmer | 5c437bcc | 2016-02-03 23:21:36 | [diff] [blame] | 482 | |
Staphany Park | 6fd74a2 | 2018-12-04 21:15:41 | [diff] [blame] | 483 | COMPONENT_EXPORT(URL) bool IsSameOriginWith(const GURL& a, const GURL& b); |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 484 | |
Lukasz Anforowicz | cfe9b2f6 | 2022-05-25 15:47:16 | [diff] [blame] | 485 | // DEBUG_ALIAS_FOR_ORIGIN(var_name, origin) copies `origin` into a new |
| 486 | // stack-allocated variable named `<var_name>`. This helps ensure that the |
| 487 | // value of `origin` gets preserved in crash dumps. |
Lukasz Anforowicz | 3d58b939 | 2018-01-05 20:56:22 | [diff] [blame] | 488 | #define DEBUG_ALIAS_FOR_ORIGIN(var_name, origin) \ |
Daniel Cheng | afbf635 | 2018-04-24 23:59:25 | [diff] [blame] | 489 | DEBUG_ALIAS_FOR_CSTR(var_name, (origin).Serialize().c_str(), 128) |
Lukasz Anforowicz | 3d58b939 | 2018-01-05 20:56:22 | [diff] [blame] | 490 | |
Lukasz Anforowicz | 731c39c | 2020-02-07 23:35:58 | [diff] [blame] | 491 | namespace debug { |
| 492 | |
Lukasz Anforowicz | 36d24d3 | 2022-02-15 19:02:53 | [diff] [blame] | 493 | class COMPONENT_EXPORT(URL) ScopedOriginCrashKey { |
Lukasz Anforowicz | 731c39c | 2020-02-07 23:35:58 | [diff] [blame] | 494 | public: |
| 495 | ScopedOriginCrashKey(base::debug::CrashKeyString* crash_key, |
| 496 | const url::Origin* value); |
| 497 | ~ScopedOriginCrashKey(); |
| 498 | |
| 499 | ScopedOriginCrashKey(const ScopedOriginCrashKey&) = delete; |
| 500 | ScopedOriginCrashKey& operator=(const ScopedOriginCrashKey&) = delete; |
Lukasz Anforowicz | 36d24d3 | 2022-02-15 19:02:53 | [diff] [blame] | 501 | |
| 502 | private: |
| 503 | base::debug::ScopedCrashKeyString scoped_string_value_; |
Lukasz Anforowicz | 731c39c | 2020-02-07 23:35:58 | [diff] [blame] | 504 | }; |
| 505 | |
| 506 | } // namespace debug |
| 507 | |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 508 | } // namespace url |
| 509 | |
qyearsley | 2bc727d | 2015-08-14 20:17:15 | [diff] [blame] | 510 | #endif // URL_ORIGIN_H_ |