3258305c789d775fe15c1c0828c36e9e2f2a8609
[WebKit.git] / Source / WebKit / WebProcess / WebPage / WebCookieJar.cpp
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 #include "config.h"
27 #include "WebCookieJar.h"
28
29 #include "NetworkConnectionToWebProcessMessages.h"
30 #include "NetworkProcessConnection.h"
31 #include "WebFrame.h"
32 #include "WebPage.h"
33 #include "WebProcess.h"
34 #include <WebCore/CookieRequestHeaderFieldProxy.h>
35 #include <WebCore/DeprecatedGlobalSettings.h>
36 #include <WebCore/Document.h>
37 #include <WebCore/Frame.h>
38 #include <WebCore/FrameLoader.h>
39 #include <WebCore/FrameLoaderClient.h>
40 #include <WebCore/StorageSessionProvider.h>
41
42 namespace WebKit {
43
44 using namespace WebCore;
45
46 class WebStorageSessionProvider : public WebCore::StorageSessionProvider {
47     // NetworkStorageSessions are accessed only in the NetworkProcess.
48     WebCore::NetworkStorageSession* storageSession() const final { return nullptr; }
49 };
50
51 WebCookieJar::WebCookieJar()
52     : WebCore::CookieJar(adoptRef(*new WebStorageSessionProvider)) { }
53
54 #if ENABLE(RESOURCE_LOAD_STATISTICS)
55 static bool shouldBlockCookies(WebFrame* frame, const URL& firstPartyForCookies, const URL& resourceURL, ShouldAskITP& shouldAskITPInNetworkProcess)
56 {
57     if (!WebCore::DeprecatedGlobalSettings::resourceLoadStatisticsEnabled())
58         return false;
59
60     if (frame && frame->isMainFrame())
61         return false;
62
63     RegistrableDomain firstPartyDomain { firstPartyForCookies };
64     if (firstPartyDomain.isEmpty())
65         return false;
66
67     RegistrableDomain resourceDomain { resourceURL };
68     if (resourceDomain.isEmpty())
69         return false;
70
71     if (firstPartyDomain == resourceDomain)
72         return false;
73
74     if (frame && frame->frameLoaderClient()->hasFrameSpecificStorageAccess())
75         return false;
76
77     if (frame && frame->page() && frame->page()->hasPageLevelStorageAccess(firstPartyDomain, resourceDomain))
78         return false;
79
80     // The WebContent process does not have enough information to deal with other policies than ThirdPartyCookieBlockingMode::All so we have to go to the NetworkProcess for all
81     // other policies and the request may end up getting blocked on NetworkProcess side.
82     if (WebProcess::singleton().thirdPartyCookieBlockingMode() != ThirdPartyCookieBlockingMode::All) {
83         shouldAskITPInNetworkProcess = ShouldAskITP::Yes;
84         return false;
85     }
86
87     return true;
88 }
89 #endif
90
91 String WebCookieJar::cookies(WebCore::Document& document, const URL& url) const
92 {
93     auto* webFrame = document.frame() ? WebFrame::fromCoreFrame(*document.frame()) : nullptr;
94     if (!webFrame || !webFrame->page())
95         return { };
96
97     ShouldAskITP shouldAskITPInNetworkProcess = ShouldAskITP::No;
98 #if ENABLE(RESOURCE_LOAD_STATISTICS)
99     if (shouldBlockCookies(webFrame, document.firstPartyForCookies(), url, shouldAskITPInNetworkProcess))
100         return { };
101 #endif
102
103     auto frameID = webFrame->frameID();
104     auto pageID = webFrame->page()->identifier();
105
106     String cookieString;
107     bool secureCookiesAccessed = false;
108     if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::CookiesForDOM(document.firstPartyForCookies(), sameSiteInfo(document), url, frameID, pageID, shouldIncludeSecureCookies(document, url), shouldAskITPInNetworkProcess), Messages::NetworkConnectionToWebProcess::CookiesForDOM::Reply(cookieString, secureCookiesAccessed), 0))
109         return { };
110
111     return cookieString;
112 }
113
114 void WebCookieJar::setCookies(WebCore::Document& document, const URL& url, const String& cookieString)
115 {
116     auto* webFrame = document.frame() ? WebFrame::fromCoreFrame(*document.frame()) : nullptr;
117     if (!webFrame || !webFrame->page())
118         return;
119
120     ShouldAskITP shouldAskITPInNetworkProcess = ShouldAskITP::No;
121 #if ENABLE(RESOURCE_LOAD_STATISTICS)
122     if (shouldBlockCookies(webFrame, document.firstPartyForCookies(), url, shouldAskITPInNetworkProcess))
123         return;
124 #endif
125
126     auto frameID = webFrame->frameID();
127     auto pageID = webFrame->page()->identifier();
128
129     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::SetCookiesFromDOM(document.firstPartyForCookies(), sameSiteInfo(document), url, frameID, pageID, shouldAskITPInNetworkProcess, cookieString), 0);
130 }
131
132 bool WebCookieJar::cookiesEnabled(const Document& document) const
133 {
134     auto* webFrame = document.frame() ? WebFrame::fromCoreFrame(*document.frame()) : nullptr;
135     if (!webFrame || !webFrame->page())
136         return false;
137
138 #if ENABLE(RESOURCE_LOAD_STATISTICS)
139     ShouldAskITP dummy;
140     if (shouldBlockCookies(webFrame, document.firstPartyForCookies(), document.cookieURL(), dummy))
141         return false;
142 #endif
143
144     return WebProcess::singleton().ensureNetworkProcessConnection().cookiesEnabled();
145 }
146
147 std::pair<String, WebCore::SecureCookiesAccessed> WebCookieJar::cookieRequestHeaderFieldValue(const URL& firstParty, const WebCore::SameSiteInfo& sameSiteInfo, const URL& url, Optional<FrameIdentifier> frameID, Optional<PageIdentifier> pageID, WebCore::IncludeSecureCookies includeSecureCookies) const
148 {
149     ShouldAskITP shouldAskITPInNetworkProcess = ShouldAskITP::No;
150 #if ENABLE(RESOURCE_LOAD_STATISTICS)
151     auto* webFrame = frameID ? WebProcess::singleton().webFrame(*frameID) : nullptr;
152     if (shouldBlockCookies(webFrame, firstParty, url, shouldAskITPInNetworkProcess))
153         return { };
154 #endif
155
156     String cookieString;
157     bool secureCookiesAccessed = false;
158     if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::CookieRequestHeaderFieldValue(firstParty, sameSiteInfo, url, frameID, pageID, includeSecureCookies, shouldAskITPInNetworkProcess), Messages::NetworkConnectionToWebProcess::CookieRequestHeaderFieldValue::Reply(cookieString, secureCookiesAccessed), 0))
159         return { };
160     return { cookieString, secureCookiesAccessed ? WebCore::SecureCookiesAccessed::Yes : WebCore::SecureCookiesAccessed::No };
161 }
162
163 bool WebCookieJar::getRawCookies(const WebCore::Document& document, const URL& url, Vector<WebCore::Cookie>& rawCookies) const
164 {
165     auto* webFrame = document.frame() ? WebFrame::fromCoreFrame(*document.frame()) : nullptr;
166     ShouldAskITP shouldAskITPInNetworkProcess = ShouldAskITP::No;
167 #if ENABLE(RESOURCE_LOAD_STATISTICS)
168     if (shouldBlockCookies(webFrame, document.firstPartyForCookies(), url, shouldAskITPInNetworkProcess))
169         return { };
170 #endif
171
172     Optional<FrameIdentifier> frameID = webFrame ? makeOptional(webFrame->frameID()) : WTF::nullopt;
173     Optional<PageIdentifier> pageID = webFrame && webFrame->page() ? makeOptional(webFrame->page()->identifier()) : WTF::nullopt;
174     if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::GetRawCookies(document.firstPartyForCookies(), sameSiteInfo(document), url, frameID, pageID, shouldAskITPInNetworkProcess), Messages::NetworkConnectionToWebProcess::GetRawCookies::Reply(rawCookies), 0))
175         return false;
176     return true;
177 }
178
179 void WebCookieJar::deleteCookie(const WebCore::Document& document, const URL& url, const String& cookieName)
180 {
181     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::DeleteCookie(url, cookieName), 0);
182 }
183
184 } // namespace WebKit