Serenity Operating System
1/*
2 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
3 * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#pragma once
9
10#include <AK/DeprecatedString.h>
11
12namespace Web::HTML {
13
14class Origin {
15public:
16 Origin() = default;
17 Origin(DeprecatedString const& scheme, DeprecatedString const& host, u16 port)
18 : m_scheme(scheme)
19 , m_host(host)
20 , m_port(port)
21 {
22 }
23
24 // https://html.spec.whatwg.org/multipage/origin.html#concept-origin-opaque
25 bool is_opaque() const { return m_scheme.is_null() && m_host.is_null() && m_port == 0; }
26
27 DeprecatedString const& scheme() const { return m_scheme; }
28 DeprecatedString const& host() const { return m_host; }
29 u16 port() const { return m_port; }
30
31 // https://html.spec.whatwg.org/multipage/origin.html#same-origin
32 bool is_same_origin(Origin const& other) const
33 {
34 // 1. If A and B are the same opaque origin, then return true.
35 if (is_opaque() && other.is_opaque())
36 return true;
37
38 // 2. If A and B are both tuple origins and their schemes, hosts, and port are identical, then return true.
39 // 3. Return false.
40 return scheme() == other.scheme()
41 && host() == other.host()
42 && port() == other.port();
43 }
44
45 // https://html.spec.whatwg.org/multipage/origin.html#same-origin-domain
46 bool is_same_origin_domain(Origin const& other) const
47 {
48 // 1. If A and B are the same opaque origin, then return true.
49 if (is_opaque() && other.is_opaque())
50 return true;
51
52 // 2. If A and B are both tuple origins, run these substeps:
53 if (!is_opaque() && !other.is_opaque()) {
54 // 1. If A and B's schemes are identical, and their domains are identical and non-null, then return true.
55 // FIXME: Check domains once supported.
56 if (scheme() == other.scheme())
57 return true;
58
59 // 2. Otherwise, if A and B are same origin and their domains are identical and null, then return true.
60 // FIXME: Check domains once supported.
61 if (is_same_origin(other))
62 return true;
63 }
64
65 // 3. Return false.
66 return false;
67 }
68
69 // https://html.spec.whatwg.org/multipage/origin.html#ascii-serialisation-of-an-origin
70 DeprecatedString serialize() const
71 {
72 // 1. If origin is an opaque origin, then return "null"
73 if (is_opaque())
74 return "null";
75
76 // 2. Otherwise, let result be origin's scheme.
77 StringBuilder result;
78 result.append(scheme());
79
80 // 3. Append "://" to result.
81 result.append("://"sv);
82
83 // 4. Append origin's host, serialized, to result.
84 result.append(host());
85
86 // 5. If origin's port is non-null, append a U+003A COLON character (:), and origin's port, serialized, to result.
87 if (port() != 0) {
88 result.append(':');
89 result.append(DeprecatedString::number(port()));
90 }
91 // 6. Return result
92 return result.to_deprecated_string();
93 }
94
95 // https://html.spec.whatwg.org/multipage/origin.html#concept-origin-effective-domain
96 Optional<DeprecatedString> effective_domain() const
97 {
98 // 1. If origin is an opaque origin, then return null.
99 if (is_opaque())
100 return Optional<DeprecatedString> {};
101
102 // FIXME: 2. If origin's domain is non-null, then return origin's domain.
103
104 // 3. Return origin's host.
105 return m_host;
106 }
107
108 bool operator==(Origin const& other) const { return is_same_origin(other); }
109
110private:
111 DeprecatedString m_scheme;
112 DeprecatedString m_host;
113 u16 m_port { 0 };
114};
115
116}
117
118namespace AK {
119template<>
120struct Traits<Web::HTML::Origin> : public GenericTraits<Web::HTML::Origin> {
121 static unsigned hash(Web::HTML::Origin const& origin)
122 {
123 return pair_int_hash(origin.scheme().hash(), pair_int_hash(int_hash(origin.port()), origin.host().hash()));
124 }
125};
126} // namespace AK