Changeset 248640 in webkit


Ignore:
Timestamp:
Aug 13, 2019 3:34:29 PM (5 years ago)
Author:
wilander@apple.com
Message:

Resource Load Statistics: Switch NSURLSession on top navigation to prevalent resource with user interaction
https://bugs.webkit.org/show_bug.cgi?id=200642
<rdar://problem/53962073>

Reviewed by Alex Christensen.

Source/WebCore:

Tests: http/tests/resourceLoadStatistics/do-not-switch-session-on-navigation-to-prevalent-without-interaction.html

http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction.html

This patch splits m_registrableDomainsToBlockCookieFor in WebCore:NetworkStorageSession into:

  • m_registrableDomainsToBlockAndDeleteCookiesFor
  • m_registrableDomainsToBlockButKeepCookiesFor

... to support different network load policies based on this distinction.

  • page/RuntimeEnabledFeatures.h:

(WebCore::RuntimeEnabledFeatures::setITPSessionSwitchingEnabled):
(WebCore::RuntimeEnabledFeatures::itpSessionSwitchingEnabled const):

  • page/Settings.yaml:
  • platform/network/NetworkStorageSession.cpp:

(WebCore::NetworkStorageSession::shouldBlockThirdPartyCookies const):
(WebCore::NetworkStorageSession::shouldBlockThirdPartyCookiesButKeepFirstPartyCookiesFor const):
(WebCore::NetworkStorageSession::setPrevalentDomainsToBlockAndDeleteCookiesFor):
(WebCore::NetworkStorageSession::setPrevalentDomainsToBlockButKeepCookiesFor):
(WebCore::NetworkStorageSession::removePrevalentDomains):
(WebCore::NetworkStorageSession::setPrevalentDomainsToBlockCookiesFor): Deleted.

  • platform/network/NetworkStorageSession.h:

Source/WebKit:

Since prevalent resources with user interaction get to keep their cookies and website
data, we should use a different NSURLSessions for when they are first-party websites
and have access to that data. This patch achieves that.

The WebKit::NetworkDataTaskCocoa constructor now checks with the network storage session
if the first party for this load should be isolated. The category for which this is true
is checked in the new function
WebCore:NetworkStorageSession::shouldBlockThirdPartyCookiesButKeepFirstPartyCookiesFor()
which in turn is backed by a new split of m_registrableDomainsToBlockCookieFor into:

  • m_registrableDomainsToBlockAndDeleteCookiesFor
  • m_registrableDomainsToBlockButKeepCookiesFor

... in WebCore:NetworkStorageSession.

Non-isolated sessions are now picked up through the convenience function
WebKit::NetworkSessionCocoa::session() whereas isolated sessions are created lazily and
picked up through WebKit::NetworkSessionCocoa::isolatedSession().

The number of isolated NSURLSessions in memory is capped to 10. When the cap is hit,
the session that's been unused the longest is aged out.

The C API changes are test infrastructure.

  • NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:

(WebKit::ResourceLoadStatisticsDatabaseStore::clear):
(WebKit::ResourceLoadStatisticsDatabaseStore::domainsToBlockAndDeleteCookiesFor const):
(WebKit::ResourceLoadStatisticsDatabaseStore::domainsToBlockButKeepCookiesFor const):
(WebKit::ResourceLoadStatisticsDatabaseStore::updateCookieBlocking):
(WebKit::ResourceLoadStatisticsDatabaseStore::domainsToBlock const): Deleted.

  • NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
  • NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp:

(WebKit::ResourceLoadStatisticsMemoryStore::clear):
(WebKit::ResourceLoadStatisticsMemoryStore::updateCookieBlocking):

  • NetworkProcess/Classifier/ResourceLoadStatisticsStore.cpp:

(WebKit::ResourceLoadStatisticsStore::updateCookieBlockingForDomains):
(WebKit::ResourceLoadStatisticsStore::debugLogDomainsInBatches):

  • NetworkProcess/Classifier/ResourceLoadStatisticsStore.h:
  • NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:

(WebKit::WebResourceLoadStatisticsStore::callUpdatePrevalentDomainsToBlockCookiesForHandler):
(WebKit::WebResourceLoadStatisticsStore::scheduleCookieBlockingUpdateForDomains): Deleted.
(WebKit::WebResourceLoadStatisticsStore::scheduleClearBlockingStateForDomains): Deleted.

Dead code.

  • NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:

(WebKit::RegistrableDomainsToBlockCookiesFor::isolatedCopy const):

  • NetworkProcess/NetworkProcess.cpp:

(WebKit::NetworkProcess::updatePrevalentDomainsToBlockCookiesFor):
(WebKit::NetworkProcess::scheduleClearInMemoryAndPersistent):
(WebKit::NetworkProcess::hasIsolatedSession const):

  • NetworkProcess/NetworkProcess.h:
  • NetworkProcess/NetworkProcess.messages.in:
  • NetworkProcess/NetworkSession.h:

(WebKit::NetworkSession::shouldIsolateSessionsForPrevalentTopFrames const):
(WebKit::NetworkSession::hasIsolatedSession const):
(WebKit::NetworkSession::clearIsolatedSessions):

  • NetworkProcess/NetworkSessionCreationParameters.cpp:

(WebKit::NetworkSessionCreationParameters::encode const):
(WebKit::NetworkSessionCreationParameters::decode):

  • NetworkProcess/NetworkSessionCreationParameters.h:
  • NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:

(WebKit::NetworkDataTaskCocoa::NetworkDataTaskCocoa):

  • NetworkProcess/cocoa/NetworkSessionCocoa.h:
  • NetworkProcess/cocoa/NetworkSessionCocoa.mm:

(WebKit::NetworkSessionCocoa::NetworkSessionCocoa):
(WebKit::NetworkSessionCocoa::session):
(WebKit::NetworkSessionCocoa::isolatedSession):
(WebKit::NetworkSessionCocoa::hasIsolatedSession const):
(WebKit::NetworkSessionCocoa::clearIsolatedSessions):
(WebKit::NetworkSessionCocoa::invalidateAndCancel):
(WebKit::NetworkSessionCocoa::clearCredentials):

  • Shared/WebPreferences.yaml:
  • UIProcess/API/C/WKWebsiteDataStoreRef.cpp:

(WKWebsiteDataStoreStatisticsHasIsolatedSession):

  • UIProcess/API/C/WKWebsiteDataStoreRef.h:
  • UIProcess/Network/NetworkProcessProxy.cpp:

(WebKit::NetworkProcessProxy::hasIsolatedSession):

  • UIProcess/Network/NetworkProcessProxy.h:
  • UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:

(WebKit::WebsiteDataStore::parameters):

  • UIProcess/WebsiteData/WebsiteDataStore.cpp:

(WebKit::WebsiteDataStore::hasLocalStorageForTesting const):
(WebKit::WebsiteDataStore::hasIsolatedSessionForTesting const):

  • UIProcess/WebsiteData/WebsiteDataStore.h:

Tools:

This patch adds test infrastructure to query whether an origin has an
isolated NSURLSession or not.

  • WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
  • WebKitTestRunner/InjectedBundle/TestRunner.cpp:

(WTR::TestRunner::hasStatisticsIsolatedSession):

  • WebKitTestRunner/InjectedBundle/TestRunner.h:
  • WebKitTestRunner/TestController.cpp:

(WTR::TestController::hasStatisticsIsolatedSession):

  • WebKitTestRunner/TestController.h:
  • WebKitTestRunner/TestInvocation.cpp:

(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):

LayoutTests:

  • http/tests/resourceLoadStatistics/do-not-switch-session-on-navigation-to-prevalent-without-interaction-expected.txt: Added.
  • http/tests/resourceLoadStatistics/do-not-switch-session-on-navigation-to-prevalent-without-interaction.html: Added.
  • http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction-expected.txt: Added.
  • http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction.html: Added.
