| // Copyright 2015 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef URL_ORIGIN_H_ | 
 | #define URL_ORIGIN_H_ | 
 |  | 
 | #include <stdint.h> | 
 |  | 
 | #include <memory> | 
 | #include <string> | 
 |  | 
 | #include "polyfills/base/component_export.h" | 
 | #include "polyfills/base/debug/alias.h" | 
 | #include "base/debug/crash_logging.h" | 
 | #include "base/strings/string_piece_forward.h" | 
 | #include "base/strings/string_util.h" | 
 | #include "base/unguessable_token.h" | 
 | #include "build/build_config.h" | 
 | #include "build/buildflag.h" | 
 | #include "ipc/ipc_param_traits.h" | 
 | #include "absl/types/optional.h" | 
 | #include "polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h" | 
 | #include "url/scheme_host_port.h" | 
 |  | 
 | #if BUILDFLAG(IS_ANDROID) | 
 | #include <jni.h> | 
 |  | 
 | namespace gurl_base { | 
 | namespace android { | 
 | template <typename> | 
 | class ScopedJavaLocalRef; | 
 | template <typename> | 
 | class JavaRef; | 
 | }  // namespace android | 
 | }  // namespace base | 
 | #endif  // BUILDFLAG(IS_ANDROID) | 
 |  | 
 | class GURL; | 
 |  | 
 | namespace blink { | 
 | class SecurityOrigin; | 
 | class SecurityOriginTest; | 
 | }  // namespace blink | 
 |  | 
 | namespace ipc_fuzzer { | 
 | template <class T> | 
 | struct FuzzTraits; | 
 | }  // namespace ipc_fuzzer | 
 |  | 
 | namespace mojo { | 
 | template <typename DataViewType, typename T> | 
 | struct StructTraits; | 
 | struct UrlOriginAdapter; | 
 | }  // namespace mojo | 
 |  | 
 | namespace net { | 
 | class SchemefulSite; | 
 | }  // namespace net | 
 |  | 
 | namespace url { | 
 |  | 
 | namespace mojom { | 
 | class OriginDataView; | 
 | }  // namespace mojom | 
 |  | 
 | // Per https://html.spec.whatwg.org/multipage/origin.html#origin, an origin is | 
 | // either: | 
 | // - a tuple origin of (scheme, host, port) as described in RFC 6454. | 
 | // - an opaque origin with an internal value, and a memory of the tuple origin | 
 | //   from which it was derived. | 
 | // | 
 | // TL;DR: If you need to make a security-relevant decision, use 'url::Origin'. | 
 | // If you only need to extract the bits of a URL which are relevant for a | 
 | // network connection, use 'url::SchemeHostPort'. | 
 | // | 
 | // STL;SDR: If you aren't making actual network connections, use 'url::Origin'. | 
 | // | 
 | // This class ought to be used when code needs to determine if two resources | 
 | // are "same-origin", and when a canonical serialization of an origin is | 
 | // required. Note that the canonical serialization of an origin *must not* be | 
 | // used to determine if two resources are same-origin. | 
 | // | 
 | // A tuple origin, like 'SchemeHostPort', is composed of a tuple of (scheme, | 
 | // host, port), but contains a number of additional concepts which make it | 
 | // appropriate for use as a security boundary and access control mechanism | 
 | // between contexts. Two tuple origins are same-origin if the tuples are equal. | 
 | // A tuple origin may also be re-created from its serialization. | 
 | // | 
 | // An opaque origin has an internal globally unique identifier. When creating a | 
 | // new opaque origin from a URL, a fresh globally unique identifier is | 
 | // generated. However, if an opaque origin is copied or moved, the internal | 
 | // globally unique identifier is preserved. Two opaque origins are same-origin | 
 | // iff the globally unique identifiers match. Unlike tuple origins, an opaque | 
 | // origin cannot be re-created from its serialization, which is always the | 
 | // string "null". | 
 | // | 
 | // IMPORTANT: Since opaque origins always serialize as the string "null", it is | 
 | // *never* safe to use the serialization for security checks! | 
 | // | 
 | // A tuple origin and an opaque origin are never same-origin. | 
 | // | 
 | // There are a few subtleties to note: | 
 | // | 
 | // * A default constructed Origin is opaque, with no precursor origin. | 
 | // | 
 | // * Invalid and non-standard GURLs are parsed as opaque origins. This includes | 
 | //   non-hierarchical URLs like 'data:text/html,...' and 'javascript:alert(1)'. | 
 | // | 
 | // * GURLs with schemes of 'filesystem' or 'blob' parse the origin out of the | 
 | //   internals of the URL. That is, 'filesystem:https://example.com/temporary/f' | 
 | //   is parsed as ('https', 'example.com', 443). | 
 | // | 
 | // * GURLs with a 'file' scheme are tricky. They are parsed as ('file', '', 0), | 
 | //   but their behavior may differ from embedder to embedder. | 
 | //   TODO(dcheng): This behavior is not consistent with Blink's notion of file | 
 | //   URLs, which always creates an opaque origin. | 
 | // | 
 | // * The host component of an IPv6 address includes brackets, just like the URL | 
 | //   representation. | 
 | // | 
 | // * Constructing origins from GURLs (or from SchemeHostPort) is typically a red | 
 | //   flag (this is true for `url::Origin::Create` but also to some extent for | 
 | //   `url::Origin::Resolve`). See docs/security/origin-vs-url.md for more. | 
 | // | 
 | // * To answer the question "Are |this| and |that| "same-origin" with each | 
 | //   other?", use |Origin::IsSameOriginWith|: | 
 | // | 
 | //     if (this.IsSameOriginWith(that)) { | 
 | //       // Amazingness goes here. | 
 | //     } | 
 | class COMPONENT_EXPORT(URL) Origin { | 
 |  public: | 
 |   // Creates an opaque Origin with a nonce that is different from all previously | 
 |   // existing origins. | 
 |   Origin(); | 
 |  | 
 |   // WARNING: Converting an URL into an Origin is usually a red flag. See | 
 |   // //docs/security/origin-vs-url.md for more details. Some discussion about | 
 |   // deprecating the Create method can be found in https://crbug.com/1270878. | 
 |   // | 
 |   // Creates an Origin from `url`, as described at | 
 |   // https://url.spec.whatwg.org/#origin, with the following additions: | 
 |   // 1. If `url` is invalid or non-standard, an opaque Origin is constructed. | 
 |   // 2. 'filesystem' URLs behave as 'blob' URLs (that is, the origin is parsed | 
 |   //    out of everything in the URL which follows the scheme). | 
 |   // 3. 'file' URLs all parse as ("file", "", 0). | 
 |   // | 
 |   // WARNING: `url::Origin::Create(url)` can give unexpected results if: | 
 |   // 1) `url` is "about:blank", or "about:srcdoc" (returning unique, opaque | 
 |   //    origin rather than the real origin of the frame) | 
 |   // 2) `url` comes from a sandboxed frame (potentially returning a non-opaque | 
 |   //    origin, when an opaque one is needed; see also | 
 |   //    https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/) | 
 |   // 3) Wrong `url` is used - e.g. in some navigations `base_url_for_data_url` | 
 |   //    might need to be used instead of relying on | 
 |   //    `content::NavigationHandle::GetURL`. | 
 |   // | 
 |   // WARNING: The returned Origin may have a different scheme and host from | 
 |   // `url` (e.g. in case of blob URLs - see OriginTest.ConstructFromGURL). | 
 |   // | 
 |   // WARNING: data: URLs will be correctly be translated into opaque origins, | 
 |   // but the precursor origin will be lost (unlike with `url::Origin::Resolve`). | 
 |   static Origin Create(const GURL& url); | 
 |  | 
 |   // Creates an Origin for the resource `url` as if it were requested | 
 |   // from the context of `base_origin`. If `url` is standard | 
 |   // (in the sense that it embeds a complete origin, like http/https), | 
 |   // this returns the same value as would Create(). | 
 |   // | 
 |   // If `url` is "about:blank" or "about:srcdoc", this returns a copy of | 
 |   // `base_origin`. | 
 |   // | 
 |   // Otherwise, returns a new opaque origin derived from `base_origin`. | 
 |   // In this case, the resulting opaque origin will inherit the tuple | 
 |   // (or precursor tuple) of `base_origin`, but will not be same origin | 
 |   // with `base_origin`, even if `base_origin` is already opaque. | 
 |   static Origin Resolve(const GURL& url, const Origin& base_origin); | 
 |  | 
 |   // Copyable and movable. | 
 |   Origin(const Origin&); | 
 |   Origin& operator=(const Origin&); | 
 |   Origin(Origin&&) noexcept; | 
 |   Origin& operator=(Origin&&) noexcept; | 
 |  | 
 |   // Creates an Origin from a |scheme|, |host|, and |port|. All the parameters | 
 |   // must be valid and canonicalized. Returns nullopt if any parameter is not | 
 |   // canonical, or if all the parameters are empty. | 
 |   // | 
 |   // This constructor should be used in order to pass 'Origin' objects back and | 
 |   // forth over IPC (as transitioning through GURL would risk potentially | 
 |   // dangerous recanonicalization); other potential callers should prefer the | 
 |   // 'GURL'-based constructor. | 
 |   static absl::optional<Origin> UnsafelyCreateTupleOriginWithoutNormalization( | 
 |       gurl_base::StringPiece scheme, | 
 |       gurl_base::StringPiece host, | 
 |       uint16_t port); | 
 |  | 
 |   // Creates an origin without sanity checking that the host is canonicalized. | 
 |   // This should only be used when converting between already normalized types, | 
 |   // and should NOT be used for IPC. Method takes std::strings for use with move | 
 |   // operators to avoid copies. | 
 |   static Origin CreateFromNormalizedTuple(std::string scheme, | 
 |                                           std::string host, | 
 |                                           uint16_t port); | 
 |  | 
 |   ~Origin(); | 
 |  | 
 |   // For opaque origins, these return ("", "", 0). | 
 |   const std::string& scheme() const { | 
 |     return !opaque() ? tuple_.scheme() : gurl_base::EmptyString(); | 
 |   } | 
 |   const std::string& host() const { | 
 |     return !opaque() ? tuple_.host() : gurl_base::EmptyString(); | 
 |   } | 
 |   uint16_t port() const { return !opaque() ? tuple_.port() : 0; } | 
 |  | 
 |   bool opaque() const { return nonce_.has_value(); } | 
 |  | 
 |   // An ASCII serialization of the Origin as per Section 6.2 of RFC 6454, with | 
 |   // the addition that all Origins with a 'file' scheme serialize to "file://". | 
 |   std::string Serialize() const; | 
 |  | 
 |   // Two non-opaque Origins are "same-origin" if their schemes, hosts, and ports | 
 |   // are exact matches. Two opaque origins are same-origin only if their | 
 |   // internal nonce values match. A non-opaque origin is never same-origin with | 
 |   // an opaque origin. | 
 |   bool IsSameOriginWith(const Origin& other) const; | 
 |   bool operator==(const Origin& other) const { return IsSameOriginWith(other); } | 
 |   bool operator!=(const Origin& other) const { | 
 |     return !IsSameOriginWith(other); | 
 |   } | 
 |  | 
 |   // Non-opaque origin is "same-origin" with `url` if their schemes, hosts, and | 
 |   // ports are exact matches. Opaque origin is never "same-origin" with any | 
 |   // `url`.  about:blank, about:srcdoc, and invalid GURLs are never | 
 |   // "same-origin" with any origin. This method is a shorthand for | 
 |   // `origin.IsSameOriginWith(url::Origin::Create(url))`. | 
 |   // | 
 |   // See also CanBeDerivedFrom. | 
 |   bool IsSameOriginWith(const GURL& url) const; | 
 |  | 
 |   // This method returns true for any |url| which if navigated to could result | 
 |   // in an origin compatible with |this|. | 
 |   bool CanBeDerivedFrom(const GURL& url) const; | 
 |  | 
 |   // Get the scheme, host, and port from which this origin derives. For | 
 |   // a tuple Origin, this gives the same values as calling scheme(), host() | 
 |   // and port(). For an opaque Origin that was created by calling | 
 |   // Origin::DeriveNewOpaqueOrigin() on a precursor or Origin::Resolve(), | 
 |   // this returns the tuple inherited from the precursor. | 
 |   // | 
 |   // If this Origin is opaque and was created via the default constructor or | 
 |   // Origin::Create(), the precursor origin is unknown. | 
 |   // | 
 |   // Use with great caution: opaque origins should generally not inherit | 
 |   // privileges from the origins they derive from. However, in some cases | 
 |   // (such as restrictions on process placement, or determining the http lock | 
 |   // icon) this information may be relevant to ensure that entering an | 
 |   // opaque origin does not grant privileges initially denied to the original | 
 |   // non-opaque origin. | 
 |   // | 
 |   // This method has a deliberately obnoxious name to prompt caution in its use. | 
 |   const SchemeHostPort& GetTupleOrPrecursorTupleIfOpaque() const { | 
 |     return tuple_; | 
 |   } | 
 |  | 
 |   // Efficiently returns what GURL(Serialize()) would without re-parsing the | 
 |   // URL. This can be used for the (rare) times a GURL representation is needed | 
 |   // for an Origin. | 
 |   // Note: The returned URL will not necessarily be serialized to the same value | 
 |   // as the Origin would. The GURL will have an added "/" path for Origins with | 
 |   // valid SchemeHostPorts and file Origins. | 
 |   // | 
 |   // Try not to use this method under normal circumstances, as it loses type | 
 |   // information. Downstream consumers can mistake the returned GURL with a full | 
 |   // URL (e.g. with a path component). | 
 |   GURL GetURL() const; | 
 |  | 
 |   // Same as GURL::DomainIs. If |this| origin is opaque, then returns false. | 
 |   bool DomainIs(gurl_base::StringPiece canonical_domain) const; | 
 |  | 
 |   // Allows Origin to be used as a key in STL (for example, a std::set or | 
 |   // std::map). | 
 |   bool operator<(const Origin& other) const; | 
 |  | 
 |   // Creates a new opaque origin that is guaranteed to be cross-origin to all | 
 |   // currently existing origins. An origin created by this method retains its | 
 |   // identity across copies. Copies are guaranteed to be same-origin to each | 
 |   // other, e.g. | 
 |   // | 
 |   //   url::Origin page = Origin::Create(GURL("http://example.com")) | 
 |   //   url::Origin a = page.DeriveNewOpaqueOrigin(); | 
 |   //   url::Origin b = page.DeriveNewOpaqueOrigin(); | 
 |   //   url::Origin c = a; | 
 |   //   url::Origin d = b; | 
 |   // | 
 |   // |a| and |c| are same-origin, since |c| was copied from |a|. |b| and |d| are | 
 |   // same-origin as well, since |d| was copied from |b|. All other combinations | 
 |   // of origins are considered cross-origin, e.g. |a| is cross-origin to |b| and | 
 |   // |d|, |b| is cross-origin to |a| and |c|, |c| is cross-origin to |b| and | 
 |   // |d|, and |d| is cross-origin to |a| and |c|. | 
 |   Origin DeriveNewOpaqueOrigin() const; | 
 |  | 
 |   // Creates a string representation of the object that can be used for logging | 
 |   // and debugging. It serializes the internal state, such as the nonce value | 
 |   // and precursor information. | 
 |   std::string GetDebugString(bool include_nonce = true) const; | 
 |  | 
 | #if BUILDFLAG(IS_ANDROID) | 
 |   gurl_base::android::ScopedJavaLocalRef<jobject> CreateJavaObject() const; | 
 |   static Origin FromJavaObject( | 
 |       const gurl_base::android::JavaRef<jobject>& java_origin); | 
 | #endif  // BUILDFLAG(IS_ANDROID) | 
 |  | 
 |   void WriteIntoTrace(perfetto::TracedValue context) const; | 
 |  | 
 |  private: | 
 |   friend class blink::SecurityOrigin; | 
 |   friend class blink::SecurityOriginTest; | 
 |   // SchemefulSite needs access to the serialization/deserialization logic which | 
 |   // includes the nonce. | 
 |   friend class net::SchemefulSite; | 
 |   friend class OriginTest; | 
 |   friend struct mojo::UrlOriginAdapter; | 
 |   friend struct ipc_fuzzer::FuzzTraits<Origin>; | 
 |   friend struct mojo::StructTraits<url::mojom::OriginDataView, url::Origin>; | 
 |   friend IPC::ParamTraits<url::Origin>; | 
 |   friend COMPONENT_EXPORT(URL) std::ostream& operator<<(std::ostream& out, | 
 |                                                         const Origin& origin); | 
 |  | 
 |   // Origin::Nonce is a wrapper around gurl_base::UnguessableToken that generates | 
 |   // the random value only when the value is first accessed. The lazy generation | 
 |   // allows Origin to be default-constructed quickly, without spending time | 
 |   // in random number generation. | 
 |   // | 
 |   // TODO(nick): Should this optimization move into UnguessableToken, once it no | 
 |   // longer treats the Null case specially? | 
 |   class COMPONENT_EXPORT(URL) Nonce { | 
 |    public: | 
 |     // Creates a nonce to hold a newly-generated UnguessableToken. The actual | 
 |     // token value will be generated lazily. | 
 |     Nonce(); | 
 |  | 
 |     // Creates a nonce to hold an already-generated UnguessableToken value. This | 
 |     // constructor should only be used for IPC serialization and testing -- | 
 |     // regular code should never need to touch the UnguessableTokens directly, | 
 |     // and the default constructor is faster. | 
 |     explicit Nonce(const gurl_base::UnguessableToken& token); | 
 |  | 
 |     // Accessor, which lazily initializes the underlying |token_| member. | 
 |     const gurl_base::UnguessableToken& token() const; | 
 |  | 
 |     // Do not use in cases where lazy initialization is expected! This | 
 |     // accessor does not initialize the |token_| member. | 
 |     const gurl_base::UnguessableToken& raw_token() const; | 
 |  | 
 |     // Copyable and movable. Copying a Nonce triggers lazy-initialization, | 
 |     // moving it does not. | 
 |     Nonce(const Nonce&); | 
 |     Nonce& operator=(const Nonce&); | 
 |     Nonce(Nonce&&) noexcept; | 
 |     Nonce& operator=(Nonce&&) noexcept; | 
 |  | 
 |     // Note that operator<, used by maps type containers, will trigger |token_| | 
 |     // lazy-initialization. Equality comparisons do not. | 
 |     bool operator<(const Nonce& other) const; | 
 |     bool operator==(const Nonce& other) const; | 
 |     bool operator!=(const Nonce& other) const; | 
 |  | 
 |    private: | 
 |     friend class OriginTest; | 
 |  | 
 |     // mutable to support lazy generation. | 
 |     mutable gurl_base::UnguessableToken token_; | 
 |   }; | 
 |  | 
 |   // This needs to be friended within Origin as well, since Nonce is a private | 
 |   // nested class of Origin. | 
 |   friend COMPONENT_EXPORT(URL) std::ostream& operator<<(std::ostream& out, | 
 |                                                         const Nonce& nonce); | 
 |  | 
 |   // Creates an origin without sanity checking that the host is canonicalized. | 
 |   // This should only be used when converting between already normalized types, | 
 |   // and should NOT be used for IPC. Method takes std::strings for use with move | 
 |   // operators to avoid copies. | 
 |   static Origin CreateOpaqueFromNormalizedPrecursorTuple( | 
 |       std::string precursor_scheme, | 
 |       std::string precursor_host, | 
 |       uint16_t precursor_port, | 
 |       const Nonce& nonce); | 
 |  | 
 |   // Creates an opaque Origin with the identity given by |nonce|, and an | 
 |   // optional precursor origin given by |precursor_scheme|, |precursor_host| and | 
 |   // |precursor_port|. Returns nullopt if any parameter is not canonical. When | 
 |   // the precursor is unknown, the precursor parameters should be ("", "", 0). | 
 |   // | 
 |   // This factory method should be used in order to pass opaque Origin objects | 
 |   // back and forth over IPC (as transitioning through GURL would risk | 
 |   // potentially dangerous recanonicalization). | 
 |   static absl::optional<Origin> UnsafelyCreateOpaqueOriginWithoutNormalization( | 
 |       gurl_base::StringPiece precursor_scheme, | 
 |       gurl_base::StringPiece precursor_host, | 
 |       uint16_t precursor_port, | 
 |       const Nonce& nonce); | 
 |  | 
 |   // Constructs a non-opaque tuple origin. |tuple| must be valid. | 
 |   explicit Origin(SchemeHostPort tuple); | 
 |  | 
 |   // Constructs an opaque origin derived from the |precursor| tuple, with the | 
 |   // given |nonce|. | 
 |   Origin(const Nonce& nonce, SchemeHostPort precursor); | 
 |  | 
 |   // Get the nonce associated with this origin, if it is opaque, or nullptr | 
 |   // otherwise. This should be used only when trying to send an Origin across an | 
 |   // IPC pipe. | 
 |   const gurl_base::UnguessableToken* GetNonceForSerialization() const; | 
 |  | 
 |   // Serializes this Origin, including its nonce if it is opaque. If an opaque | 
 |   // origin's |tuple_| is invalid nullopt is returned. If the nonce is not | 
 |   // initialized, a nonce of 0 is used. Use of this method should be limited as | 
 |   // an opaque origin will never be matchable in future browser sessions. | 
 |   absl::optional<std::string> SerializeWithNonce() const; | 
 |  | 
 |   // Like SerializeWithNonce(), but forces |nonce_| to be initialized prior to | 
 |   // serializing. | 
 |   absl::optional<std::string> SerializeWithNonceAndInitIfNeeded(); | 
 |  | 
 |   absl::optional<std::string> SerializeWithNonceImpl() const; | 
 |  | 
 |   // Deserializes an origin from |ToValueWithNonce|. Returns nullopt if the | 
 |   // value was invalid in any way. | 
 |   static absl::optional<Origin> Deserialize(const std::string& value); | 
 |  | 
 |   // The tuple is used for both tuple origins (e.g. https://example.com:80), as | 
 |   // well as for opaque origins, where it tracks the tuple origin from which | 
 |   // the opaque origin was initially derived (we call this the "precursor" | 
 |   // origin). | 
 |   SchemeHostPort tuple_; | 
 |  | 
 |   // The nonce is used for maintaining identity of an opaque origin. This | 
 |   // nonce is preserved when an opaque origin is copied or moved. An Origin | 
 |   // is considered opaque if and only if |nonce_| holds a value. | 
 |   absl::optional<Nonce> nonce_; | 
 | }; | 
 |  | 
 | // Pretty-printers for logging. These expose the internal state of the nonce. | 
 | COMPONENT_EXPORT(URL) | 
 | std::ostream& operator<<(std::ostream& out, const Origin& origin); | 
 | COMPONENT_EXPORT(URL) | 
 | std::ostream& operator<<(std::ostream& out, const Origin::Nonce& origin); | 
 |  | 
 | COMPONENT_EXPORT(URL) bool IsSameOriginWith(const GURL& a, const GURL& b); | 
 |  | 
 | // DEBUG_ALIAS_FOR_ORIGIN(var_name, origin) copies `origin` into a new | 
 | // stack-allocated variable named `<var_name>`. This helps ensure that the | 
 | // value of `origin` gets preserved in crash dumps. | 
 | #define DEBUG_ALIAS_FOR_ORIGIN(var_name, origin) \ | 
 |   DEBUG_ALIAS_FOR_CSTR(var_name, (origin).Serialize().c_str(), 128) | 
 |  | 
 | namespace debug { | 
 |  | 
 | class COMPONENT_EXPORT(URL) ScopedOriginCrashKey { | 
 |  public: | 
 |   ScopedOriginCrashKey(gurl_base::debug::CrashKeyString* crash_key, | 
 |                        const url::Origin* value); | 
 |   ~ScopedOriginCrashKey(); | 
 |  | 
 |   ScopedOriginCrashKey(const ScopedOriginCrashKey&) = delete; | 
 |   ScopedOriginCrashKey& operator=(const ScopedOriginCrashKey&) = delete; | 
 |  | 
 |  private: | 
 |   gurl_base::debug::ScopedCrashKeyString scoped_string_value_; | 
 | }; | 
 |  | 
 | }  // namespace debug | 
 |  | 
 | }  // namespace url | 
 |  | 
 | #endif  // URL_ORIGIN_H_ |