Move URL from WebCore to WTF
[WebKit-https.git] / Source / WebCore / platform / network / soup / NetworkStorageSessionSoup.cpp
1 /*
2  * Copyright (C) 2013 Apple Inc. All rights reserved.
3  * Copyright (C) 2013 University of Szeged. All rights reserved.
4  * Copyright (C) 2016 Igalia S.L.
5  * Copyright (C) 2017 Endless Mobile, Inc.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS''
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "NetworkStorageSession.h"
31
32 #if USE(SOUP)
33
34 #include "Cookie.h"
35 #include "CookieRequestHeaderFieldProxy.h"
36 #include "ResourceHandle.h"
37 #include "SoupNetworkSession.h"
38 #include <libsoup/soup.h>
39 #include <wtf/DateMath.h>
40 #include <wtf/MainThread.h>
41 #include <wtf/NeverDestroyed.h>
42 #include <wtf/glib/GUniquePtr.h>
43 #include <wtf/glib/GUniquePtrSoup.h>
44
45 #if USE(LIBSECRET)
46 #include "GRefPtrGtk.h"
47 #include <glib/gi18n-lib.h>
48 #define SECRET_WITH_UNSTABLE 1
49 #define SECRET_API_SUBJECT_TO_CHANGE 1
50 #include <libsecret/secret.h>
51 #endif
52
53 namespace WebCore {
54
55 NetworkStorageSession::NetworkStorageSession(PAL::SessionID sessionID, std::unique_ptr<SoupNetworkSession>&& session)
56     : m_sessionID(sessionID)
57     , m_session(WTFMove(session))
58 {
59     setCookieStorage(m_session ? m_session->cookieJar() : nullptr);
60 }
61
62 NetworkStorageSession::~NetworkStorageSession()
63 {
64     g_signal_handlers_disconnect_matched(m_cookieStorage.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
65 }
66
67 static std::unique_ptr<NetworkStorageSession>& defaultSession()
68 {
69     ASSERT(isMainThread());
70     static NeverDestroyed<std::unique_ptr<NetworkStorageSession>> session;
71     return session;
72 }
73
74 NetworkStorageSession& NetworkStorageSession::defaultStorageSession()
75 {
76     if (!defaultSession())
77         defaultSession() = std::make_unique<NetworkStorageSession>(PAL::SessionID::defaultSessionID(), nullptr);
78     return *defaultSession();
79 }
80
81 void NetworkStorageSession::ensureSession(PAL::SessionID sessionID, const String&)
82 {
83     ASSERT(!globalSessionMap().contains(sessionID));
84     globalSessionMap().add(sessionID, std::make_unique<NetworkStorageSession>(sessionID, std::make_unique<SoupNetworkSession>(sessionID)));
85 }
86
87 void NetworkStorageSession::switchToNewTestingSession()
88 {
89     defaultSession() = std::make_unique<NetworkStorageSession>(PAL::SessionID::defaultSessionID(), std::make_unique<SoupNetworkSession>());
90 }
91
92 SoupNetworkSession& NetworkStorageSession::getOrCreateSoupNetworkSession() const
93 {
94     if (!m_session)
95         m_session = std::make_unique<SoupNetworkSession>(m_sessionID, m_cookieStorage.get());
96     return *m_session;
97 }
98
99 void NetworkStorageSession::clearSoupNetworkSessionAndCookieStorage()
100 {
101     ASSERT(defaultSession().get() == this);
102     m_session = nullptr;
103     m_cookieObserverHandler = nullptr;
104     m_cookieStorage = nullptr;
105 }
106
107 void NetworkStorageSession::cookiesDidChange(NetworkStorageSession* session)
108 {
109     if (session->m_cookieObserverHandler)
110         session->m_cookieObserverHandler();
111 }
112
113 SoupCookieJar* NetworkStorageSession::cookieStorage() const
114 {
115     RELEASE_ASSERT(!m_session || m_session->cookieJar() == m_cookieStorage.get());
116     return m_cookieStorage.get();
117 }
118
119 void NetworkStorageSession::setCookieStorage(SoupCookieJar* jar)
120 {
121     if (m_cookieStorage)
122         g_signal_handlers_disconnect_matched(m_cookieStorage.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
123
124     // We always have a valid cookieStorage.
125     if (jar)
126         m_cookieStorage = jar;
127     else {
128         m_cookieStorage = adoptGRef(soup_cookie_jar_new());
129         soup_cookie_jar_set_accept_policy(m_cookieStorage.get(), SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY);
130     }
131     g_signal_connect_swapped(m_cookieStorage.get(), "changed", G_CALLBACK(cookiesDidChange), this);
132     if (m_session && m_session->cookieJar() != m_cookieStorage.get())
133         m_session->setCookieJar(m_cookieStorage.get());
134 }
135
136 void NetworkStorageSession::setCookieObserverHandler(Function<void ()>&& handler)
137 {
138     m_cookieObserverHandler = WTFMove(handler);
139 }
140
141 #if USE(LIBSECRET)
142 static const char* schemeFromProtectionSpaceServerType(ProtectionSpaceServerType serverType)
143 {
144     switch (serverType) {
145     case ProtectionSpaceServerHTTP:
146     case ProtectionSpaceProxyHTTP:
147         return SOUP_URI_SCHEME_HTTP;
148     case ProtectionSpaceServerHTTPS:
149     case ProtectionSpaceProxyHTTPS:
150         return SOUP_URI_SCHEME_HTTPS;
151     case ProtectionSpaceServerFTP:
152     case ProtectionSpaceProxyFTP:
153         return SOUP_URI_SCHEME_FTP;
154     case ProtectionSpaceServerFTPS:
155     case ProtectionSpaceProxySOCKS:
156         break;
157     }
158
159     ASSERT_NOT_REACHED();
160     return SOUP_URI_SCHEME_HTTP;
161 }
162
163 static const char* authTypeFromProtectionSpaceAuthenticationScheme(ProtectionSpaceAuthenticationScheme scheme)
164 {
165     switch (scheme) {
166     case ProtectionSpaceAuthenticationSchemeDefault:
167     case ProtectionSpaceAuthenticationSchemeHTTPBasic:
168         return "Basic";
169     case ProtectionSpaceAuthenticationSchemeHTTPDigest:
170         return "Digest";
171     case ProtectionSpaceAuthenticationSchemeNTLM:
172         return "NTLM";
173     case ProtectionSpaceAuthenticationSchemeNegotiate:
174         return "Negotiate";
175     case ProtectionSpaceAuthenticationSchemeHTMLForm:
176     case ProtectionSpaceAuthenticationSchemeClientCertificateRequested:
177     case ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested:
178         ASSERT_NOT_REACHED();
179         break;
180     case ProtectionSpaceAuthenticationSchemeOAuth:
181         return "OAuth";
182     case ProtectionSpaceAuthenticationSchemeUnknown:
183         return "unknown";
184     }
185
186     ASSERT_NOT_REACHED();
187     return "unknown";
188 }
189
190 struct SecretServiceSearchData {
191     SecretServiceSearchData(GCancellable* cancellable, Function<void (Credential&&)>&& completionHandler)
192         : cancellable(cancellable)
193         , completionHandler(WTFMove(completionHandler))
194     {
195     }
196
197     ~SecretServiceSearchData() = default;
198
199     GRefPtr<GCancellable> cancellable;
200     Function<void (Credential&&)> completionHandler;
201 };
202 #endif // USE(LIBSECRET)
203
204 void NetworkStorageSession::getCredentialFromPersistentStorage(const ProtectionSpace& protectionSpace, GCancellable* cancellable, Function<void (Credential&&)>&& completionHandler)
205 {
206 #if USE(LIBSECRET)
207     if (m_sessionID.isEphemeral()) {
208         completionHandler({ });
209         return;
210     }
211
212     const String& realm = protectionSpace.realm();
213     if (realm.isEmpty()) {
214         completionHandler({ });
215         return;
216     }
217
218     GRefPtr<GHashTable> attributes = adoptGRef(secret_attributes_build(SECRET_SCHEMA_COMPAT_NETWORK,
219         "domain", realm.utf8().data(),
220         "server", protectionSpace.host().utf8().data(),
221         "port", protectionSpace.port(),
222         "protocol", schemeFromProtectionSpaceServerType(protectionSpace.serverType()),
223         "authtype", authTypeFromProtectionSpaceAuthenticationScheme(protectionSpace.authenticationScheme()),
224         nullptr));
225     if (!attributes) {
226         completionHandler({ });
227         return;
228     }
229
230     auto data = std::make_unique<SecretServiceSearchData>(cancellable, WTFMove(completionHandler));
231     secret_service_search(nullptr, SECRET_SCHEMA_COMPAT_NETWORK, attributes.get(),
232         static_cast<SecretSearchFlags>(SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS), cancellable,
233         [](GObject* source, GAsyncResult* result, gpointer userData) {
234             auto data = std::unique_ptr<SecretServiceSearchData>(static_cast<SecretServiceSearchData*>(userData));
235             GUniqueOutPtr<GError> error;
236             GUniquePtr<GList> elements(secret_service_search_finish(SECRET_SERVICE(source), result, &error.outPtr()));
237             if (g_cancellable_is_cancelled(data->cancellable.get()) || error || !elements || !elements->data) {
238                 data->completionHandler({ });
239                 return;
240             }
241
242             GRefPtr<SecretItem> secretItem = static_cast<SecretItem*>(elements->data);
243             g_list_foreach(elements.get(), reinterpret_cast<GFunc>(reinterpret_cast<GCallback>(g_object_unref)), nullptr);
244             GRefPtr<GHashTable> attributes = adoptGRef(secret_item_get_attributes(secretItem.get()));
245             String user = String::fromUTF8(static_cast<const char*>(g_hash_table_lookup(attributes.get(), "user")));
246             if (user.isEmpty()) {
247                 data->completionHandler({ });
248                 return;
249             }
250
251             size_t length;
252             GRefPtr<SecretValue> secretValue = adoptGRef(secret_item_get_secret(secretItem.get()));
253             const char* passwordData = secret_value_get(secretValue.get(), &length);
254             data->completionHandler(Credential(user, String::fromUTF8(passwordData, length), CredentialPersistencePermanent));
255         }, data.release());
256 #else
257     UNUSED_PARAM(protectionSpace);
258     UNUSED_PARAM(cancellable);
259     completionHandler({ });
260 #endif
261 }
262
263 void NetworkStorageSession::saveCredentialToPersistentStorage(const ProtectionSpace& protectionSpace, const Credential& credential)
264 {
265 #if USE(LIBSECRET)
266     if (m_sessionID.isEphemeral())
267         return;
268
269     if (credential.isEmpty())
270         return;
271
272     const String& realm = protectionSpace.realm();
273     if (realm.isEmpty())
274         return;
275
276     GRefPtr<GHashTable> attributes = adoptGRef(secret_attributes_build(SECRET_SCHEMA_COMPAT_NETWORK,
277         "domain", realm.utf8().data(),
278         "server", protectionSpace.host().utf8().data(),
279         "port", protectionSpace.port(),
280         "protocol", schemeFromProtectionSpaceServerType(protectionSpace.serverType()),
281         "authtype", authTypeFromProtectionSpaceAuthenticationScheme(protectionSpace.authenticationScheme()),
282         nullptr));
283     if (!attributes)
284         return;
285
286     g_hash_table_insert(attributes.get(), g_strdup("user"), g_strdup(credential.user().utf8().data()));
287     CString utf8Password = credential.password().utf8();
288     GRefPtr<SecretValue> newSecretValue = adoptGRef(secret_value_new(utf8Password.data(), utf8Password.length(), "text/plain"));
289     secret_service_store(nullptr, SECRET_SCHEMA_COMPAT_NETWORK, attributes.get(), SECRET_COLLECTION_DEFAULT, _("WebKitGTK+ password"),
290         newSecretValue.get(), nullptr, nullptr, nullptr);
291 #else
292     UNUSED_PARAM(protectionSpace);
293     UNUSED_PARAM(credential);
294 #endif
295 }
296
297 bool NetworkStorageSession::cookiesEnabled() const
298 {
299     auto policy = soup_cookie_jar_get_accept_policy(cookieStorage());
300     return policy == SOUP_COOKIE_JAR_ACCEPT_ALWAYS || policy == SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY;
301 }
302
303 static inline bool httpOnlyCookieExists(const GSList* cookies, const gchar* name, const gchar* path)
304 {
305     for (const GSList* iter = cookies; iter; iter = g_slist_next(iter)) {
306         SoupCookie* cookie = static_cast<SoupCookie*>(iter->data);
307         if (!strcmp(soup_cookie_get_name(cookie), name) 
308             && !g_strcmp0(soup_cookie_get_path(cookie), path)) {
309             if (soup_cookie_get_http_only(cookie))
310                 return true;
311             break;
312         }
313     }
314     return false;
315 }
316
317 void NetworkStorageSession::setCookiesFromDOM(const URL& firstParty, const SameSiteInfo&, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, const String& value) const
318 {
319     UNUSED_PARAM(frameID);
320     UNUSED_PARAM(pageID);
321     GUniquePtr<SoupURI> origin = url.createSoupURI();
322     if (!origin)
323         return;
324
325     GUniquePtr<SoupURI> firstPartyURI = firstParty.createSoupURI();
326     if (!firstPartyURI)
327         return;
328
329     // Get existing cookies for this origin.
330     SoupCookieJar* jar = cookieStorage();
331     GSList* existingCookies = soup_cookie_jar_get_cookie_list(jar, origin.get(), TRUE);
332
333     for (auto& cookieString : value.split('\n')) {
334         GUniquePtr<SoupCookie> cookie(soup_cookie_parse(cookieString.utf8().data(), origin.get()));
335
336         if (!cookie)
337             continue;
338
339         // Make sure the cookie is not httpOnly since such cookies should not be set from JavaScript.
340         if (soup_cookie_get_http_only(cookie.get()))
341             continue;
342
343         // Make sure we do not overwrite httpOnly cookies from JavaScript.
344         if (httpOnlyCookieExists(existingCookies, soup_cookie_get_name(cookie.get()), soup_cookie_get_path(cookie.get())))
345             continue;
346
347         soup_cookie_jar_add_cookie_with_first_party(jar, firstPartyURI.get(), cookie.release());
348     }
349
350     soup_cookies_free(existingCookies);
351 }
352
353 void NetworkStorageSession::setCookies(const Vector<Cookie>& cookies, const URL&, const URL&)
354 {
355     for (auto cookie : cookies)
356         soup_cookie_jar_add_cookie(cookieStorage(), cookie.toSoupCookie());
357 }
358
359 void NetworkStorageSession::setCookie(const Cookie& cookie)
360 {
361     soup_cookie_jar_add_cookie(cookieStorage(), cookie.toSoupCookie());
362 }
363
364 void NetworkStorageSession::deleteCookie(const Cookie& cookie)
365 {
366     GUniquePtr<SoupCookie> targetCookie(cookie.toSoupCookie());
367     soup_cookie_jar_delete_cookie(cookieStorage(), targetCookie.get());
368 }
369
370 void NetworkStorageSession::deleteCookie(const URL& url, const String& name) const
371 {
372     GUniquePtr<SoupURI> uri = url.createSoupURI();
373     if (!uri)
374         return;
375
376     SoupCookieJar* jar = cookieStorage();
377     GUniquePtr<GSList> cookies(soup_cookie_jar_get_cookie_list(jar, uri.get(), TRUE));
378     if (!cookies)
379         return;
380
381     CString cookieName = name.utf8();
382     bool wasDeleted = false;
383     for (GSList* iter = cookies.get(); iter; iter = g_slist_next(iter)) {
384         SoupCookie* cookie = static_cast<SoupCookie*>(iter->data);
385         if (!wasDeleted && cookieName == cookie->name) {
386             soup_cookie_jar_delete_cookie(jar, cookie);
387             wasDeleted = true;
388         }
389         soup_cookie_free(cookie);
390     }
391 }
392
393 void NetworkStorageSession::deleteAllCookies()
394 {
395     SoupCookieJar* cookieJar = cookieStorage();
396     GUniquePtr<GSList> cookies(soup_cookie_jar_all_cookies(cookieJar));
397     for (GSList* item = cookies.get(); item; item = g_slist_next(item)) {
398         SoupCookie* cookie = static_cast<SoupCookie*>(item->data);
399         soup_cookie_jar_delete_cookie(cookieJar, cookie);
400         soup_cookie_free(cookie);
401     }
402 }
403
404 void NetworkStorageSession::deleteAllCookiesModifiedSince(WallTime timestamp)
405 {
406     // FIXME: Add support for deleting cookies modified since the given timestamp. It should probably be added to libsoup.
407     if (timestamp == WallTime::fromRawSeconds(0))
408         deleteAllCookies();
409     else
410         g_warning("Deleting cookies modified since a given time span is not supported yet");
411 }
412
413 void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& hostnames)
414 {
415     SoupCookieJar* cookieJar = cookieStorage();
416
417     for (const auto& hostname : hostnames) {
418         CString hostNameString = hostname.utf8();
419
420         GUniquePtr<GSList> cookies(soup_cookie_jar_all_cookies(cookieJar));
421         for (GSList* item = cookies.get(); item; item = g_slist_next(item)) {
422             SoupCookie* cookie = static_cast<SoupCookie*>(item->data);
423             if (soup_cookie_domain_matches(cookie, hostNameString.data()))
424                 soup_cookie_jar_delete_cookie(cookieJar, cookie);
425             soup_cookie_free(cookie);
426         }
427     }
428 }
429
430 void NetworkStorageSession::getHostnamesWithCookies(HashSet<String>& hostnames)
431 {
432     GUniquePtr<GSList> cookies(soup_cookie_jar_all_cookies(cookieStorage()));
433     for (GSList* item = cookies.get(); item; item = g_slist_next(item)) {
434         SoupCookie* cookie = static_cast<SoupCookie*>(item->data);
435         if (cookie->domain)
436             hostnames.add(String::fromUTF8(cookie->domain));
437         soup_cookie_free(cookie);
438     }
439 }
440
441 Vector<Cookie> NetworkStorageSession::getAllCookies()
442 {
443     // FIXME: Implement for WK2 to use.
444     return { };
445 }
446
447 Vector<Cookie> NetworkStorageSession::getCookies(const URL& url)
448 {
449     Vector<Cookie> cookies;
450     GUniquePtr<SoupURI> uri = url.createSoupURI();
451     if (!uri)
452         return cookies;
453
454     GUniquePtr<GSList> cookiesList(soup_cookie_jar_get_cookie_list(cookieStorage(), uri.get(), TRUE));
455     for (GSList* item = cookiesList.get(); item; item = g_slist_next(item)) {
456         GUniquePtr<SoupCookie> soupCookie(static_cast<SoupCookie*>(item->data));
457         cookies.append(WebCore::Cookie(soupCookie.get()));
458     }
459
460     return cookies;
461 }
462
463 bool NetworkStorageSession::getRawCookies(const URL& firstParty, const SameSiteInfo&, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>& rawCookies) const
464 {
465     UNUSED_PARAM(firstParty);
466     UNUSED_PARAM(frameID);
467     UNUSED_PARAM(pageID);
468     rawCookies.clear();
469     GUniquePtr<SoupURI> uri = url.createSoupURI();
470     if (!uri)
471         return false;
472
473     GUniquePtr<GSList> cookies(soup_cookie_jar_get_cookie_list(cookieStorage(), uri.get(), TRUE));
474     if (!cookies)
475         return false;
476
477     for (GSList* iter = cookies.get(); iter; iter = g_slist_next(iter)) {
478         SoupCookie* soupCookie = static_cast<SoupCookie*>(iter->data);
479         Cookie cookie;
480         cookie.name = String::fromUTF8(soupCookie->name);
481         cookie.value = String::fromUTF8(soupCookie->value);
482         cookie.domain = String::fromUTF8(soupCookie->domain);
483         cookie.path = String::fromUTF8(soupCookie->path);
484         cookie.created = 0;
485         cookie.expires = soupCookie->expires ? static_cast<double>(soup_date_to_time_t(soupCookie->expires)) * 1000 : 0;
486         cookie.httpOnly = soupCookie->http_only;
487         cookie.secure = soupCookie->secure;
488         cookie.session = !soupCookie->expires;
489         rawCookies.append(WTFMove(cookie));
490         soup_cookie_free(soupCookie);
491     }
492
493     return true;
494 }
495
496 static std::pair<String, bool> cookiesForSession(const NetworkStorageSession& session, const URL& url, bool forHTTPHeader, IncludeSecureCookies includeSecureCookies)
497 {
498     GUniquePtr<SoupURI> uri = url.createSoupURI();
499     if (!uri)
500         return { { }, false };
501
502     GSList* cookies = soup_cookie_jar_get_cookie_list(session.cookieStorage(), uri.get(), forHTTPHeader);
503     bool didAccessSecureCookies = false;
504
505     // libsoup should omit secure cookies itself if the protocol is not https.
506     if (url.protocolIs("https")) {
507         GSList* item = cookies;
508         while (item) {
509             auto cookie = static_cast<SoupCookie*>(item->data);
510             if (soup_cookie_get_secure(cookie)) {
511                 didAccessSecureCookies = true;
512                 if (includeSecureCookies == IncludeSecureCookies::No) {
513                     GSList* next = item->next;
514                     soup_cookie_free(static_cast<SoupCookie*>(item->data));
515                     cookies = g_slist_remove_link(cookies, item);
516                     item = next;
517                     continue;
518                 }
519             }
520             item = item->next;
521         }
522     }
523
524     if (!cookies)
525         return { { }, false };
526
527     GUniquePtr<char> cookieHeader(soup_cookies_to_cookie_header(cookies));
528     soup_cookies_free(cookies);
529
530     return { String::fromUTF8(cookieHeader.get()), didAccessSecureCookies };
531 }
532
533 std::pair<String, bool> NetworkStorageSession::cookiesForDOM(const URL& firstParty, const SameSiteInfo&, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies includeSecureCookies) const
534 {
535     UNUSED_PARAM(firstParty);
536     UNUSED_PARAM(frameID);
537     UNUSED_PARAM(pageID);
538     return cookiesForSession(*this, url, false, includeSecureCookies);
539 }
540
541 std::pair<String, bool> NetworkStorageSession::cookieRequestHeaderFieldValue(const URL& firstParty, const SameSiteInfo&, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies includeSecureCookies) const
542 {
543     UNUSED_PARAM(firstParty);
544     UNUSED_PARAM(frameID);
545     UNUSED_PARAM(pageID);
546     // Secure cookies will still only be included if url's protocol is https.
547     return cookiesForSession(*this, url, true, includeSecureCookies);
548 }
549
550 std::pair<String, bool> NetworkStorageSession::cookieRequestHeaderFieldValue(const CookieRequestHeaderFieldProxy& headerFieldProxy) const
551 {
552     return cookieRequestHeaderFieldValue(headerFieldProxy.firstParty, headerFieldProxy.sameSiteInfo, headerFieldProxy.url, headerFieldProxy.frameID, headerFieldProxy.pageID, headerFieldProxy.includeSecureCookies);
553 }
554
555 void NetworkStorageSession::flushCookieStore()
556 {
557     // FIXME: Implement for WK2 to use.
558 }
559
560 } // namespace WebCore
561
562 #endif // USE(SOUP)