Location:
trunk
Files:
4 added
38 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r248639 r248640  
     12019-08-13  John Wilander  <wilander@apple.com>
     2
     3        Resource Load Statistics: Switch NSURLSession on top navigation to prevalent resource with user interaction
     4        https://bugs.webkit.org/show_bug.cgi?id=200642
     5        <rdar://problem/53962073>
     6
     7        Reviewed by Alex Christensen.
     8
     9        * http/tests/resourceLoadStatistics/do-not-switch-session-on-navigation-to-prevalent-without-interaction-expected.txt: Added.
     10        * http/tests/resourceLoadStatistics/do-not-switch-session-on-navigation-to-prevalent-without-interaction.html: Added.
     11        * http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction-expected.txt: Added.
     12        * http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction.html: Added.
     13
    1142019-08-13  Ryan Haddad  <ryanhaddad@apple.com>
    215
  • trunk/Source/WebCore/ChangeLog

    r248635 r248640  
     12019-08-13  John Wilander  <wilander@apple.com>
     2
     3        Resource Load Statistics: Switch NSURLSession on top navigation to prevalent resource with user interaction
     4        https://bugs.webkit.org/show_bug.cgi?id=200642
     5        <rdar://problem/53962073>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Tests: http/tests/resourceLoadStatistics/do-not-switch-session-on-navigation-to-prevalent-without-interaction.html
     10               http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction.html
     11
     12        This patch splits m_registrableDomainsToBlockCookieFor in WebCore:NetworkStorageSession into:
     13        - m_registrableDomainsToBlockAndDeleteCookiesFor
     14        - m_registrableDomainsToBlockButKeepCookiesFor
     15        ... to support different network load policies based on this distinction.
     16
     17        * page/RuntimeEnabledFeatures.h:
     18        (WebCore::RuntimeEnabledFeatures::setITPSessionSwitchingEnabled):
     19        (WebCore::RuntimeEnabledFeatures::itpSessionSwitchingEnabled const):
     20        * page/Settings.yaml:
     21        * platform/network/NetworkStorageSession.cpp:
     22        (WebCore::NetworkStorageSession::shouldBlockThirdPartyCookies const):
     23        (WebCore::NetworkStorageSession::shouldBlockThirdPartyCookiesButKeepFirstPartyCookiesFor const):
     24        (WebCore::NetworkStorageSession::setPrevalentDomainsToBlockAndDeleteCookiesFor):
     25        (WebCore::NetworkStorageSession::setPrevalentDomainsToBlockButKeepCookiesFor):
     26        (WebCore::NetworkStorageSession::removePrevalentDomains):
     27        (WebCore::NetworkStorageSession::setPrevalentDomainsToBlockCookiesFor): Deleted.
     28        * platform/network/NetworkStorageSession.h:
     29
    1302019-08-13  Zalan Bujtas  <zalan@apple.com>
    231
  • trunk/Source/WebCore/page/RuntimeEnabledFeatures.h

    r248409 r248640  
    147147    void setIsITPDatabaseEnabled(bool isEnabled) { m_isITPDatabaseEnabled = isEnabled; }
    148148    bool isITPDatabaseEnabled() const { return m_isITPDatabaseEnabled; }
     149
     150    void setIsITPSessionSwitchingEnabled(bool isEnabled) { m_isITPSessionSwitchingEnabled = isEnabled; }
     151    bool isITPSessionSwitchingEnabled() const { return m_isITPSessionSwitchingEnabled; }
    149152
    150153    void setRestrictedHTTPResponseAccess(bool isEnabled) { m_isRestrictedHTTPResponseAccess = isEnabled; }
     
    411414    bool m_ariaReflectionEnabled { true };
    412415    bool m_itpDebugMode { false };
     416    bool m_isITPSessionSwitchingEnabled { true };
    413417    bool m_isRestrictedHTTPResponseAccess { true };
    414418    bool m_crossOriginResourcePolicyEnabled { true };
  • trunk/Source/WebCore/page/Settings.yaml

    r247530 r248640  
    862862  inspectorOverride: true
    863863
     864isITPSessionSwitchingEnabled:
     865  initial: true
     866
    864867# Deprecated
    865868
  • trunk/Source/WebCore/platform/network/NetworkStorageSession.cpp

    r245796 r248640  
    6464        return false;
    6565
    66     return m_registrableDomainsToBlockCookieFor.contains(registrableDomain);
     66    ASSERT(!(m_registrableDomainsToBlockAndDeleteCookiesFor.contains(registrableDomain) && m_registrableDomainsToBlockButKeepCookiesFor.contains(registrableDomain)));
     67
     68    return m_registrableDomainsToBlockAndDeleteCookiesFor.contains(registrableDomain)
     69        || m_registrableDomainsToBlockButKeepCookiesFor.contains(registrableDomain);
     70}
     71
     72bool NetworkStorageSession::shouldBlockThirdPartyCookiesButKeepFirstPartyCookiesFor(const RegistrableDomain& registrableDomain) const
     73{
     74    if (registrableDomain.isEmpty())
     75        return false;
     76
     77    ASSERT(!(m_registrableDomainsToBlockAndDeleteCookiesFor.contains(registrableDomain) && m_registrableDomainsToBlockButKeepCookiesFor.contains(registrableDomain)));
     78
     79    return m_registrableDomainsToBlockButKeepCookiesFor.contains(registrableDomain);
    6780}
    6881
     
    104117}
    105118
    106 void NetworkStorageSession::setPrevalentDomainsToBlockCookiesFor(const Vector<RegistrableDomain>& domains)
    107 {
    108     m_registrableDomainsToBlockCookieFor.clear();
    109     m_registrableDomainsToBlockCookieFor.add(domains.begin(), domains.end());
     119void NetworkStorageSession::setPrevalentDomainsToBlockAndDeleteCookiesFor(const Vector<RegistrableDomain>& domains)
     120{
     121    m_registrableDomainsToBlockAndDeleteCookiesFor.clear();
     122    m_registrableDomainsToBlockAndDeleteCookiesFor.add(domains.begin(), domains.end());
     123}
     124
     125void NetworkStorageSession::setPrevalentDomainsToBlockButKeepCookiesFor(const Vector<RegistrableDomain>& domains)
     126{
     127    m_registrableDomainsToBlockButKeepCookiesFor.clear();
     128    m_registrableDomainsToBlockButKeepCookiesFor.add(domains.begin(), domains.end());
    110129}
    111130
    112131void NetworkStorageSession::removePrevalentDomains(const Vector<RegistrableDomain>& domains)
    113132{
    114     for (auto& domain : domains)
    115         m_registrableDomainsToBlockCookieFor.remove(domain);
     133    for (auto& domain : domains) {
     134        m_registrableDomainsToBlockAndDeleteCookiesFor.remove(domain);
     135        m_registrableDomainsToBlockButKeepCookiesFor.remove(domain);
     136    }
    116137}
    117138
  • trunk/Source/WebCore/platform/network/NetworkStorageSession.h

    r248010 r248640  
    144144    WEBCORE_EXPORT bool shouldBlockCookies(const URL& firstPartyForCookies, const URL& resource, Optional<uint64_t> frameID, Optional<PageIdentifier>) const;
    145145    WEBCORE_EXPORT bool shouldBlockThirdPartyCookies(const RegistrableDomain&) const;
    146     WEBCORE_EXPORT void setPrevalentDomainsToBlockCookiesFor(const Vector<RegistrableDomain>&);
     146    WEBCORE_EXPORT bool shouldBlockThirdPartyCookiesButKeepFirstPartyCookiesFor(const RegistrableDomain&) const;
     147    WEBCORE_EXPORT void setPrevalentDomainsToBlockAndDeleteCookiesFor(const Vector<RegistrableDomain>&);
     148    WEBCORE_EXPORT void setPrevalentDomainsToBlockButKeepCookiesFor(const Vector<RegistrableDomain>&);
    147149    WEBCORE_EXPORT void setAgeCapForClientSideCookies(Optional<Seconds>);
    148150    WEBCORE_EXPORT void removePrevalentDomains(const Vector<RegistrableDomain>& domains);
     
    182184#if ENABLE(RESOURCE_LOAD_STATISTICS)
    183185    Optional<Seconds> clientSideCookieCap(const RegistrableDomain& firstParty, Optional<PageIdentifier>) const;
    184     HashSet<RegistrableDomain> m_registrableDomainsToBlockCookieFor;
     186    HashSet<RegistrableDomain> m_registrableDomainsToBlockAndDeleteCookiesFor;
     187    HashSet<RegistrableDomain> m_registrableDomainsToBlockButKeepCookiesFor;
    185188    HashMap<PageIdentifier, HashMap<uint64_t, RegistrableDomain, DefaultHash<uint64_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>> m_framesGrantedStorageAccess;
    186189    HashMap<PageIdentifier, HashMap<RegistrableDomain, RegistrableDomain>> m_pagesGrantedStorageAccess;
  • trunk/Source/WebKit/ChangeLog

    r248634 r248640  
     12019-08-13  John Wilander  <wilander@apple.com>
     2
     3        Resource Load Statistics: Switch NSURLSession on top navigation to prevalent resource with user interaction
     4        https://bugs.webkit.org/show_bug.cgi?id=200642
     5        <rdar://problem/53962073>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Since prevalent resources with user interaction get to keep their cookies and website
     10        data, we should use a different NSURLSessions for when they are first-party websites
     11        and have access to that data. This patch achieves that.
     12
     13        The WebKit::NetworkDataTaskCocoa constructor now checks with the network storage session
     14        if the first party for this load should be isolated. The category for which this is true
     15        is checked in the new function
     16        WebCore:NetworkStorageSession::shouldBlockThirdPartyCookiesButKeepFirstPartyCookiesFor()
     17        which in turn is backed by a new split of m_registrableDomainsToBlockCookieFor into:
     18        - m_registrableDomainsToBlockAndDeleteCookiesFor
     19        - m_registrableDomainsToBlockButKeepCookiesFor
     20        ... in WebCore:NetworkStorageSession.
     21
     22        Non-isolated sessions are now picked up through the convenience function
     23        WebKit::NetworkSessionCocoa::session() whereas isolated sessions are created lazily and
     24        picked up through WebKit::NetworkSessionCocoa::isolatedSession().
     25
     26        The number of isolated NSURLSessions in memory is capped to 10. When the cap is hit,
     27        the session that's been unused the longest is aged out.
     28
     29        The C API changes are test infrastructure.
     30
     31        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
     32        (WebKit::ResourceLoadStatisticsDatabaseStore::clear):
     33        (WebKit::ResourceLoadStatisticsDatabaseStore::domainsToBlockAndDeleteCookiesFor const):
     34        (WebKit::ResourceLoadStatisticsDatabaseStore::domainsToBlockButKeepCookiesFor const):
     35        (WebKit::ResourceLoadStatisticsDatabaseStore::updateCookieBlocking):
     36        (WebKit::ResourceLoadStatisticsDatabaseStore::domainsToBlock const): Deleted.
     37        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
     38        * NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp:
     39        (WebKit::ResourceLoadStatisticsMemoryStore::clear):
     40        (WebKit::ResourceLoadStatisticsMemoryStore::updateCookieBlocking):
     41        * NetworkProcess/Classifier/ResourceLoadStatisticsStore.cpp:
     42        (WebKit::ResourceLoadStatisticsStore::updateCookieBlockingForDomains):
     43        (WebKit::ResourceLoadStatisticsStore::debugLogDomainsInBatches):
     44        * NetworkProcess/Classifier/ResourceLoadStatisticsStore.h:
     45        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
     46        (WebKit::WebResourceLoadStatisticsStore::callUpdatePrevalentDomainsToBlockCookiesForHandler):
     47        (WebKit::WebResourceLoadStatisticsStore::scheduleCookieBlockingUpdateForDomains): Deleted.
     48        (WebKit::WebResourceLoadStatisticsStore::scheduleClearBlockingStateForDomains): Deleted.
     49            Dead code.
     50        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
     51        (WebKit::RegistrableDomainsToBlockCookiesFor::isolatedCopy const):
     52        * NetworkProcess/NetworkProcess.cpp:
     53        (WebKit::NetworkProcess::updatePrevalentDomainsToBlockCookiesFor):
     54        (WebKit::NetworkProcess::scheduleClearInMemoryAndPersistent):
     55        (WebKit::NetworkProcess::hasIsolatedSession const):
     56        * NetworkProcess/NetworkProcess.h:
     57        * NetworkProcess/NetworkProcess.messages.in:
     58        * NetworkProcess/NetworkSession.h:
     59        (WebKit::NetworkSession::shouldIsolateSessionsForPrevalentTopFrames const):
     60        (WebKit::NetworkSession::hasIsolatedSession const):
     61        (WebKit::NetworkSession::clearIsolatedSessions):
     62        * NetworkProcess/NetworkSessionCreationParameters.cpp:
     63        (WebKit::NetworkSessionCreationParameters::encode const):
     64        (WebKit::NetworkSessionCreationParameters::decode):
     65        * NetworkProcess/NetworkSessionCreationParameters.h:
     66        * NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
     67        (WebKit::NetworkDataTaskCocoa::NetworkDataTaskCocoa):
     68        * NetworkProcess/cocoa/NetworkSessionCocoa.h:
     69        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
     70        (WebKit::NetworkSessionCocoa::NetworkSessionCocoa):
     71        (WebKit::NetworkSessionCocoa::session):
     72        (WebKit::NetworkSessionCocoa::isolatedSession):
     73        (WebKit::NetworkSessionCocoa::hasIsolatedSession const):
     74        (WebKit::NetworkSessionCocoa::clearIsolatedSessions):
     75        (WebKit::NetworkSessionCocoa::invalidateAndCancel):
     76        (WebKit::NetworkSessionCocoa::clearCredentials):
     77        * Shared/WebPreferences.yaml:
     78        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
     79        (WKWebsiteDataStoreStatisticsHasIsolatedSession):
     80        * UIProcess/API/C/WKWebsiteDataStoreRef.h:
     81        * UIProcess/Network/NetworkProcessProxy.cpp:
     82        (WebKit::NetworkProcessProxy::hasIsolatedSession):
     83        * UIProcess/Network/NetworkProcessProxy.h:
     84        * UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:
     85        (WebKit::WebsiteDataStore::parameters):
     86        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
     87        (WebKit::WebsiteDataStore::hasLocalStorageForTesting const):
     88        (WebKit::WebsiteDataStore::hasIsolatedSessionForTesting const):
     89        * UIProcess/WebsiteData/WebsiteDataStore.h:
     90
    1912019-08-13  Chris Dumez  <cdumez@apple.com>
    292
  • trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp

    r247119 r248640  
    13181318    removeAllStorageAccess([callbackAggregator = callbackAggregator.copyRef()] { });
    13191319
    1320     auto primaryDomainsToBlock = ensurePrevalentResourcesForDebugMode();
    1321     updateCookieBlockingForDomains(primaryDomainsToBlock, [callbackAggregator = callbackAggregator.copyRef()] { });
     1320    auto registrableDomainsToBlockAndDeleteCookiesFor = ensurePrevalentResourcesForDebugMode();
     1321    RegistrableDomainsToBlockCookiesFor domainsToBlock { registrableDomainsToBlockAndDeleteCookiesFor, { } };
     1322    updateCookieBlockingForDomains(domainsToBlock, [callbackAggregator = callbackAggregator.copyRef()] { });
    13221323}
    13231324
     
    13541355}
    13551356
    1356 Vector<RegistrableDomain> ResourceLoadStatisticsDatabaseStore::domainsToBlock() const
    1357 {
    1358     ASSERT(!RunLoop::isMain());
    1359 
     1357Vector<RegistrableDomain> ResourceLoadStatisticsDatabaseStore::domainsToBlockAndDeleteCookiesFor() const
     1358{
     1359    ASSERT(!RunLoop::isMain());
     1360   
    13601361    Vector<RegistrableDomain> results;
    1361     SQLiteStatement statement(m_database, "SELECT registrableDomain FROM ObservedDomains WHERE isPrevalent = 1"_s);
     1362    SQLiteStatement statement(m_database, "SELECT registrableDomain FROM ObservedDomains WHERE isPrevalent = 1 AND hadUserInteraction = 0"_s);
    13621363    if (statement.prepare() != SQLITE_OK)
    13631364        return results;
     
    13651366    while (statement.step() == SQLITE_ROW)
    13661367        results.append(RegistrableDomain::uncheckedCreateFromRegistrableDomainString(statement.getColumnText(0)));
    1367 
     1368   
    13681369    return results;
    13691370}
    13701371
     1372Vector<RegistrableDomain> ResourceLoadStatisticsDatabaseStore::domainsToBlockButKeepCookiesFor() const
     1373{
     1374    ASSERT(!RunLoop::isMain());
     1375
     1376    Vector<RegistrableDomain> results;
     1377    SQLiteStatement statement(m_database, "SELECT registrableDomain FROM ObservedDomains WHERE isPrevalent = 1 AND hadUserInteraction = 1"_s);
     1378    if (statement.prepare() != SQLITE_OK)
     1379        return results;
     1380   
     1381    while (statement.step() == SQLITE_ROW)
     1382        results.append(RegistrableDomain::uncheckedCreateFromRegistrableDomainString(statement.getColumnText(0)));
     1383
     1384    return results;
     1385}
     1386
    13711387void ResourceLoadStatisticsDatabaseStore::updateCookieBlocking(CompletionHandler<void()>&& completionHandler)
    13721388{
    13731389    ASSERT(!RunLoop::isMain());
    13741390
    1375     auto domainsToBlock = this->domainsToBlock();
    1376 
    1377     if (domainsToBlock.isEmpty()) {
     1391    auto domainsToBlockAndDeleteCookiesFor = this->domainsToBlockAndDeleteCookiesFor();
     1392    auto domainsToBlockButKeepCookiesFor = this->domainsToBlockButKeepCookiesFor();
     1393
     1394    if (domainsToBlockAndDeleteCookiesFor.isEmpty() && domainsToBlockButKeepCookiesFor.isEmpty()) {
    13781395        completionHandler();
    13791396        return;
    13801397    }
    13811398
    1382     if (debugLoggingEnabled() && !domainsToBlock.isEmpty())
     1399    RegistrableDomainsToBlockCookiesFor domainsToBlock { domainsToBlockAndDeleteCookiesFor, domainsToBlockButKeepCookiesFor };
     1400
     1401    if (debugLoggingEnabled() && !domainsToBlockAndDeleteCookiesFor.isEmpty() && !domainsToBlockButKeepCookiesFor.isEmpty())
    13831402        debugLogDomainsInBatches("block", domainsToBlock);
    13841403
  • trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h

    r247119 r248640  
    118118    void updateLastSeen(const RegistrableDomain&, WallTime);
    119119    void setUserInteraction(const RegistrableDomain&, bool hadUserInteraction, WallTime);
    120     Vector<RegistrableDomain> domainsToBlock() const;
     120    Vector<RegistrableDomain> domainsToBlockAndDeleteCookiesFor() const;
     121    Vector<RegistrableDomain> domainsToBlockButKeepCookiesFor() const;
    121122
    122123    struct PrevalentDomainData {
  • trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp

    r248401 r248640  
    713713    removeAllStorageAccess([callbackAggregator = callbackAggregator.copyRef()] { });
    714714
    715     auto primaryDomainsToBlock = ensurePrevalentResourcesForDebugMode();
    716     updateCookieBlockingForDomains(primaryDomainsToBlock, [callbackAggregator = callbackAggregator.copyRef()] { });
     715    auto registrableDomainsToBlockAndDeleteCookiesFor = ensurePrevalentResourcesForDebugMode();
     716    RegistrableDomainsToBlockCookiesFor domainsToBlock { registrableDomainsToBlockAndDeleteCookiesFor, { } };
     717    updateCookieBlockingForDomains(domainsToBlock, [callbackAggregator = callbackAggregator.copyRef()] { });
    717718}
    718719
     
    762763    ASSERT(!RunLoop::isMain());
    763764
    764     Vector<RegistrableDomain> domainsToBlock;
     765    Vector<RegistrableDomain> domainsToBlockAndDeleteCookiesFor;
     766    Vector<RegistrableDomain> domainsToBlockButKeepCookiesFor;
    765767    for (auto& resourceStatistic : m_resourceStatisticsMap.values()) {
    766         if (resourceStatistic.isPrevalentResource)
    767             domainsToBlock.append(resourceStatistic.registrableDomain);
    768     }
    769 
    770     if (domainsToBlock.isEmpty() && !debugModeEnabled()) {
     768        if (resourceStatistic.isPrevalentResource) {
     769            if (hasHadUnexpiredRecentUserInteraction(resourceStatistic, OperatingDatesWindow::Long))
     770                domainsToBlockButKeepCookiesFor.append(resourceStatistic.registrableDomain);
     771            else
     772                domainsToBlockAndDeleteCookiesFor.append(resourceStatistic.registrableDomain);
     773        }
     774    }
     775
     776    if (domainsToBlockAndDeleteCookiesFor.isEmpty() && domainsToBlockButKeepCookiesFor.isEmpty() && !debugModeEnabled()) {
    771777        completionHandler();
    772778        return;
    773779    }
    774780
    775     if (debugLoggingEnabled() && !domainsToBlock.isEmpty())
     781    RegistrableDomainsToBlockCookiesFor domainsToBlock { domainsToBlockAndDeleteCookiesFor, domainsToBlockButKeepCookiesFor };
     782
     783    if (debugLoggingEnabled() && !domainsToBlockAndDeleteCookiesFor.isEmpty() && !domainsToBlockButKeepCookiesFor.isEmpty())
    776784        debugLogDomainsInBatches("block", domainsToBlock);
    777785
  • trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.cpp

    r248372 r248640  
    414414}
    415415
    416 void ResourceLoadStatisticsStore::updateCookieBlockingForDomains(const Vector<RegistrableDomain>& domainsToBlock, CompletionHandler<void()>&& completionHandler)
     416void ResourceLoadStatisticsStore::updateCookieBlockingForDomains(const RegistrableDomainsToBlockCookiesFor& domainsToBlock, CompletionHandler<void()>&& completionHandler)
    417417{
    418418    ASSERT(!RunLoop::isMain());
     
    572572}
    573573
    574 void ResourceLoadStatisticsStore::debugLogDomainsInBatches(const char* action, const Vector<RegistrableDomain>& domains)
    575 {
     574void ResourceLoadStatisticsStore::debugLogDomainsInBatches(const char* action, const RegistrableDomainsToBlockCookiesFor& domainsToBlock)
     575{
     576    Vector<RegistrableDomain> domains;
     577    domains.appendVector(domainsToBlock.domainsToBlockAndDeleteCookiesFor);
     578    domains.appendVector(domainsToBlock.domainsToBlockButKeepCookiesFor);
    576579    static const auto maxNumberOfDomainsInOneLogStatement = 50;
    577580    if (domains.isEmpty())
  • trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.h

    r247119 r248640  
    9999
    100100    virtual void updateCookieBlocking(CompletionHandler<void()>&&) = 0;
    101     void updateCookieBlockingForDomains(const Vector<RegistrableDomain>& domainsToBlock, CompletionHandler<void()>&&);
     101    void updateCookieBlockingForDomains(const RegistrableDomainsToBlockCookiesFor&, CompletionHandler<void()>&&);
    102102    void clearBlockingStateForDomains(const Vector<RegistrableDomain>& domains, CompletionHandler<void()>&&);
    103103
     
    187187    static unsigned computeImportance(const WebCore::ResourceLoadStatistics&);
    188188    static Vector<OperatingDate> mergeOperatingDates(const Vector<OperatingDate>& existingDates, Vector<OperatingDate>&& newDates);
    189     static void debugLogDomainsInBatches(const char* action, const Vector<RegistrableDomain>& domains);
     189    static void debugLogDomainsInBatches(const char* action, const RegistrableDomainsToBlockCookiesFor&);
    190190
    191191    ResourceLoadStatisticsStore(WebResourceLoadStatisticsStore&, WorkQueue&, ShouldIncludeLocalhost);
  • trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp

    r248634 r248640  
    841841}
    842842
    843 void WebResourceLoadStatisticsStore::scheduleCookieBlockingUpdateForDomains(const Vector<RegistrableDomain>& domainsToBlock, CompletionHandler<void()>&& completionHandler)
    844 {
    845     // Helper function used by testing system. Should only be called from the main thread.
    846     ASSERT(RunLoop::isMain());
    847     postTask([this, domainsToBlock = crossThreadCopy(domainsToBlock), completionHandler = WTFMove(completionHandler)]() mutable {
    848         if (!m_statisticsStore) {
    849             postTaskReply(WTFMove(completionHandler));
    850             return;
    851         }
    852 
    853         m_statisticsStore->updateCookieBlockingForDomains(domainsToBlock, [completionHandler = WTFMove(completionHandler)]() mutable {
    854             postTaskReply(WTFMove(completionHandler));
    855         });
    856     });
    857 }
    858 
    859 void WebResourceLoadStatisticsStore::scheduleClearBlockingStateForDomains(const Vector<RegistrableDomain>& domains, CompletionHandler<void()>&& completionHandler)
    860 {
    861     // Helper function used by testing system. Should only be called from the main thread.
    862     ASSERT(RunLoop::isMain());
    863     postTask([this, domains = crossThreadCopy(domains), completionHandler = WTFMove(completionHandler)]() mutable {
    864         if (!m_statisticsStore) {
    865             postTaskReply(WTFMove(completionHandler));
    866             return;
    867         }
    868 
    869         m_statisticsStore->clearBlockingStateForDomains(domains, [completionHandler = WTFMove(completionHandler)]() mutable {
    870             postTaskReply(WTFMove(completionHandler));
    871         });
    872     });
    873 }
    874 
    875843void WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent(ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
    876844{
     
    957925}
    958926
    959 void WebResourceLoadStatisticsStore::callUpdatePrevalentDomainsToBlockCookiesForHandler(const Vector<RegistrableDomain>& domainsToBlock, CompletionHandler<void()>&& completionHandler)
     927void WebResourceLoadStatisticsStore::callUpdatePrevalentDomainsToBlockCookiesForHandler(const RegistrableDomainsToBlockCookiesFor& domainsToBlock, CompletionHandler<void()>&& completionHandler)
    960928{
    961929    ASSERT(RunLoop::isMain());
    962930
    963931    if (m_networkSession) {
    964         if (auto* storageSession = m_networkSession->networkStorageSession())
    965             storageSession->setPrevalentDomainsToBlockCookiesFor(domainsToBlock);
     932        if (auto* storageSession = m_networkSession->networkStorageSession()) {
     933            storageSession->setPrevalentDomainsToBlockAndDeleteCookiesFor(domainsToBlock.domainsToBlockAndDeleteCookiesFor);
     934            storageSession->setPrevalentDomainsToBlockButKeepCookiesFor(domainsToBlock.domainsToBlockButKeepCookiesFor);
     935        }
    966936    }
    967937
  • trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h

    r247784 r248640  
    6464enum class ShouldIncludeLocalhost : bool { No, Yes };
    6565enum class EnableResourceLoadStatisticsDebugMode : bool { No, Yes };
     66enum class EnableResourceLoadStatisticsNSURLSessionSwitching : bool { No, Yes };
    6667enum class WebsiteDataToRemove : uint8_t {
    6768    All,
    6869    AllButHttpOnlyCookies,
    6970    AllButCookies
     71};
     72struct RegistrableDomainsToBlockCookiesFor {
     73    Vector<WebCore::RegistrableDomain> domainsToBlockAndDeleteCookiesFor;
     74    Vector<WebCore::RegistrableDomain> domainsToBlockButKeepCookiesFor;
     75    RegistrableDomainsToBlockCookiesFor isolatedCopy() const { return { domainsToBlockAndDeleteCookiesFor.isolatedCopy(), domainsToBlockButKeepCookiesFor.isolatedCopy() }; }
    7076};
    7177
     
    169175    void callGrantStorageAccessHandler(const SubFrameDomain&, const TopFrameDomain&, Optional<FrameID>, WebCore::PageIdentifier, CompletionHandler<void(StorageAccessWasGranted)>&&);
    170176    void removeAllStorageAccess(CompletionHandler<void()>&&);
    171     void callUpdatePrevalentDomainsToBlockCookiesForHandler(const Vector<RegistrableDomain>&, CompletionHandler<void()>&&);
     177    void callUpdatePrevalentDomainsToBlockCookiesForHandler(const RegistrableDomainsToBlockCookiesFor&, CompletionHandler<void()>&&);
    172178    void callRemoveDomainsHandler(const Vector<RegistrableDomain>&);
    173179    void callHasStorageAccessForFrameHandler(const SubFrameDomain&, const TopFrameDomain&, FrameID, WebCore::PageIdentifier, CompletionHandler<void(bool)>&&);
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp

    r248593 r248640  
    637637{
    638638    if (auto* networkStorageSession = storageSession(sessionID))
    639         networkStorageSession->setPrevalentDomainsToBlockCookiesFor(domainsToBlock);
     639        networkStorageSession->setPrevalentDomainsToBlockAndDeleteCookiesFor(domainsToBlock);
    640640    completionHandler();
    641641}
     
    781781{
    782782    if (auto* networkSession = this->networkSession(sessionID)) {
     783        networkSession->clearIsolatedSessions();
    783784        if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics()) {
    784785            if (modifiedSince)
     
    12351236        ASSERT_NOT_REACHED();
    12361237    completionHandler();
     1238}
     1239
     1240void NetworkProcess::hasIsolatedSession(PAL::SessionID sessionID, const WebCore::RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler) const
     1241{
     1242    bool result = false;
     1243    if (auto* networkSession = this->networkSession(sessionID))
     1244        result = networkSession->hasIsolatedSession(domain);
     1245    completionHandler(result);
    12371246}
    12381247#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.h

    r248593 r248640  
    260260    void setCrossSiteLoadWithLinkDecorationForTesting(PAL::SessionID, const RegistrableDomain& fromDomain, const RegistrableDomain& toDomain, CompletionHandler<void()>&&);
    261261    void resetCrossSiteLoadsWithLinkDecorationForTesting(PAL::SessionID, CompletionHandler<void()>&&);
     262    void hasIsolatedSession(PAL::SessionID, const WebCore::RegistrableDomain&, CompletionHandler<void(bool)>&&) const;
    262263#endif
    263264
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in

    r248526 r248640  
    138138    ResetCrossSiteLoadsWithLinkDecorationForTesting(PAL::SessionID sessionID) -> () Async
    139139    DeleteCookiesForTesting(PAL::SessionID sessionID, WebCore::RegistrableDomain domain, bool includeHttpOnlyCookies) -> () Async
     140    HasIsolatedSession(PAL::SessionID sessionID, WebCore::RegistrableDomain domain) -> (bool hasIsolatedSession) Async
    140141#endif
    141142
  • trunk/Source/WebKit/NetworkProcess/NetworkSession.h

    r248593 r248640  
    9494    bool enableResourceLoadStatisticsLogTestingEvent() const { return m_enableResourceLoadStatisticsLogTestingEvent; }
    9595    void setResourceLoadStatisticsLogTestingEvent(bool log) { m_enableResourceLoadStatisticsLogTestingEvent = log; }
     96    bool shouldIsolateSessionsForPrevalentTopFrames() const { return m_enableResourceLoadStatisticsNSURLSessionSwitching == EnableResourceLoadStatisticsNSURLSessionSwitching::Yes; }
     97    virtual bool hasIsolatedSession(const WebCore::RegistrableDomain) const { return false; }
     98    virtual void clearIsolatedSessions() { }
    9699#endif
    97100    void storeAdClickAttribution(WebCore::AdClickAttribution&&);
     
    134137    EnableResourceLoadStatisticsDebugMode m_enableResourceLoadStatisticsDebugMode { EnableResourceLoadStatisticsDebugMode::No };
    135138    WebCore::RegistrableDomain m_resourceLoadStatisticsManualPrevalentResource;
     139    EnableResourceLoadStatisticsNSURLSessionSwitching m_enableResourceLoadStatisticsNSURLSessionSwitching { EnableResourceLoadStatisticsNSURLSessionSwitching::No };
    136140    bool m_enableResourceLoadStatisticsLogTestingEvent;
    137141#endif
  • trunk/Source/WebKit/NetworkProcess/NetworkSessionCreationParameters.cpp

    r248144 r248640  
    5151        , { }, { }
    5252#endif
    53         , { }, { }, false, false, { }, { }, { }, { }, { }, { }, { }, { }, { }
     53        , { }, { }, false, false, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
    5454    };
    5555}
     
    8585    encoder << enableResourceLoadStatisticsDebugMode;
    8686    encoder << resourceLoadStatisticsManualPrevalentResource;
     87    encoder << enableResourceLoadStatisticsNSURLSessionSwitching;
    8788
    8889    encoder << localStorageDirectory << localStorageDirectoryExtensionHandle;
     
    209210        return WTF::nullopt;
    210211
     212    Optional<bool> enableResourceLoadStatisticsNSURLSessionSwitching;
     213    decoder >> enableResourceLoadStatisticsNSURLSessionSwitching;
     214    if (!enableResourceLoadStatisticsNSURLSessionSwitching)
     215        return WTF::nullopt;
     216   
    211217    Optional<String> localStorageDirectory;
    212218    decoder >> localStorageDirectory;
     
    267273        , WTFMove(*shouldIncludeLocalhostInResourceLoadStatistics)
    268274        , WTFMove(*enableResourceLoadStatisticsDebugMode)
     275        , WTFMove(*enableResourceLoadStatisticsNSURLSessionSwitching)
    269276        , WTFMove(*deviceManagementRestrictionsEnabled)
    270277        , WTFMove(*allLoadsBlockedByDeviceManagementRestrictionsForTesting)
  • trunk/Source/WebKit/NetworkProcess/NetworkSessionCreationParameters.h

    r248144 r248640  
    8888    bool shouldIncludeLocalhostInResourceLoadStatistics { true };
    8989    bool enableResourceLoadStatisticsDebugMode { false };
     90    bool enableResourceLoadStatisticsNSURLSessionSwitching { true };
    9091    bool deviceManagementRestrictionsEnabled { false };
    9192    bool allLoadsBlockedByDeviceManagementRestrictionsForTesting { false };
  • trunk/Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm

    r248273 r248640  
    3939#import <WebCore/NetworkStorageSession.h>
    4040#import <WebCore/NotImplemented.h>
     41#import <WebCore/RegistrableDomain.h>
    4142#import <WebCore/ResourceRequest.h>
    4243#import <pal/spi/cf/CFNetworkSPI.h>
     
    206207
    207208    bool shouldBlockCookies = false;
     209    bool needsIsolatedSession = false;
     210    auto firstParty = WebCore::RegistrableDomain(request.firstPartyForCookies());
    208211#if ENABLE(RESOURCE_LOAD_STATISTICS)
    209     shouldBlockCookies = storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless
    210         || (session.networkStorageSession() && session.networkStorageSession()->shouldBlockCookies(request, frameID, pageID));
     212    shouldBlockCookies = storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless;
     213    if (auto* networkStorageSession = session.networkStorageSession()) {
     214        if (!shouldBlockCookies)
     215            shouldBlockCookies = networkStorageSession->shouldBlockCookies(request, frameID, pageID);
     216        needsIsolatedSession = session.shouldIsolateSessionsForPrevalentTopFrames() && networkStorageSession->shouldBlockThirdPartyCookiesButKeepFirstPartyCookiesFor(firstParty);
     217    }
    211218#endif
    212219    restrictRequestReferrerToOriginIfNeeded(request, shouldBlockCookies);
     
    216223
    217224    auto& cocoaSession = static_cast<NetworkSessionCocoa&>(*m_session);
     225    if (needsIsolatedSession)
     226        m_task = [cocoaSession.isolatedSession(storedCredentialsPolicy, firstParty) dataTaskWithRequest:nsRequest];
     227    else
     228        m_task = [cocoaSession.session(storedCredentialsPolicy) dataTaskWithRequest:nsRequest];
    218229    switch (storedCredentialsPolicy) {
    219230    case WebCore::StoredCredentialsPolicy::Use:
    220         m_task = [cocoaSession.m_sessionWithCredentialStorage dataTaskWithRequest:nsRequest];
    221231        ASSERT(!cocoaSession.m_dataTaskMapWithCredentials.contains([m_task taskIdentifier]));
    222232        cocoaSession.m_dataTaskMapWithCredentials.add([m_task taskIdentifier], this);
     
    224234        break;
    225235    case WebCore::StoredCredentialsPolicy::DoNotUse:
    226         m_task = [cocoaSession.m_statelessSession dataTaskWithRequest:nsRequest];
    227236        ASSERT(!cocoaSession.m_dataTaskMapWithoutState.contains([m_task taskIdentifier]));
    228237        cocoaSession.m_dataTaskMapWithoutState.add([m_task taskIdentifier], this);
     
    230239        break;
    231240    case WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless:
    232         if (!cocoaSession.m_ephemeralStatelessCookielessSession)
    233             cocoaSession.initializeEphemeralStatelessCookielessSession();
    234         m_task = [cocoaSession.m_ephemeralStatelessCookielessSession dataTaskWithRequest:nsRequest];
    235241        ASSERT(!cocoaSession.m_dataTaskMapEphemeralStatelessCookieless.contains([m_task taskIdentifier]));
    236242        cocoaSession.m_dataTaskMapEphemeralStatelessCookieless.add([m_task taskIdentifier], this);
  • trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h

    r248592 r248640  
    3939#include "WebSocketTask.h"
    4040#include <WebCore/NetworkLoadMetrics.h>
     41#include <WebCore/RegistrableDomain.h>
    4142#include <wtf/HashMap.h>
     43#include <wtf/Seconds.h>
    4244
    4345namespace WebKit {
     
    8486    CFDictionaryRef proxyConfiguration() const { return m_proxyConfiguration.get(); }
    8587
     88    NSURLSession* session(WebCore::StoredCredentialsPolicy);
     89    NSURLSession* isolatedSession(WebCore::StoredCredentialsPolicy, const WebCore::RegistrableDomain);
     90    bool hasIsolatedSession(const WebCore::RegistrableDomain) const override;
     91    void clearIsolatedSessions() override;
     92
    8693private:
    8794    void invalidateAndCancel() override;
     
    104111#endif
    105112
     113    struct IsolatedSession {
     114        RetainPtr<NSURLSession> sessionWithCredentialStorage;
     115        RetainPtr<WKNetworkSessionDelegate> sessionWithCredentialStorageDelegate;
     116        RetainPtr<NSURLSession> statelessSession;
     117        RetainPtr<WKNetworkSessionDelegate> statelessSessionDelegate;
     118        WallTime lastUsed;
     119    };
     120
     121    HashMap<WebCore::RegistrableDomain, IsolatedSession> m_isolatedSessions;
     122
    106123    RetainPtr<NSURLSession> m_sessionWithCredentialStorage;
    107124    RetainPtr<WKNetworkSessionDelegate> m_sessionWithCredentialStorageDelegate;
  • trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm

    r248394 r248640  
    6767CFStringRef const WebKit2HTTPProxyDefaultsKey = static_cast<CFStringRef>(@"WebKit2HTTPProxy");
    6868CFStringRef const WebKit2HTTPSProxyDefaultsKey = static_cast<CFStringRef>(@"WebKit2HTTPSProxy");
     69
     70constexpr unsigned maxNumberOfIsolatedSessions { 10 };
    6971
    7072static NSURLSessionResponseDisposition toNSURLSessionResponseDisposition(WebCore::PolicyAction disposition)
     
    10351037    m_enableResourceLoadStatisticsDebugMode = parameters.enableResourceLoadStatisticsDebugMode ? EnableResourceLoadStatisticsDebugMode::Yes : EnableResourceLoadStatisticsDebugMode::No;
    10361038    m_resourceLoadStatisticsManualPrevalentResource = parameters.resourceLoadStatisticsManualPrevalentResource;
     1039    m_enableResourceLoadStatisticsNSURLSessionSwitching = parameters.enableResourceLoadStatisticsNSURLSessionSwitching ? EnableResourceLoadStatisticsNSURLSessionSwitching::Yes : EnableResourceLoadStatisticsNSURLSessionSwitching::No;
    10371040    setResourceLoadStatisticsEnabled(parameters.enableResourceLoadStatistics);
    10381041#endif
     
    10671070    m_ephemeralStatelessCookielessSessionDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:false]);
    10681071    m_ephemeralStatelessCookielessSession = [NSURLSession sessionWithConfiguration:configuration delegate:static_cast<id>(m_ephemeralStatelessCookielessSessionDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
     1072}
     1073
     1074NSURLSession* NetworkSessionCocoa::session(WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
     1075{
     1076    switch (storedCredentialsPolicy) {
     1077    case WebCore::StoredCredentialsPolicy::Use:
     1078        return m_sessionWithCredentialStorage.get();
     1079    case WebCore::StoredCredentialsPolicy::DoNotUse:
     1080        return m_statelessSession.get();
     1081    case WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless:
     1082        if (!m_ephemeralStatelessCookielessSession)
     1083            initializeEphemeralStatelessCookielessSession();
     1084        return m_ephemeralStatelessCookielessSession.get();
     1085    }
     1086}
     1087
     1088NSURLSession* NetworkSessionCocoa::isolatedSession(WebCore::StoredCredentialsPolicy storedCredentialsPolicy, const WebCore::RegistrableDomain firstPartyDomain)
     1089{
     1090    auto entry = m_isolatedSessions.ensure(firstPartyDomain, [this] {
     1091        IsolatedSession newEntry { };
     1092        newEntry.sessionWithCredentialStorageDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:true]);
     1093        newEntry.sessionWithCredentialStorage = [NSURLSession sessionWithConfiguration:m_sessionWithCredentialStorage.get().configuration delegate:static_cast<id>(newEntry.sessionWithCredentialStorageDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
     1094
     1095        newEntry.statelessSessionDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:false]);
     1096        newEntry.statelessSession = [NSURLSession sessionWithConfiguration:m_statelessSession.get().configuration delegate:static_cast<id>(newEntry.statelessSessionDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
     1097
     1098        return newEntry;
     1099    }).iterator->value;
     1100
     1101    entry.lastUsed = WallTime::now();
     1102
     1103    if (m_isolatedSessions.size() > maxNumberOfIsolatedSessions) {
     1104        WebCore::RegistrableDomain keyToRemove;
     1105        auto oldestTimestamp = WallTime::now();
     1106        for (auto& key : m_isolatedSessions.keys()) {
     1107            auto timestamp = m_isolatedSessions.get(key).lastUsed;
     1108            if (timestamp < oldestTimestamp) {
     1109                oldestTimestamp = timestamp;
     1110                keyToRemove = key;
     1111            }
     1112        }
     1113        LOG(NetworkSession, "About to remove isolated NSURLSession.");
     1114        m_isolatedSessions.remove(keyToRemove);
     1115    }
     1116
     1117    RELEASE_ASSERT(m_isolatedSessions.size() <= maxNumberOfIsolatedSessions);
     1118
     1119    switch (storedCredentialsPolicy) {
     1120    case WebCore::StoredCredentialsPolicy::Use:
     1121        LOG(NetworkSession, "Using isolated NSURLSession with credential storage.");
     1122        return entry.sessionWithCredentialStorage.get();
     1123    case WebCore::StoredCredentialsPolicy::DoNotUse:
     1124        LOG(NetworkSession, "Using isolated NSURLSession without credential storage.");
     1125        return entry.statelessSession.get();
     1126    case WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless:
     1127        if (!m_ephemeralStatelessCookielessSession)
     1128            initializeEphemeralStatelessCookielessSession();
     1129        return m_ephemeralStatelessCookielessSession.get();
     1130    }
     1131}
     1132
     1133bool NetworkSessionCocoa::hasIsolatedSession(const WebCore::RegistrableDomain domain) const
     1134{
     1135    return m_isolatedSessions.contains(domain);
     1136}
     1137
     1138void NetworkSessionCocoa::clearIsolatedSessions()
     1139{
     1140    m_isolatedSessions.clear();
    10691141}
    10701142
     
    10791151    [m_statelessSessionDelegate sessionInvalidated];
    10801152    [m_ephemeralStatelessCookielessSessionDelegate sessionInvalidated];
     1153
     1154    for (auto& session : m_isolatedSessions.values()) {
     1155        [session.sessionWithCredentialStorage invalidateAndCancel];
     1156        [session.sessionWithCredentialStorageDelegate sessionInvalidated];
     1157    }
     1158    m_isolatedSessions.clear();
    10811159}
    10821160
     
    10901168    m_sessionWithCredentialStorage = [NSURLSession sessionWithConfiguration:m_sessionWithCredentialStorage.get().configuration delegate:static_cast<id>(m_sessionWithCredentialStorageDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
    10911169    m_statelessSession = [NSURLSession sessionWithConfiguration:m_statelessSession.get().configuration delegate:static_cast<id>(m_statelessSessionDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
     1170    for (auto& entry : m_isolatedSessions.values())
     1171        entry.session = [NSURLSession sessionWithConfiguration:entry.session.get().configuration delegate:static_cast<id>(entry.delegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
    10921172#endif
    10931173}
  • trunk/Source/WebKit/Shared/WebPreferences.yaml

    r248471 r248640  
    17241724  category: experimental
    17251725
     1726IsITPSessionSwitchingEnabled:
     1727  type: bool
     1728  defaultValue: true
     1729  humanReadableName: "ITP Session Switching"
     1730  humanReadableDescription: "Enable session switching for domains classified by ITP"
     1731  webcoreBinding: RuntimeEnabledFeatures
     1732  category: internal
     1733
    17261734# Deprecated
    17271735
  • trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp

    r245500 r248640  
    473473}
    474474
     475void WKWebsiteDataStoreStatisticsHasIsolatedSession(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, void* context, WKWebsiteDataStoreStatisticsHasIsolatedSessionFunction callback)
     476{
     477#if ENABLE(RESOURCE_LOAD_STATISTICS)
     478    WebKit::toImpl(dataStoreRef)->websiteDataStore().hasIsolatedSessionForTesting(URL(URL(), WebKit::toImpl(host)->string()), [context, callback](bool hasIsolatedSession) {
     479        callback(hasIsolatedSession, context);
     480    });
     481#else
     482    callback(false, context);
     483#endif
     484}
     485
    475486void WKWebsiteDataStoreStatisticsResetToConsistentState(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreStatisticsResetToConsistentStateFunction completionHandler)
    476487{
  • trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h

    r244572 r248640  
    104104typedef void (*WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction)(void* functionContext);
    105105WK_EXPORT void WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap(WKWebsiteDataStoreRef dataStoreRef, double seconds, void* context, WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction);
     106typedef void (*WKWebsiteDataStoreStatisticsHasIsolatedSessionFunction)(bool hasIsolatedSession, void* functionContext);
     107WK_EXPORT void WKWebsiteDataStoreStatisticsHasIsolatedSession(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, void* context, WKWebsiteDataStoreStatisticsHasIsolatedSessionFunction callback);
    106108typedef void (*WKWebsiteDataStoreStatisticsResetToConsistentStateFunction)(void* functionContext);
    107109WK_EXPORT void WKWebsiteDataStoreStatisticsResetToConsistentState(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreStatisticsResetToConsistentStateFunction completionHandler);
  • trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp

    r248047 r248640  
    975975}
    976976
     977void NetworkProcessProxy::hasIsolatedSession(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
     978{
     979    if (!canSendMessage()) {
     980        completionHandler(false);
     981        return;
     982    }
     983   
     984    sendWithAsyncReply(Messages::NetworkProcess::HasIsolatedSession(sessionID, domain), WTFMove(completionHandler));
     985}
     986
    977987#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
    978988
  • trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h

    r248047 r248640  
    151151    void deleteCookiesForTesting(PAL::SessionID, const RegistrableDomain&, bool includeHttpOnlyCookies, CompletionHandler<void()>&&);
    152152    void deleteWebsiteDataInUIProcessForRegistrableDomains(PAL::SessionID, OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, Vector<RegistrableDomain>, CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&&);
     153    void hasIsolatedSession(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void(bool)>&&);
    153154#endif
    154155
  • trunk/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm

    r248144 r248640  
    3333#import <WebCore/RegistrableDomain.h>
    3434#import <WebCore/RuntimeApplicationChecks.h>
     35#import <WebCore/RuntimeEnabledFeatures.h>
    3536#import <WebCore/SearchPopupMenuCocoa.h>
    3637#import <pal/spi/cf/CFNetworkSPI.h>
     
    6768    bool shouldLogCookieInformation = false;
    6869    bool enableResourceLoadStatisticsDebugMode = false;
     70    bool enableResourceLoadStatisticsNSURLSessionSwitching = WebCore::RuntimeEnabledFeatures::sharedFeatures().isITPSessionSwitchingEnabled();
    6971    WebCore::RegistrableDomain resourceLoadStatisticsManualPrevalentResource { };
    7072#if ENABLE(RESOURCE_LOAD_STATISTICS)
     
    138140        shouldIncludeLocalhostInResourceLoadStatistics,
    139141        enableResourceLoadStatisticsDebugMode,
     142        enableResourceLoadStatisticsNSURLSessionSwitching,
    140143        m_configuration->deviceManagementRestrictionsEnabled(),
    141144        m_configuration->allLoadsBlockedByDeviceManagementRestrictionsForTesting(),
  • trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp

    r248144 r248640  
    16851685    ASSERT(!completionHandler);
    16861686}
     1687
     1688void WebsiteDataStore::hasIsolatedSessionForTesting(const URL& url, CompletionHandler<void(bool)>&& completionHandler) const
     1689{
     1690    for (auto& processPool : processPools()) {
     1691        if (auto* networkProcess = processPool->networkProcess()) {
     1692            networkProcess->hasIsolatedSession(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
     1693            ASSERT(processPools().size() == 1);
     1694            break;
     1695        }
     1696    }
     1697    ASSERT(!completionHandler);
     1698}
    16871699#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
    16881700
  • trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h

    r248144 r248640  
    180180    void deleteCookiesForTesting(const URL&, bool includeHttpOnlyCookies, CompletionHandler<void()>&&);
    181181    void hasLocalStorageForTesting(const URL&, CompletionHandler<void(bool)>&&) const;
     182    void hasIsolatedSessionForTesting(const URL&, CompletionHandler<void(bool)>&&) const;
    182183#endif
    183184    void setCacheMaxAgeCapForPrevalentResources(Seconds, CompletionHandler<void()>&&);
  • trunk/Tools/ChangeLog

    r248636 r248640  
     12019-08-13  John Wilander  <wilander@apple.com>
     2
     3        Resource Load Statistics: Switch NSURLSession on top navigation to prevalent resource with user interaction
     4        https://bugs.webkit.org/show_bug.cgi?id=200642
     5        <rdar://problem/53962073>
     6
     7        Reviewed by Alex Christensen.
     8
     9        This patch adds test infrastructure to query whether an origin has an
     10        isolated NSURLSession or not.
     11
     12        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
     13        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
     14        (WTR::TestRunner::hasStatisticsIsolatedSession):
     15        * WebKitTestRunner/InjectedBundle/TestRunner.h:
     16        * WebKitTestRunner/TestController.cpp:
     17        (WTR::TestController::hasStatisticsIsolatedSession):
     18        * WebKitTestRunner/TestController.h:
     19        * WebKitTestRunner/TestInvocation.cpp:
     20        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
     21
    1222019-08-13  Zhifei Fang  <zhifei_fang@apple.com>
    223
  • trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl

    r248526 r248640  
    334334    void setStatisticsCacheMaxAgeCap(double seconds);
    335335    void statisticsResetToConsistentState(object completionHandler);
     336    boolean hasStatisticsIsolatedSession(DOMString hostName);
    336337
    337338    // Injected bundle form client.
  • trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp

    r248526 r248640  
    20672067}
    20682068
     2069bool TestRunner::hasStatisticsIsolatedSession(JSStringRef hostName)
     2070{
     2071    auto messageName = adoptWK(WKStringCreateWithUTF8CString("HasStatisticsIsolatedSession"));
     2072    auto messageBody = adoptWK(WKStringCreateWithJSString(hostName));
     2073    WKTypeRef returnData = nullptr;
     2074    WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
     2075    ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
     2076    return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
     2077}
     2078
    20692079void TestRunner::statisticsCallClearThroughWebsiteDataRemovalCallback()
    20702080{
  • trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h

    r248526 r248640  
    432432    bool isStatisticsHasLocalStorage(JSStringRef hostName);
    433433    void setStatisticsCacheMaxAgeCap(double seconds);
     434    bool hasStatisticsIsolatedSession(JSStringRef hostName);
    434435    void statisticsResetToConsistentState(JSValueRef completionHandler);
    435436    void statisticsCallDidResetToConsistentStateCallback();
  • trunk/Tools/WebKitTestRunner/TestController.cpp

    r248526 r248640  
    35123512}
    35133513
     3514bool TestController::hasStatisticsIsolatedSession(WKStringRef host)
     3515{
     3516    auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
     3517    ResourceStatisticsCallbackContext context(*this);
     3518    WKWebsiteDataStoreStatisticsHasIsolatedSession(dataStore, host, &context, resourceStatisticsBooleanResultCallback);
     3519    runUntil(context.done, noTimeout);
     3520    return context.result;
     3521}
     3522
    35143523void TestController::statisticsResetToConsistentState()
    35153524{
  • trunk/Tools/WebKitTestRunner/TestController.h

    r248526 r248640  
    245245    bool isStatisticsHasLocalStorage(WKStringRef hostName);
    246246    void setStatisticsCacheMaxAgeCap(double seconds);
     247    bool hasStatisticsIsolatedSession(WKStringRef hostName);
    247248    void statisticsResetToConsistentState();
    248249
  • trunk/Tools/WebKitTestRunner/TestInvocation.cpp

    r248526 r248640  
    14631463    }
    14641464
     1465    if (WKStringIsEqualToUTF8CString(messageName, "HasStatisticsIsolatedSession")) {
     1466        ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
     1467       
     1468        WKStringRef hostName = static_cast<WKStringRef>(messageBody);
     1469        bool hasIsolatedSession = TestController::singleton().hasStatisticsIsolatedSession(hostName);
     1470        auto result = adoptWK(WKBooleanCreate(hasIsolatedSession));
     1471        return result;
     1472    }
     1473   
    14651474    if (WKStringIsEqualToUTF8CString(messageName, "RemoveAllSessionCredentials")) {
    14661475        TestController::singleton().removeAllSessionCredentials();
Note: See TracChangeset for help on using the changeset viewer.