mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors. All rights reserved. |
| 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 | |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 10 | #include <string> |
| 11 | |
| 12 | #include "base/strings/string16.h" |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 13 | #include "base/strings/string_piece.h" |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 14 | #include "url/scheme_host_port.h" |
| 15 | #include "url/third_party/mozilla/url_parse.h" |
| 16 | #include "url/url_canon.h" |
| 17 | #include "url/url_constants.h" |
| 18 | #include "url/url_export.h" |
| 19 | |
| 20 | class GURL; |
| 21 | |
| 22 | namespace url { |
| 23 | |
| 24 | // An Origin is a tuple of (scheme, host, port), as described in RFC 6454. |
| 25 | // |
| 26 | // TL;DR: If you need to make a security-relevant decision, use 'url::Origin'. |
| 27 | // If you only need to extract the bits of a URL which are relevant for a |
| 28 | // network connection, use 'url::SchemeHostPort'. |
| 29 | // |
| 30 | // STL;SDR: If you aren't making actual network connections, use 'url::Origin'. |
| 31 | // |
| 32 | // 'Origin', like 'SchemeHostPort', is composed of a tuple of (scheme, host, |
| 33 | // port), but contains a number of additional concepts which make it appropriate |
| 34 | // for use as a security boundary and access control mechanism between contexts. |
| 35 | // |
| 36 | // This class ought to be used when code needs to determine if two resources |
| 37 | // are "same-origin", and when a canonical serialization of an origin is |
| 38 | // required. Note that some origins are "unique", meaning that they are not |
| 39 | // same-origin with any other origin (including themselves). |
| 40 | // |
| 41 | // There are a few subtleties to note: |
| 42 | // |
| 43 | // * Invalid and non-standard GURLs are parsed as unique origins. This includes |
| 44 | // non-hierarchical URLs like 'data:text/html,...' and 'javascript:alert(1)'. |
| 45 | // |
| 46 | // * GURLs with schemes of 'filesystem' or 'blob' parse the origin out of the |
| 47 | // internals of the URL. That is, 'filesystem:https://example.com/temporary/f' |
| 48 | // is parsed as ('https', 'example.com', 443). |
| 49 | // |
| 50 | // * Unique origins all serialize to the string "null"; this means that the |
| 51 | // serializations of two unique origins are identical to each other, though |
| 52 | // the origins themselves are not "the same". This means that origins' |
| 53 | // serializations must not be relied upon for security checks. |
| 54 | // |
| 55 | // * GURLs with a 'file' scheme are tricky. They are parsed as ('file', '', 0), |
| 56 | // but their behavior may differ from embedder to embedder. |
| 57 | // |
| 58 | // * The host component of an IPv6 address includes brackets, just like the URL |
| 59 | // representation. |
| 60 | // |
| 61 | // Usage: |
| 62 | // |
| 63 | // * Origins are generally constructed from an already-canonicalized GURL: |
| 64 | // |
| 65 | // GURL url("https://example.com/"); |
| 66 | // url::Origin origin(url); |
| 67 | // origin.scheme(); // "https" |
| 68 | // origin.host(); // "example.com" |
| 69 | // origin.port(); // 443 |
iclelland | e099c8a | 2016-01-07 21:10:39 | [diff] [blame] | 70 | // origin.unique(); // false |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 71 | // |
| 72 | // * To answer the question "Are |this| and |that| "same-origin" with each |
| 73 | // other?", use |Origin::IsSameOriginWith|: |
| 74 | // |
| 75 | // if (this.IsSameOriginWith(that)) { |
| 76 | // // Amazingness goes here. |
| 77 | // } |
| 78 | class URL_EXPORT Origin { |
| 79 | public: |
| 80 | // Creates a unique Origin. |
| 81 | Origin(); |
| 82 | |
| 83 | // Creates an Origin from |url|, as described at |
| 84 | // https://url.spec.whatwg.org/#origin, with the following additions: |
| 85 | // |
| 86 | // 1. If |url| is invalid or non-standard, a unique Origin is constructed. |
| 87 | // 2. 'filesystem' URLs behave as 'blob' URLs (that is, the origin is parsed |
| 88 | // out of everything in the URL which follows the scheme). |
| 89 | // 3. 'file' URLs all parse as ("file", "", 0). |
| 90 | explicit Origin(const GURL& url); |
| 91 | |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 92 | // Creates an Origin from a |scheme|, |host|, and |port|. All the parameters |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 93 | // must be valid and canonicalized. Do not use this method to create unique |
| 94 | // origins. Use Origin() for that. |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 95 | // |
| 96 | // This constructor should be used in order to pass 'Origin' objects back and |
| 97 | // forth over IPC (as transitioning through GURL would risk potentially |
| 98 | // dangerous recanonicalization); other potential callers should prefer the |
| 99 | // 'GURL'-based constructor. |
| 100 | static Origin UnsafelyCreateOriginWithoutNormalization( |
| 101 | base::StringPiece scheme, |
| 102 | base::StringPiece host, |
avi | c0c6031 | 2015-12-21 21:03:50 | [diff] [blame] | 103 | uint16_t port); |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 104 | |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 105 | // Creates an origin without sanity checking that the host is canonicalized. |
| 106 | // This should only be used when converting between already normalized types, |
csharrison | f07ac3c | 2016-12-13 04:15:02 | [diff] [blame^] | 107 | // and should NOT be used for IPC. Method takes std::strings for use with move |
| 108 | // operators to avoid copies. |
jww | 908428c | 2016-10-26 21:51:46 | [diff] [blame] | 109 | static Origin CreateFromNormalizedTupleWithSuborigin( |
csharrison | f07ac3c | 2016-12-13 04:15:02 | [diff] [blame^] | 110 | std::string scheme, |
| 111 | std::string host, |
jww | 908428c | 2016-10-26 21:51:46 | [diff] [blame] | 112 | uint16_t port, |
csharrison | f07ac3c | 2016-12-13 04:15:02 | [diff] [blame^] | 113 | std::string suborigin); |
jww | 908428c | 2016-10-26 21:51:46 | [diff] [blame] | 114 | |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 115 | ~Origin(); |
| 116 | |
| 117 | // For unique origins, these return ("", "", 0). |
mkwst | f5fef06 | 2015-07-22 08:29:01 | [diff] [blame] | 118 | const std::string& scheme() const { return tuple_.scheme(); } |
| 119 | const std::string& host() const { return tuple_.host(); } |
avi | c0c6031 | 2015-12-21 21:03:50 | [diff] [blame] | 120 | uint16_t port() const { return tuple_.port(); } |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 121 | |
jww | 0448040 | 2016-10-25 02:50:33 | [diff] [blame] | 122 | // Note that an origin without a suborgin will return the empty string. |
| 123 | const std::string& suborigin() const { return suborigin_; } |
| 124 | |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 125 | bool unique() const { return unique_; } |
| 126 | |
| 127 | // An ASCII serialization of the Origin as per Section 6.2 of RFC 6454, with |
| 128 | // the addition that all Origins with a 'file' scheme serialize to "file://". |
jww | 0448040 | 2016-10-25 02:50:33 | [diff] [blame] | 129 | // If the Origin has a suborigin, it will be serialized per |
| 130 | // https://w3c.github.io/webappsec-suborigins/#serializing. |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 131 | std::string Serialize() const; |
| 132 | |
jww | 0448040 | 2016-10-25 02:50:33 | [diff] [blame] | 133 | // Returns the physical origin for Origin. If the suborigin is empty, this |
| 134 | // will just return a copy of the Origin. If it has a suborigin, will return |
| 135 | // the Origin of just the scheme/host/port tuple, without the suborigin. See |
| 136 | // https://w3c.github.io/webappsec-suborigins/. |
| 137 | Origin GetPhysicalOrigin() const; |
| 138 | |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 139 | // Two Origins are "same-origin" if their schemes, hosts, and ports are exact |
jww | 0448040 | 2016-10-25 02:50:33 | [diff] [blame] | 140 | // matches; and neither is unique. If either of the origins have suborigins, |
| 141 | // the suborigins also must be exact matches. |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 142 | bool IsSameOriginWith(const Origin& other) const; |
mek | 0126c13 | 2016-02-17 23:50:59 | [diff] [blame] | 143 | bool operator==(const Origin& other) const { |
| 144 | return IsSameOriginWith(other); |
| 145 | } |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 146 | |
jww | 0448040 | 2016-10-25 02:50:33 | [diff] [blame] | 147 | // Same as above, but ignores suborigins if they exist. |
| 148 | bool IsSamePhysicalOriginWith(const Origin& other) const; |
| 149 | |
csharrison | 048bee1 | 2016-10-04 00:08:21 | [diff] [blame] | 150 | // Efficiently returns what GURL(Serialize()) would without re-parsing the |
| 151 | // URL. This can be used for the (rare) times a GURL representation is needed |
| 152 | // for an Origin. |
| 153 | // Note: The returned URL will not necessarily be serialized to the same value |
| 154 | // as the Origin would. The GURL will have an added "/" path for Origins with |
| 155 | // valid SchemeHostPorts and file Origins. |
| 156 | GURL GetURL() const; |
| 157 | |
pkalinnikov | 054f403 | 2016-08-31 10:54:17 | [diff] [blame] | 158 | // Same as GURL::DomainIs. If |this| origin is unique, then returns false. |
| 159 | bool DomainIs(base::StringPiece lower_ascii_domain) const; |
| 160 | |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 161 | // 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] | 162 | // std::map). |
| 163 | bool operator<(const Origin& other) const; |
| 164 | |
| 165 | private: |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 166 | Origin(base::StringPiece scheme, |
| 167 | base::StringPiece host, |
| 168 | uint16_t port, |
jww | 908428c | 2016-10-26 21:51:46 | [diff] [blame] | 169 | base::StringPiece suborigin, |
csharrison | edf893f | 2016-10-12 01:42:56 | [diff] [blame] | 170 | SchemeHostPort::ConstructPolicy policy); |
csharrison | f07ac3c | 2016-12-13 04:15:02 | [diff] [blame^] | 171 | Origin(std::string scheme, |
| 172 | std::string host, |
| 173 | uint16_t port, |
| 174 | std::string suborigin, |
| 175 | SchemeHostPort::ConstructPolicy policy); |
mkwst | d8335d98 | 2015-07-25 05:18:48 | [diff] [blame] | 176 | |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 177 | SchemeHostPort tuple_; |
| 178 | bool unique_; |
jww | 0448040 | 2016-10-25 02:50:33 | [diff] [blame] | 179 | std::string suborigin_; |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 180 | }; |
| 181 | |
palmer | 5c437bcc | 2016-02-03 23:21:36 | [diff] [blame] | 182 | URL_EXPORT std::ostream& operator<<(std::ostream& out, const Origin& origin); |
| 183 | |
| 184 | URL_EXPORT bool IsSameOriginWith(const GURL& a, const GURL& b); |
jww | 0448040 | 2016-10-25 02:50:33 | [diff] [blame] | 185 | URL_EXPORT bool IsSamePhysicalOriginWith(const GURL& a, const GURL& b); |
mkwst | 9f2cc89 | 2015-07-22 06:03:25 | [diff] [blame] | 186 | |
| 187 | } // namespace url |
| 188 | |
qyearsley | 2bc727d | 2015-08-14 20:17:15 | [diff] [blame] | 189 | #endif // URL_ORIGIN_H_ |