Introduce and adopt new class RegistrableDomain for eTLD+1
[WebKit.git] / Source / WebCore / platform / network / NetworkStorageSession.cpp
1 /*
2  * Copyright (C) 2016-2018 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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "NetworkStorageSession.h"
28
29 #include "RuntimeApplicationChecks.h"
30 #include <pal/SessionID.h>
31 #include <wtf/NeverDestroyed.h>
32 #include <wtf/ProcessPrivilege.h>
33
34 #if ENABLE(RESOURCE_LOAD_STATISTICS)
35 #include "ResourceRequest.h"
36 #if ENABLE(PUBLIC_SUFFIX_LIST)
37 #include "PublicSuffix.h"
38 #endif
39 #endif
40
41 namespace WebCore {
42
43 bool NetworkStorageSession::m_processMayUseCookieAPI = false;
44
45 bool NetworkStorageSession::processMayUseCookieAPI()
46 {
47     return m_processMayUseCookieAPI;
48 }
49
50 void NetworkStorageSession::permitProcessToUseCookieAPI(bool value)
51 {
52     m_processMayUseCookieAPI = value;
53     if (m_processMayUseCookieAPI)
54         addProcessPrivilege(ProcessPrivilege::CanAccessRawCookies);
55     else
56         removeProcessPrivilege(ProcessPrivilege::CanAccessRawCookies);
57 }
58
59 #if ENABLE(RESOURCE_LOAD_STATISTICS)
60
61 bool NetworkStorageSession::shouldBlockThirdPartyCookies(const RegistrableDomain& registrableDomain) const
62 {
63     if (registrableDomain.isEmpty())
64         return false;
65
66     return m_registrableDomainsToBlockCookieFor.contains(registrableDomain);
67 }
68
69 bool NetworkStorageSession::shouldBlockCookies(const ResourceRequest& request, Optional<uint64_t> frameID, Optional<uint64_t> pageID) const
70 {
71     return shouldBlockCookies(request.firstPartyForCookies(), request.url(), frameID, pageID);
72 }
73     
74 bool NetworkStorageSession::shouldBlockCookies(const URL& firstPartyForCookies, const URL& resource, Optional<uint64_t> frameID, Optional<uint64_t> pageID) const
75 {
76     RegistrableDomain firstPartyDomain { firstPartyForCookies };
77     if (firstPartyDomain.isEmpty())
78         return false;
79
80     RegistrableDomain resourceDomain { resource };
81     if (resourceDomain.isEmpty())
82         return false;
83
84     if (firstPartyDomain == resourceDomain)
85         return false;
86
87     if (pageID && hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID.value()))
88         return false;
89
90     return shouldBlockThirdPartyCookies(resourceDomain);
91 }
92
93 Optional<Seconds> NetworkStorageSession::maxAgeCacheCap(const ResourceRequest& request)
94 {
95     if (m_cacheMaxAgeCapForPrevalentResources && shouldBlockCookies(request, WTF::nullopt, WTF::nullopt))
96         return m_cacheMaxAgeCapForPrevalentResources;
97     return WTF::nullopt;
98 }
99
100 void NetworkStorageSession::setAgeCapForClientSideCookies(Optional<Seconds> seconds)
101 {
102     m_ageCapForClientSideCookies = seconds;
103 }
104
105 void NetworkStorageSession::setPrevalentDomainsToBlockCookiesFor(const Vector<RegistrableDomain>& domains)
106 {
107     m_registrableDomainsToBlockCookieFor.clear();
108     m_registrableDomainsToBlockCookieFor.add(domains.begin(), domains.end());
109 }
110
111 void NetworkStorageSession::removePrevalentDomains(const Vector<RegistrableDomain>& domains)
112 {
113     for (auto& domain : domains)
114         m_registrableDomainsToBlockCookieFor.remove(domain);
115 }
116
117 bool NetworkStorageSession::hasStorageAccess(const RegistrableDomain& resourceDomain, const RegistrableDomain& firstPartyDomain, Optional<uint64_t> frameID, uint64_t pageID) const
118 {
119     if (frameID) {
120         auto framesGrantedIterator = m_framesGrantedStorageAccess.find(pageID);
121         if (framesGrantedIterator != m_framesGrantedStorageAccess.end()) {
122             auto it = framesGrantedIterator->value.find(frameID.value());
123             if (it != framesGrantedIterator->value.end() && it->value == resourceDomain)
124                 return true;
125         }
126     }
127
128     if (!firstPartyDomain.isEmpty()) {
129         auto pagesGrantedIterator = m_pagesGrantedStorageAccess.find(pageID);
130         if (pagesGrantedIterator != m_pagesGrantedStorageAccess.end()) {
131             auto it = pagesGrantedIterator->value.find(firstPartyDomain);
132             if (it != pagesGrantedIterator->value.end() && it->value == resourceDomain)
133                 return true;
134         }
135     }
136
137     return false;
138 }
139
140 Vector<String> NetworkStorageSession::getAllStorageAccessEntries() const
141 {
142     Vector<String> entries;
143     for (auto& innerMap : m_framesGrantedStorageAccess.values()) {
144         for (auto& value : innerMap.values())
145             entries.append(value.string());
146     }
147     return entries;
148 }
149     
150 void NetworkStorageSession::grantStorageAccess(const RegistrableDomain& resourceDomain, const RegistrableDomain& firstPartyDomain, Optional<uint64_t> frameID, uint64_t pageID)
151 {
152     if (!frameID) {
153         if (firstPartyDomain.isEmpty())
154             return;
155         auto pagesGrantedIterator = m_pagesGrantedStorageAccess.find(pageID);
156         if (pagesGrantedIterator == m_pagesGrantedStorageAccess.end()) {
157             HashMap<RegistrableDomain, RegistrableDomain> entry;
158             entry.add(firstPartyDomain, resourceDomain);
159             m_pagesGrantedStorageAccess.add(pageID, entry);
160         } else {
161             auto firstPartyDomainIterator = pagesGrantedIterator->value.find(firstPartyDomain);
162             if (firstPartyDomainIterator == pagesGrantedIterator->value.end())
163                 pagesGrantedIterator->value.add(firstPartyDomain, resourceDomain);
164             else
165                 firstPartyDomainIterator->value = resourceDomain;
166         }
167         return;
168     }
169
170     auto pagesGrantedIterator = m_framesGrantedStorageAccess.find(pageID);
171     if (pagesGrantedIterator == m_framesGrantedStorageAccess.end()) {
172         HashMap<uint64_t, RegistrableDomain, DefaultHash<uint64_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> entry;
173         entry.add(frameID.value(), resourceDomain);
174         m_framesGrantedStorageAccess.add(pageID, entry);
175     } else {
176         auto framesGrantedIterator = pagesGrantedIterator->value.find(frameID.value());
177         if (framesGrantedIterator == pagesGrantedIterator->value.end())
178             pagesGrantedIterator->value.add(frameID.value(), resourceDomain);
179         else
180             framesGrantedIterator->value = resourceDomain;
181     }
182 }
183
184 void NetworkStorageSession::removeStorageAccessForFrame(uint64_t frameID, uint64_t pageID)
185 {
186     auto iteration = m_framesGrantedStorageAccess.find(pageID);
187     if (iteration == m_framesGrantedStorageAccess.end())
188         return;
189
190     iteration->value.remove(frameID);
191 }
192
193 void NetworkStorageSession::removeStorageAccessForAllFramesOnPage(uint64_t pageID)
194 {
195     m_pagesGrantedStorageAccess.remove(pageID);
196     m_framesGrantedStorageAccess.remove(pageID);
197 }
198
199 void NetworkStorageSession::removeAllStorageAccess()
200 {
201     m_pagesGrantedStorageAccess.clear();
202     m_framesGrantedStorageAccess.clear();
203 }
204
205 void NetworkStorageSession::setCacheMaxAgeCapForPrevalentResources(Seconds seconds)
206 {
207     m_cacheMaxAgeCapForPrevalentResources = seconds;
208 }
209     
210 void NetworkStorageSession::resetCacheMaxAgeCapForPrevalentResources()
211 {
212     m_cacheMaxAgeCapForPrevalentResources = WTF::nullopt;
213 }
214 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
215
216 }