b386730da617b2db8d8085df05ce7d9e54bd351f
[WebKit-https.git] / Source / WebCore / platform / RegistrableDomain.h
1 /*
2  * Copyright (C) 2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "PublicSuffix.h"
29 #include <wtf/HashTraits.h>
30 #include <wtf/URL.h>
31 #include <wtf/text/WTFString.h>
32
33 namespace WebCore {
34
35 class RegistrableDomain {
36     WTF_MAKE_FAST_ALLOCATED;
37 public:
38     RegistrableDomain() = default;
39     explicit RegistrableDomain(const URL& url)
40 #if ENABLE(PUBLIC_SUFFIX_LIST)
41         : m_registrableDomain { topPrivatelyControlledDomain(url.host().toString()) }
42 #else
43         : m_registrableDomain { url.host().toString() }
44 #endif
45     {
46         auto hostString = url.host().toString();
47         if (hostString.isEmpty())
48             m_registrableDomain = "nullOrigin"_s;
49         else if (m_registrableDomain.isEmpty())
50             m_registrableDomain = hostString;
51     }
52
53     bool isEmpty() const { return m_registrableDomain.isEmpty() || m_registrableDomain == "nullOrigin"_s; }
54     const String& string() const { return m_registrableDomain; }
55
56     bool operator!=(const RegistrableDomain& other) const { return m_registrableDomain != other.m_registrableDomain; }
57     bool operator==(const RegistrableDomain& other) const { return m_registrableDomain == other.m_registrableDomain; }
58
59     bool matches(const URL& url) const
60     {
61         auto host = url.host();
62         if (host.isEmpty() && m_registrableDomain == "nullOrigin"_s)
63             return true;
64         if (!host.endsWith(m_registrableDomain))
65             return false;
66         if (host.length() == m_registrableDomain.length())
67             return true;
68         return host[host.length() - m_registrableDomain.length() - 1] == '.';
69     }
70
71     RegistrableDomain isolatedCopy() const { return RegistrableDomain { m_registrableDomain.isolatedCopy() }; }
72
73     RegistrableDomain(WTF::HashTableDeletedValueType)
74         : m_registrableDomain(WTF::HashTableDeletedValue) { }
75     bool isHashTableDeletedValue() const { return m_registrableDomain.isHashTableDeletedValue(); }
76     unsigned hash() const { return m_registrableDomain.hash(); }
77
78     struct RegistrableDomainHash {
79         static unsigned hash(const RegistrableDomain& registrableDomain) { return registrableDomain.m_registrableDomain.hash(); }
80         static bool equal(const RegistrableDomain& a, const RegistrableDomain& b) { return a == b; }
81         static const bool safeToCompareToEmptyOrDeleted = false;
82     };
83
84     static RegistrableDomain uncheckedCreateFromRegistrableDomainString(const String& domain)
85     {
86         return RegistrableDomain { domain };
87     }
88     
89     static RegistrableDomain uncheckedCreateFromHost(const String& host)
90     {
91 #if ENABLE(PUBLIC_SUFFIX_LIST)
92         auto registrableDomain = topPrivatelyControlledDomain(host);
93         if (registrableDomain.isEmpty())
94             return uncheckedCreateFromRegistrableDomainString(host);
95         return RegistrableDomain { registrableDomain };
96 #else
97         return uncheckedCreateFromRegistrableDomainString(host);
98 #endif
99     }
100
101     template<class Encoder> void encode(Encoder&) const;
102     template<class Decoder> static Optional<RegistrableDomain> decode(Decoder&);
103
104 protected:
105
106 private:
107     explicit RegistrableDomain(const String& domain)
108         : m_registrableDomain { domain.isEmpty() ? "nullOrigin"_s : domain }
109     {
110     }
111
112     String m_registrableDomain;
113 };
114
115 template<class Encoder>
116 void RegistrableDomain::encode(Encoder& encoder) const
117 {
118     encoder << m_registrableDomain;
119 }
120
121 template<class Decoder>
122 Optional<RegistrableDomain> RegistrableDomain::decode(Decoder& decoder)
123 {
124     Optional<String> domain;
125     decoder >> domain;
126     if (!domain)
127         return WTF::nullopt;
128
129     RegistrableDomain registrableDomain;
130     registrableDomain.m_registrableDomain = WTFMove(*domain);
131     return registrableDomain;
132 }
133
134 } // namespace WebCore
135
136 namespace WTF {
137 template<> struct DefaultHash<WebCore::RegistrableDomain> {
138     using Hash = WebCore::RegistrableDomain::RegistrableDomainHash;
139 };
140 template<> struct HashTraits<WebCore::RegistrableDomain> : SimpleClassHashTraits<WebCore::RegistrableDomain> { };
141 }