Title: [269807] trunk/Source
Revision
269807
Author
[email protected]
Date
2020-11-13 16:55:05 -0800 (Fri, 13 Nov 2020)

Log Message

Can't login to Microsoft Teams
https://bugs.webkit.org/show_bug.cgi?id=218778
<rdar://problem/36331568>

Reviewed by John Wilander.

This is a temporary quirk to assist a high-traffic website while they
complete the large task of migrating away from login flows that
require third party cookies. This quirk will be removed when the site
is updated.

Create a quirk to call the Storage Access API on behalf of Microsoft.

Source/WebCore:

No new tests, site-specific quirk.

* dom/Element.cpp:
(WebCore::Element::dispatchMouseEvent):
Pass additional parameters to be able to dispatch a synthetic click
if storage access is granted.

* loader/ResourceLoadObserver.h:
(WebCore::ResourceLoadObserver::setDomainsWithCrossPageStorageAccess):
(WebCore::ResourceLoadObserver::hasCrossPageStorageAccess const):
Store domains in the web process to avoid async calls to the network
process.

(WebCore::isMicrosoftLoginElement):
(WebCore::isMicrosoftDomain):
* page/Quirks.cpp:
(WebCore::Quirks::triggerOptionalStorageAccessQuirk const):
This is the quirk.

* page/Quirks.h:
* platform/network/NetworkStorageSession.cpp:
(WebCore::NetworkStorageSession::setDomainsWithCrossPageStorageAccess):
(WebCore::NetworkStorageSession::grantCrossPageStorageAccess):
(WebCore::NetworkStorageSession::hasStorageAccess const):
(WebCore::NetworkStorageSession::grantStorageAccess):
(WebCore::NetworkStorageSession::removeAllStorageAccess):
(WebCore::NetworkStorageSession::storageAccessQuirks):
(WebCore::NetworkStorageSession::canRequestStorageAccessForLoginPurposesWithoutPriorUserInteraction):
(WebCore::NetworkStorageSession::loginDomainForFirstParty):
(WebCore::NetworkStorageSession::mapToTopDomain):
The user might go directly to login.live.com to sign in to Microsoft
Teams, but may not have seen the Storage Access prompt. In this case,
we should map live.com to microsoft.com and request storage access for
microsoftonline.com under microsoft.com. Since login.live.com is used
for other Microsoft login flows besides Teams, a user may have to
grant storage access to microsoftonline.com even when it is not needed
to complete the login. But this guarantees they will always be
successfully logged into all Microsoft accounts.

* platform/network/NetworkStorageSession.h:
In order for the user to stay logged in between sessions, we should
update NetworkStorageSession to grant storage access based on values
stored in the ITP database for quirk domains.

Source/WebKit:

* NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
(WebKit::ResourceLoadStatisticsDatabaseStore::grantStorageAccess):
(WebKit::ResourceLoadStatisticsDatabaseStore::grantStorageAccessInternal):
Relax the requirement for user interaction for a specific third party
needing cookies for authentication purposes.

(WebKit::ResourceLoadStatisticsDatabaseStore::clear):
(WebKit::ResourceLoadStatisticsDatabaseStore::cookieAccess):
Relax the requirement for user interaction for a specific third party
needing cookies for authentication purposes.

(WebKit::ResourceLoadStatisticsDatabaseStore::domainsWithStorageAccess const):
(WebKit::ResourceLoadStatisticsDatabaseStore::updateCookieBlocking):
* NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
* NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp:
(WebKit::ResourceLoadStatisticsMemoryStore::clear):
(WebKit::ResourceLoadStatisticsMemoryStore::updateCookieBlocking):
* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::requestStorageAccessEphemeral):
Relax user interaction for reasons above.

(WebKit::WebResourceLoadStatisticsStore::callUpdatePrevalentDomainsToBlockCookiesForHandler):
* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
(WebKit::RegistrableDomainsToBlockCookiesFor::isolatedCopy const):
* Shared/WebProcessDataStoreParameters.h:
(WebKit::WebProcessDataStoreParameters::encode const):
(WebKit::WebProcessDataStoreParameters::decode):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::setDomainsWithCrossPageStorageAccess):
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/Network/NetworkProcessProxy.messages.in:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::webProcessDataStoreParameters):
(WebKit::WebProcessPool::setDomainsWithCrossPageStorageAccess):
* UIProcess/WebProcessPool.h:
* WebProcess/WebCoreSupport/WebResourceLoadObserver.cpp:
(WebKit::WebResourceLoadObserver::hasCrossPageStorageAccess const):
(WebKit::WebResourceLoadObserver::setDomainsWithCrossPageStorageAccess):
* WebProcess/WebCoreSupport/WebResourceLoadObserver.h:
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::setWebsiteDataStoreParameters):
(WebKit::WebProcess::setDomainsWithCrossPageStorageAccess):
Add quirk'd domains to have page level storage access to be able to
use document.cookie.

* WebProcess/WebProcess.h:
* WebProcess/WebProcess.messages.in:
Forward domains with the storage access quirk to the web process to
avoid an async call to the network process.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (269806 => 269807)


--- trunk/Source/WebCore/ChangeLog	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebCore/ChangeLog	2020-11-14 00:55:05 UTC (rev 269807)
@@ -1,3 +1,62 @@
+2020-11-13  Kate Cheney  <[email protected]>
+
+        Can't login to Microsoft Teams
+        https://bugs.webkit.org/show_bug.cgi?id=218778
+        <rdar://problem/36331568>
+
+        Reviewed by John Wilander.
+
+        This is a temporary quirk to assist a high-traffic website while they
+        complete the large task of migrating away from login flows that
+        require third party cookies. This quirk will be removed when the site
+        is updated.
+
+        Create a quirk to call the Storage Access API on behalf of Microsoft.
+
+        No new tests, site-specific quirk.
+
+        * dom/Element.cpp:
+        (WebCore::Element::dispatchMouseEvent):
+        Pass additional parameters to be able to dispatch a synthetic click
+        if storage access is granted.
+
+        * loader/ResourceLoadObserver.h:
+        (WebCore::ResourceLoadObserver::setDomainsWithCrossPageStorageAccess):
+        (WebCore::ResourceLoadObserver::hasCrossPageStorageAccess const):
+        Store domains in the web process to avoid async calls to the network
+        process.
+
+        (WebCore::isMicrosoftLoginElement):
+        (WebCore::isMicrosoftDomain):
+        * page/Quirks.cpp:
+        (WebCore::Quirks::triggerOptionalStorageAccessQuirk const):
+        This is the quirk.
+
+        * page/Quirks.h:
+        * platform/network/NetworkStorageSession.cpp:
+        (WebCore::NetworkStorageSession::setDomainsWithCrossPageStorageAccess):
+        (WebCore::NetworkStorageSession::grantCrossPageStorageAccess):
+        (WebCore::NetworkStorageSession::hasStorageAccess const):
+        (WebCore::NetworkStorageSession::grantStorageAccess):
+        (WebCore::NetworkStorageSession::removeAllStorageAccess):
+        (WebCore::NetworkStorageSession::storageAccessQuirks):
+        (WebCore::NetworkStorageSession::canRequestStorageAccessForLoginPurposesWithoutPriorUserInteraction):
+        (WebCore::NetworkStorageSession::loginDomainForFirstParty):
+        (WebCore::NetworkStorageSession::mapToTopDomain):
+        The user might go directly to login.live.com to sign in to Microsoft
+        Teams, but may not have seen the Storage Access prompt. In this case,
+        we should map live.com to microsoft.com and request storage access for
+        microsoftonline.com under microsoft.com. Since login.live.com is used
+        for other Microsoft login flows besides Teams, a user may have to
+        grant storage access to microsoftonline.com even when it is not needed
+        to complete the login. But this guarantees they will always be
+        successfully logged into all Microsoft accounts.
+
+        * platform/network/NetworkStorageSession.h:
+        In order for the user to stay logged in between sessions, we should
+        update NetworkStorageSession to grant storage access based on values
+        stored in the ITP database for quirk domains.
+
 2020-11-13  Brian Burg  <[email protected]>
 
         REGRESSION(r269701): inspector/console/webcore-logging.html is crashing

Modified: trunk/Source/WebCore/dom/DocumentStorageAccess.cpp (269806 => 269807)


--- trunk/Source/WebCore/dom/DocumentStorageAccess.cpp	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebCore/dom/DocumentStorageAccess.cpp	2020-11-14 00:55:05 UTC (rev 269807)
@@ -36,6 +36,7 @@
 #include "FrameLoader.h"
 #include "FrameLoaderClient.h"
 #include "JSDOMPromiseDeferred.h"
+#include "NetworkStorageSession.h"
 #include "Page.h"
 #include "RegistrableDomain.h"
 #include "SecurityOrigin.h"
@@ -265,7 +266,9 @@
     ASSERT(m_document.settings().storageAccessAPIEnabled());
     RELEASE_ASSERT(m_document.frame() && m_document.frame()->page());
 
-    m_document.frame()->page()->chrome().client().requestStorageAccess(WTFMove(requestingDomain), RegistrableDomain::uncheckedCreateFromHost(m_document.topDocument().securityOrigin().host()), *m_document.frame(), m_storageAccessScope, [this, weakThis = makeWeakPtr(*this), completionHandler = WTFMove(completionHandler)] (RequestStorageAccessResult result) mutable {
+    auto topFrameDomain = NetworkStorageSession::mapToTopDomain(RegistrableDomain(m_document.topDocument().url()));
+
+    m_document.frame()->page()->chrome().client().requestStorageAccess(WTFMove(requestingDomain), WTFMove(topFrameDomain), *m_document.frame(), m_storageAccessScope, [this, weakThis = makeWeakPtr(*this), completionHandler = WTFMove(completionHandler)] (RequestStorageAccessResult result) mutable {
         if (!weakThis)
             return;
 

Modified: trunk/Source/WebCore/dom/Element.cpp (269806 => 269807)


--- trunk/Source/WebCore/dom/Element.cpp	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebCore/dom/Element.cpp	2020-11-14 00:55:05 UTC (rev 269807)
@@ -389,7 +389,7 @@
     if (dispatchPointerEventIfNeeded(*this, mouseEvent.get(), platformEvent, didNotSwallowEvent) == ShouldIgnoreMouseEvent::Yes)
         return false;
 
-    if (Quirks::StorageAccessResult::ShouldCancelEvent == document().quirks().triggerOptionalStorageAccessQuirk(*this, eventType))
+    if (Quirks::StorageAccessResult::ShouldCancelEvent == document().quirks().triggerOptionalStorageAccessQuirk(*this, platformEvent, eventType, detail, relatedTarget))
         return false;
 
     ASSERT(!mouseEvent->target() || mouseEvent->target() != relatedTarget);

Modified: trunk/Source/WebCore/loader/ResourceLoadObserver.h (269806 => 269807)


--- trunk/Source/WebCore/loader/ResourceLoadObserver.h	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebCore/loader/ResourceLoadObserver.h	2020-11-14 00:55:05 UTC (rev 269807)
@@ -39,6 +39,9 @@
 class ResourceLoadObserver {
     WTF_MAKE_FAST_ALLOCATED;
 public:
+    using TopFrameDomain = WebCore::RegistrableDomain;
+    using SubResourceDomain = WebCore::RegistrableDomain;
+
     // https://fetch.spec.whatwg.org/#request-destination-script-like
     enum class FetchDestinationIsScriptLike : bool { Yes, No };
 
@@ -65,6 +68,8 @@
     virtual bool hasStatistics() const { return false; }
 
     virtual void setDomainsWithUserInteraction(HashSet<RegistrableDomain>&&) { }
+    virtual void setDomainsWithCrossPageStorageAccess(HashMap<TopFrameDomain, SubResourceDomain>&&, CompletionHandler<void()>&& completionHandler) { completionHandler(); }
+    virtual bool hasCrossPageStorageAccess(const SubResourceDomain&, const TopFrameDomain&) const { return false; }
     virtual bool hasHadUserInteraction(const RegistrableDomain&) const { return false; }
 };
     

Modified: trunk/Source/WebCore/page/Quirks.cpp (269806 => 269807)


--- trunk/Source/WebCore/page/Quirks.cpp	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebCore/page/Quirks.cpp	2020-11-14 00:55:05 UTC (rev 269807)
@@ -42,6 +42,7 @@
 #include "JSEventListener.h"
 #include "LayoutUnit.h"
 #include "NamedNodeMap.h"
+#include "NetworkStorageSession.h"
 #include "ResourceLoadObserver.h"
 #include "RuntimeEnabledFeatures.h"
 #include "SVGPathElement.h"
@@ -961,9 +962,26 @@
 
     return false;
 }
+
+static bool isMicrosoftLoginElement(const Element& element)
+{
+    if (!element.hasClass())
+        return false;
+
+    auto& classNames = element.classNames();
+    return classNames.contains("glyph_signIn_circle") || classNames.contains("mectrl_headertext") || classNames.contains("mectrl_header") || classNames.contains("ext-button primary") || classNames.contains("ext-primary");
+}
+
+static bool isMicrosoftDomain(const RegistrableDomain& domain)
+{
+    static NeverDestroyed<RegistrableDomain> microsoftDotCom = RegistrableDomain::uncheckedCreateFromRegistrableDomainString("microsoft.com"_s);
+    static NeverDestroyed<RegistrableDomain> liveDotCom = RegistrableDomain::uncheckedCreateFromRegistrableDomainString("live.com"_s);
+
+    return domain == microsoftDotCom || domain == liveDotCom;
+}
 #endif
 
-Quirks::StorageAccessResult Quirks::triggerOptionalStorageAccessQuirk(const Element& element, const AtomString& eventType) const
+Quirks::StorageAccessResult Quirks::triggerOptionalStorageAccessQuirk(Element& element, const PlatformMouseEvent& platformEvent, const AtomString& eventType, int detail, Element* relatedTarget) const
 {
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     if (!needsQuirks())
@@ -1033,10 +1051,32 @@
                 return Quirks::StorageAccessResult::ShouldCancelEvent;
             }
         }
+
+        // Microsoft Teams login case.
+        // FIXME(218779): Remove this quirk once microsoft.com completes their login flow redesign.
+        if (isMicrosoftDomain(domain) && isMicrosoftLoginElement(element)) {
+            auto firstPartyDomain = NetworkStorageSession::mapToTopDomain(RegistrableDomain::uncheckedCreateFromHost(m_document->topDocument().securityOrigin().host()));
+            if (auto loginDomain = NetworkStorageSession::loginDomainForFirstParty(firstPartyDomain)) {
+                if (!ResourceLoadObserver::shared().hasCrossPageStorageAccess(*loginDomain, firstPartyDomain)) {
+                    DocumentStorageAccess::requestStorageAccessForNonDocumentQuirk(*m_document, WTFMove(*loginDomain), [firstPartyDomain, loginDomain, &element, platformEvent, eventType, detail, relatedTarget](StorageAccessWasGranted storageAccessGranted) mutable {
+                        if (storageAccessGranted == StorageAccessWasGranted::Yes) {
+                            ResourceLoadObserver::shared().setDomainsWithCrossPageStorageAccess({{ firstPartyDomain, *loginDomain }}, [&element, platformEvent, eventType, detail, relatedTarget] {
+                                element.dispatchMouseEvent(platformEvent, eventType, detail, relatedTarget);
+                            });
+                        }
+                    });
+                    return Quirks::StorageAccessResult::ShouldCancelEvent;
+                }
+            }
+            return Quirks::StorageAccessResult::ShouldNotCancelEvent;
+        }
     }
 #else
     UNUSED_PARAM(element);
+    UNUSED_PARAM(platformEvent);
     UNUSED_PARAM(eventType);
+    UNUSED_PARAM(detail);
+    UNUSED_PARAM(relatedTarget);
 #endif
     return Quirks::StorageAccessResult::ShouldNotCancelEvent;
 }

Modified: trunk/Source/WebCore/page/Quirks.h (269806 => 269807)


--- trunk/Source/WebCore/page/Quirks.h	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebCore/page/Quirks.h	2020-11-14 00:55:05 UTC (rev 269807)
@@ -37,6 +37,7 @@
 class HTMLElement;
 class HTMLVideoElement;
 class LayoutUnit;
+class PlatformMouseEvent;
 
 class Quirks {
     WTF_MAKE_NONCOPYABLE(Quirks); WTF_MAKE_FAST_ALLOCATED;
@@ -112,7 +113,7 @@
     bool shouldAvoidPastingImagesAsWebContent() const;
 
     enum StorageAccessResult : bool { ShouldNotCancelEvent, ShouldCancelEvent };
-    StorageAccessResult triggerOptionalStorageAccessQuirk(const Element&, const AtomString& eventType) const;
+    StorageAccessResult triggerOptionalStorageAccessQuirk(Element&, const PlatformMouseEvent&, const AtomString& eventType, int, Element*) const;
 
     bool needsVP9FullRangeFlagQuirk() const;
     bool needsHDRPixelDepthQuirk() const;
@@ -154,4 +155,4 @@
     mutable Optional<bool> m_needsBlackFullscreenBackgroundQuirk;
 };
 
-}
+} // namespace WebCore

Modified: trunk/Source/WebCore/platform/network/NetworkStorageSession.cpp (269806 => 269807)


--- trunk/Source/WebCore/platform/network/NetworkStorageSession.cpp	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebCore/platform/network/NetworkStorageSession.cpp	2020-11-14 00:55:05 UTC (rev 269807)
@@ -209,6 +209,18 @@
     m_registrableDomainsWithUserInteractionAsFirstParty.add(domains.begin(), domains.end());
 }
 
+void NetworkStorageSession::setDomainsWithCrossPageStorageAccess(const HashMap<TopFrameDomain, SubResourceDomain>& domains)
+{
+    m_pairsGrantedCrossPageStorageAccess.clear();
+    for (auto& topFrameDomain : domains.keys())
+        grantCrossPageStorageAccess(topFrameDomain, domains.get(topFrameDomain));
+}
+
+void NetworkStorageSession::grantCrossPageStorageAccess(const TopFrameDomain& topFrameDomain, const SubResourceDomain& resourceDomain)
+{
+    m_pairsGrantedCrossPageStorageAccess.add(topFrameDomain, resourceDomain);
+}
+
 bool NetworkStorageSession::hasStorageAccess(const RegistrableDomain& resourceDomain, const RegistrableDomain& firstPartyDomain, Optional<FrameIdentifier> frameID, PageIdentifier pageID) const
 {
     if (frameID) {
@@ -227,6 +239,10 @@
             if (it != pagesGrantedIterator->value.end() && it->value == resourceDomain)
                 return true;
         }
+
+        auto it = m_pairsGrantedCrossPageStorageAccess.find(firstPartyDomain);
+        if (it != m_pairsGrantedCrossPageStorageAccess.end() && it->value == resourceDomain)
+            return true;
     }
 
     return false;
@@ -244,6 +260,11 @@
     
 void NetworkStorageSession::grantStorageAccess(const RegistrableDomain& resourceDomain, const RegistrableDomain& firstPartyDomain, Optional<FrameIdentifier> frameID, PageIdentifier pageID)
 {
+    if (NetworkStorageSession::loginDomainMatchesRequestingDomain(firstPartyDomain, resourceDomain)) {
+        grantCrossPageStorageAccess(firstPartyDomain, resourceDomain);
+        return;
+    }
+
     if (!frameID) {
         if (firstPartyDomain.isEmpty())
             return;
@@ -297,6 +318,7 @@
 {
     m_pagesGrantedStorageAccess.clear();
     m_framesGrantedStorageAccess.clear();
+    m_pairsGrantedCrossPageStorageAccess.clear();
 }
 
 void NetworkStorageSession::setCacheMaxAgeCapForPrevalentResources(Seconds seconds)
@@ -351,6 +373,52 @@
 
     return m_ageCapForClientSideCookies;
 }
+
+HashMap<RegistrableDomain, RegistrableDomain>& NetworkStorageSession::storageAccessQuirks()
+{
+    static NeverDestroyed<HashMap<RegistrableDomain, RegistrableDomain>> map = [] {
+        HashMap<RegistrableDomain, RegistrableDomain> map;
+        map.add(RegistrableDomain::uncheckedCreateFromRegistrableDomainString("microsoft.com"),
+            RegistrableDomain::uncheckedCreateFromRegistrableDomainString("microsoftonline.com"_s));
+        return map;
+    }();
+    return map.get();
+}
+
+bool NetworkStorageSession::loginDomainMatchesRequestingDomain(const TopFrameDomain& topFrameDomain, const SubResourceDomain& resourceDomain)
+{
+    auto loginDomain = WebCore::NetworkStorageSession::loginDomainForFirstParty(topFrameDomain);
+    return loginDomain && resourceDomain == loginDomain;
+}
+
+bool NetworkStorageSession::canRequestStorageAccessForLoginPurposesWithoutPriorUserInteraction(const SubResourceDomain& resourceDomain, const TopFrameDomain& topFrameDomain)
+{
+    return loginDomainMatchesRequestingDomain(topFrameDomain, resourceDomain);
+}
+
+Optional<RegistrableDomain> NetworkStorageSession::loginDomainForFirstParty(const RegistrableDomain& topFrameDomain)
+{
+    auto it = storageAccessQuirks().find(topFrameDomain);
+    if (it != storageAccessQuirks().end())
+        return it->value;
+    return WTF::nullopt;
+}
+
+RegistrableDomain NetworkStorageSession::mapToTopDomain(const RegistrableDomain& domainToMap)
+{
+    static NeverDestroyed<HashMap<RegistrableDomain, RegistrableDomain>> map = [] {
+        HashMap<RegistrableDomain, RegistrableDomain> map;
+        map.add(RegistrableDomain::uncheckedCreateFromRegistrableDomainString("live.com"),
+            RegistrableDomain::uncheckedCreateFromRegistrableDomainString("microsoft.com"_s));
+        return map;
+    }();
+
+    auto it = map.get().find(domainToMap);
+    if (it != map.get().end())
+        return it->value;
+    return domainToMap;
+}
+
 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
 
 }

Modified: trunk/Source/WebCore/platform/network/NetworkStorageSession.h (269806 => 269807)


--- trunk/Source/WebCore/platform/network/NetworkStorageSession.h	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebCore/platform/network/NetworkStorageSession.h	2020-11-14 00:55:05 UTC (rev 269807)
@@ -199,6 +199,8 @@
     WEBCORE_EXPORT void setPrevalentDomainsToBlockAndDeleteCookiesFor(const Vector<RegistrableDomain>&);
     WEBCORE_EXPORT void setPrevalentDomainsToBlockButKeepCookiesFor(const Vector<RegistrableDomain>&);
     WEBCORE_EXPORT void setDomainsWithUserInteractionAsFirstParty(const Vector<RegistrableDomain>&);
+    WEBCORE_EXPORT void setDomainsWithCrossPageStorageAccess(const HashMap<TopFrameDomain, SubResourceDomain>&);
+    WEBCORE_EXPORT void grantCrossPageStorageAccess(const TopFrameDomain&, const SubResourceDomain&);
     WEBCORE_EXPORT void setAgeCapForClientSideCookies(Optional<Seconds>);
     WEBCORE_EXPORT bool hasStorageAccess(const RegistrableDomain& resourceDomain, const RegistrableDomain& firstPartyDomain, Optional<FrameIdentifier>, PageIdentifier) const;
     WEBCORE_EXPORT Vector<String> getAllStorageAccessEntries() const;
@@ -212,6 +214,12 @@
     WEBCORE_EXPORT void didCommitCrossSiteLoadWithDataTransferFromPrevalentResource(const RegistrableDomain& toDomain, PageIdentifier);
     WEBCORE_EXPORT void resetCrossSiteLoadsWithLinkDecorationForTesting();
     WEBCORE_EXPORT void setThirdPartyCookieBlockingMode(ThirdPartyCookieBlockingMode);
+
+    WEBCORE_EXPORT static HashMap<RegistrableDomain, RegistrableDomain>& storageAccessQuirks();
+    WEBCORE_EXPORT static bool canRequestStorageAccessForLoginPurposesWithoutPriorUserInteraction(const SubResourceDomain&, const TopFrameDomain&);
+    WEBCORE_EXPORT static Optional<RegistrableDomain> loginDomainForFirstParty(const RegistrableDomain&);
+    WEBCORE_EXPORT static bool loginDomainMatchesRequestingDomain(const TopFrameDomain&, const SubResourceDomain&);
+    WEBCORE_EXPORT static RegistrableDomain mapToTopDomain(const RegistrableDomain&);
 #endif
     
 #if ENABLE(APP_BOUND_DOMAINS)
@@ -271,6 +279,7 @@
     HashSet<RegistrableDomain> m_registrableDomainsWithUserInteractionAsFirstParty;
     HashMap<PageIdentifier, HashMap<FrameIdentifier, RegistrableDomain>> m_framesGrantedStorageAccess;
     HashMap<PageIdentifier, HashMap<RegistrableDomain, RegistrableDomain>> m_pagesGrantedStorageAccess;
+    HashMap<TopFrameDomain, SubResourceDomain> m_pairsGrantedCrossPageStorageAccess;
     Optional<Seconds> m_cacheMaxAgeCapForPrevalentResources { };
     Optional<Seconds> m_ageCapForClientSideCookies { };
     Optional<Seconds> m_ageCapForClientSideCookiesShort { };

Modified: trunk/Source/WebKit/ChangeLog (269806 => 269807)


--- trunk/Source/WebKit/ChangeLog	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/ChangeLog	2020-11-14 00:55:05 UTC (rev 269807)
@@ -1,3 +1,68 @@
+2020-11-13  Kate Cheney  <[email protected]>
+
+        Can't login to Microsoft Teams
+        https://bugs.webkit.org/show_bug.cgi?id=218778
+        <rdar://problem/36331568>
+
+        Reviewed by John Wilander.
+
+        This is a temporary quirk to assist a high-traffic website while they
+        complete the large task of migrating away from login flows that
+        require third party cookies. This quirk will be removed when the site
+        is updated.
+
+        Create a quirk to call the Storage Access API on behalf of Microsoft.
+
+        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
+        (WebKit::ResourceLoadStatisticsDatabaseStore::grantStorageAccess):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::grantStorageAccessInternal):
+        Relax the requirement for user interaction for a specific third party
+        needing cookies for authentication purposes.
+
+        (WebKit::ResourceLoadStatisticsDatabaseStore::clear):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::cookieAccess):
+        Relax the requirement for user interaction for a specific third party
+        needing cookies for authentication purposes.
+
+        (WebKit::ResourceLoadStatisticsDatabaseStore::domainsWithStorageAccess const):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::updateCookieBlocking):
+        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
+        * NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp:
+        (WebKit::ResourceLoadStatisticsMemoryStore::clear):
+        (WebKit::ResourceLoadStatisticsMemoryStore::updateCookieBlocking):
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::requestStorageAccessEphemeral):
+        Relax user interaction for reasons above.
+
+        (WebKit::WebResourceLoadStatisticsStore::callUpdatePrevalentDomainsToBlockCookiesForHandler):
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
+        (WebKit::RegistrableDomainsToBlockCookiesFor::isolatedCopy const):
+        * Shared/WebProcessDataStoreParameters.h:
+        (WebKit::WebProcessDataStoreParameters::encode const):
+        (WebKit::WebProcessDataStoreParameters::decode):
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::setDomainsWithCrossPageStorageAccess):
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/Network/NetworkProcessProxy.messages.in:
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::webProcessDataStoreParameters):
+        (WebKit::WebProcessPool::setDomainsWithCrossPageStorageAccess):
+        * UIProcess/WebProcessPool.h:
+        * WebProcess/WebCoreSupport/WebResourceLoadObserver.cpp:
+        (WebKit::WebResourceLoadObserver::hasCrossPageStorageAccess const):
+        (WebKit::WebResourceLoadObserver::setDomainsWithCrossPageStorageAccess):
+        * WebProcess/WebCoreSupport/WebResourceLoadObserver.h:
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::setWebsiteDataStoreParameters):
+        (WebKit::WebProcess::setDomainsWithCrossPageStorageAccess):
+        Add quirk'd domains to have page level storage access to be able to
+        use document.cookie.
+
+        * WebProcess/WebProcess.h:
+        * WebProcess/WebProcess.messages.in:
+        Forward domains with the storage access quirk to the web process to
+        avoid an async call to the network process.
+
 2020-11-13  Sam Weinig  <[email protected]>
 
         Move some more WebKit and WebKitLegacy preferences bound to Settings to WebPreferences.yaml

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp (269806 => 269807)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp	2020-11-14 00:55:05 UTC (rev 269807)
@@ -1324,7 +1324,10 @@
             return;
         }
         ASSERT(subFrameStatus.first == AddedRecord::No);
-        ASSERT(hasHadUserInteraction(subFrameDomain, OperatingDatesWindow::Long));
+#if ASSERT_ENABLED
+        if (!NetworkStorageSession::canRequestStorageAccessForLoginPurposesWithoutPriorUserInteraction(subFrameDomain, topFrameDomain))
+            ASSERT(hasHadUserInteraction(subFrameDomain, OperatingDatesWindow::Long));
+#endif
         insertDomainRelationshipList(storageAccessUnderTopFrameDomainsQuery, HashSet<RegistrableDomain>({ topFrameDomain }), *subFrameStatus.second);
     }
 
@@ -1348,7 +1351,10 @@
             return;
         }
         ASSERT(subFrameStatus.first == AddedRecord::No);
-        ASSERT(hasHadUserInteraction(subFrameDomain, OperatingDatesWindow::Long));
+#if ASSERT_ENABLED
+        if (!NetworkStorageSession::canRequestStorageAccessForLoginPurposesWithoutPriorUserInteraction(subFrameDomain, topFrameDomain))
+            ASSERT(hasHadUserInteraction(subFrameDomain, OperatingDatesWindow::Long));
+#endif
         ASSERT(hasUserGrantedStorageAccessThroughPrompt(*subFrameStatus.second, topFrameDomain) == StorageAccessPromptWasShown::Yes);
 #endif
         setUserInteraction(subFrameDomain, true, WallTime::now());
@@ -2003,7 +2009,7 @@
     removeAllStorageAccess([callbackAggregator] { });
 
     auto registrableDomainsToBlockAndDeleteCookiesFor = ensurePrevalentResourcesForDebugMode();
-    RegistrableDomainsToBlockCookiesFor domainsToBlock { registrableDomainsToBlockAndDeleteCookiesFor, { }, { } };
+    RegistrableDomainsToBlockCookiesFor domainsToBlock { registrableDomainsToBlockAndDeleteCookiesFor, { }, { }, { } };
     updateCookieBlockingForDomains(domainsToBlock, [callbackAggregator] { });
 }
 
@@ -2036,7 +2042,7 @@
     if (!areAllThirdPartyCookiesBlockedUnder(topFrameDomain) && !isPrevalent)
         return CookieAccess::BasedOnCookiePolicy;
 
-    if (!hadUserInteraction)
+    if (!NetworkStorageSession::canRequestStorageAccessForLoginPurposesWithoutPriorUserInteraction(subresourceDomain, topFrameDomain) && !hadUserInteraction)
         return CookieAccess::CannotRequest;
 
     return CookieAccess::OnlyIfGranted;
@@ -2103,6 +2109,22 @@
     return results;
 }
 
+HashMap<TopFrameDomain, SubResourceDomain> ResourceLoadStatisticsDatabaseStore::domainsWithStorageAccess() const
+{
+    ASSERT(!RunLoop::isMain());
+
+    HashMap<WebCore::RegistrableDomain, WebCore::RegistrableDomain> results;
+    SQLiteStatement statement(m_database, "SELECT subFrameDomain, registrableDomain FROM (SELECT o.registrableDomain as subFrameDomain, s.topLevelDomainID as topLevelDomainID FROM ObservedDomains as o INNER JOIN StorageAccessUnderTopFrameDomains as s WHERE o.domainID = s.domainID) as z INNER JOIN ObservedDomains ON domainID = z.topLevelDomainID;"_s);
+
+    if (statement.prepare() != SQLITE_OK)
+        return results;
+
+    while (statement.step() == SQLITE_ROW)
+        results.add(RegistrableDomain::uncheckedCreateFromRegistrableDomainString(statement.getColumnText(1)), RegistrableDomain::uncheckedCreateFromRegistrableDomainString(statement.getColumnText(0)));
+
+    return results;
+}
+
 void ResourceLoadStatisticsDatabaseStore::updateCookieBlocking(CompletionHandler<void()>&& completionHandler)
 {
     ASSERT(!RunLoop::isMain());
@@ -2110,13 +2132,14 @@
     auto domainsToBlockAndDeleteCookiesFor = this->domainsToBlockAndDeleteCookiesFor();
     auto domainsToBlockButKeepCookiesFor = this->domainsToBlockButKeepCookiesFor();
     auto domainsWithUserInteractionAsFirstParty = this->domainsWithUserInteractionAsFirstParty();
+    auto domainsWithStorageAccess = this->domainsWithStorageAccess();
 
-    if (domainsToBlockAndDeleteCookiesFor.isEmpty() && domainsToBlockButKeepCookiesFor.isEmpty() && domainsWithUserInteractionAsFirstParty.isEmpty()) {
+    if (domainsToBlockAndDeleteCookiesFor.isEmpty() && domainsToBlockButKeepCookiesFor.isEmpty() && domainsWithUserInteractionAsFirstParty.isEmpty() && domainsWithStorageAccess.isEmpty()) {
         completionHandler();
         return;
     }
 
-    RegistrableDomainsToBlockCookiesFor domainsToBlock { domainsToBlockAndDeleteCookiesFor, domainsToBlockButKeepCookiesFor, domainsWithUserInteractionAsFirstParty };
+    RegistrableDomainsToBlockCookiesFor domainsToBlock { domainsToBlockAndDeleteCookiesFor, domainsToBlockButKeepCookiesFor, domainsWithUserInteractionAsFirstParty, domainsWithStorageAccess };
 
     if (debugLoggingEnabled() && (!domainsToBlockAndDeleteCookiesFor.isEmpty() || !domainsToBlockButKeepCookiesFor.isEmpty()))
         debugLogDomainsInBatches("Applying cross-site tracking restrictions", domainsToBlock);

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h (269806 => 269807)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h	2020-11-14 00:55:05 UTC (rev 269807)
@@ -159,6 +159,7 @@
     Vector<RegistrableDomain> domainsToBlockAndDeleteCookiesFor() const;
     Vector<RegistrableDomain> domainsToBlockButKeepCookiesFor() const;
     Vector<RegistrableDomain> domainsWithUserInteractionAsFirstParty() const;
+    HashMap<TopFrameDomain, SubResourceDomain> domainsWithStorageAccess() const;
 
     struct DomainData {
         unsigned domainID;

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp (269806 => 269807)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp	2020-11-14 00:55:05 UTC (rev 269807)
@@ -785,7 +785,7 @@
     removeAllStorageAccess([callbackAggregator] { });
 
     auto registrableDomainsToBlockAndDeleteCookiesFor = ensurePrevalentResourcesForDebugMode();
-    RegistrableDomainsToBlockCookiesFor domainsToBlock { registrableDomainsToBlockAndDeleteCookiesFor, { }, { } };
+    RegistrableDomainsToBlockCookiesFor domainsToBlock { registrableDomainsToBlockAndDeleteCookiesFor, { }, { }, { }};
     updateCookieBlockingForDomains(domainsToBlock, [callbackAggregator] { });
 }
 
@@ -838,7 +838,7 @@
         return;
     }
 
-    RegistrableDomainsToBlockCookiesFor domainsToBlock { domainsToBlockAndDeleteCookiesFor, domainsToBlockButKeepCookiesFor, domainsWithUserInteractionAsFirstParty };
+    RegistrableDomainsToBlockCookiesFor domainsToBlock { domainsToBlockAndDeleteCookiesFor, domainsToBlockButKeepCookiesFor, domainsWithUserInteractionAsFirstParty, { } };
 
     if (debugLoggingEnabled() && (!domainsToBlockAndDeleteCookiesFor.isEmpty() || !domainsToBlockButKeepCookiesFor.isEmpty()))
         debugLogDomainsInBatches("Applying cross-site tracking restrictions", domainsToBlock);

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp (269806 => 269807)


--- trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp	2020-11-14 00:55:05 UTC (rev 269807)
@@ -470,7 +470,7 @@
 {
     ASSERT(isEphemeral());
 
-    if (!m_networkSession || !m_domainsWithEphemeralUserInteraction.contains(subFrameDomain))
+    if (!m_networkSession || (!m_domainsWithEphemeralUserInteraction.contains(subFrameDomain) && !NetworkStorageSession::canRequestStorageAccessForLoginPurposesWithoutPriorUserInteraction(subFrameDomain, topFrameDomain)))
         return completionHandler({ StorageAccessWasGranted::No, StorageAccessPromptWasShown::No, scope, topFrameDomain, subFrameDomain });
 
     CompletionHandler<void(bool)> requestConfirmationCompletionHandler = [this, protectedThis = makeRef(*this), subFrameDomain, topFrameDomain, frameID, webPageID, scope, completionHandler = WTFMove(completionHandler)] (bool userDidGrantAccess) mutable {
@@ -1257,6 +1257,23 @@
             m_domainsWithUserInteractionQuirk = domainsWithUserInteractionQuirk;
             m_networkSession->networkProcess().parentProcessConnection()->send(Messages::NetworkProcessProxy::SetDomainsWithUserInteraction(domainsWithUserInteractionQuirk), 0);
         }
+
+        HashMap<TopFrameDomain, SubResourceDomain> domainsWithStorageAccessQuirk;
+        for (auto& firstPartyDomain : domainsToBlock.domainsWithStorageAccess.keys()) {
+            auto requestingDomain = domainsToBlock.domainsWithStorageAccess.get(firstPartyDomain);
+            if (NetworkStorageSession::loginDomainMatchesRequestingDomain(firstPartyDomain, requestingDomain))
+                domainsWithStorageAccessQuirk.add(firstPartyDomain, requestingDomain);
+        }
+
+        if (m_domainsWithCrossPageStorageAccessQuirk != domainsWithStorageAccessQuirk) {
+            if (m_networkSession) {
+                if (auto* storageSession = m_networkSession->networkStorageSession())
+                    storageSession->setDomainsWithCrossPageStorageAccess(domainsWithStorageAccessQuirk);
+                m_networkSession->networkProcess().parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::SetDomainsWithCrossPageStorageAccess(domainsWithStorageAccessQuirk), [this, domainsWithStorageAccessQuirk] () mutable {
+                    m_domainsWithCrossPageStorageAccessQuirk = domainsWithStorageAccessQuirk;
+                });
+            }
+        }
     }
 
     completionHandler();

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h (269806 => 269807)


--- trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h	2020-11-14 00:55:05 UTC (rev 269807)
@@ -68,11 +68,16 @@
 enum class ShouldGrandfatherStatistics : bool;
 enum class ShouldIncludeLocalhost : bool { No, Yes };
 enum class EnableResourceLoadStatisticsDebugMode : bool { No, Yes };
+
+using TopFrameDomain = WebCore::RegistrableDomain;
+using SubResourceDomain = WebCore::RegistrableDomain;
+
 struct RegistrableDomainsToBlockCookiesFor {
     Vector<WebCore::RegistrableDomain> domainsToBlockAndDeleteCookiesFor;
     Vector<WebCore::RegistrableDomain> domainsToBlockButKeepCookiesFor;
     Vector<WebCore::RegistrableDomain> domainsWithUserInteractionAsFirstParty;
-    RegistrableDomainsToBlockCookiesFor isolatedCopy() const { return { domainsToBlockAndDeleteCookiesFor.isolatedCopy(), domainsToBlockButKeepCookiesFor.isolatedCopy(), domainsWithUserInteractionAsFirstParty.isolatedCopy() }; }
+    HashMap<TopFrameDomain, SubResourceDomain> domainsWithStorageAccess;
+    RegistrableDomainsToBlockCookiesFor isolatedCopy() const { return { domainsToBlockAndDeleteCookiesFor.isolatedCopy(), domainsToBlockButKeepCookiesFor.isolatedCopy(), domainsWithUserInteractionAsFirstParty.isolatedCopy(), domainsWithStorageAccess }; }
 };
 struct RegistrableDomainsToDeleteOrRestrictWebsiteDataFor {
     Vector<WebCore::RegistrableDomain> domainsToDeleteAllCookiesFor;
@@ -330,6 +335,7 @@
     HashSet<RegistrableDomain> m_domainsWithEphemeralUserInteraction;
 
     HashSet<RegistrableDomain> m_domainsWithUserInteractionQuirk;
+    HashMap<TopFrameDomain, SubResourceDomain> m_domainsWithCrossPageStorageAccessQuirk;
 
     bool m_hasScheduledProcessStats { false };
 

Modified: trunk/Source/WebKit/Shared/WebProcessDataStoreParameters.h (269806 => 269807)


--- trunk/Source/WebKit/Shared/WebProcessDataStoreParameters.h	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/Shared/WebProcessDataStoreParameters.h	2020-11-14 00:55:05 UTC (rev 269807)
@@ -33,6 +33,9 @@
 namespace WebKit {
 
 struct WebProcessDataStoreParameters {
+    using TopFrameDomain = WebCore::RegistrableDomain;
+    using SubResourceDomain = WebCore::RegistrableDomain;
+
     PAL::SessionID sessionID;
     String applicationCacheDirectory;
     SandboxExtension::Handle applicationCacheDirectoryExtensionHandle;
@@ -48,6 +51,8 @@
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     WebCore::ThirdPartyCookieBlockingMode thirdPartyCookieBlockingMode { WebCore::ThirdPartyCookieBlockingMode::All };
     HashSet<WebCore::RegistrableDomain> domainsWithUserInteraction;
+    HashMap<TopFrameDomain, SubResourceDomain> domainsWithStorageAccessQuirk;
+
 #endif
     bool resourceLoadStatisticsEnabled { false };
 
@@ -73,6 +78,7 @@
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     encoder << thirdPartyCookieBlockingMode;
     encoder << domainsWithUserInteraction;
+    encoder << domainsWithStorageAccessQuirk;
 #endif
     encoder << resourceLoadStatisticsEnabled;
 }
@@ -144,6 +150,11 @@
     decoder >> domainsWithUserInteraction;
     if (!domainsWithUserInteraction)
         return WTF::nullopt;
+    
+    Optional<HashMap<TopFrameDomain, SubResourceDomain>> domainsWithStorageAccessQuirk;
+    decoder >> domainsWithStorageAccessQuirk;
+    if (!domainsWithStorageAccessQuirk)
+        return WTF::nullopt;
 #endif
 
     bool resourceLoadStatisticsEnabled = false;
@@ -166,6 +177,7 @@
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
         *thirdPartyCookieBlockingMode,
         WTFMove(*domainsWithUserInteraction),
+        WTFMove(*domainsWithStorageAccessQuirk),
 #endif
         resourceLoadStatisticsEnabled
     };

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (269806 => 269807)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2020-11-14 00:55:05 UTC (rev 269807)
@@ -1265,11 +1265,21 @@
 {
     sendWithAsyncReply(Messages::NetworkProcess::SetThirdPartyCNAMEDomainForTesting(sessionID, domain), WTFMove(completionHandler));
 }
+
 void NetworkProcessProxy::setDomainsWithUserInteraction(HashSet<WebCore::RegistrableDomain>&& domains)
 {
     for (auto* processPool : WebProcessPool::allProcessPools())
         processPool->setDomainsWithUserInteraction(HashSet<WebCore::RegistrableDomain> { domains });
 }
+
+void NetworkProcessProxy::setDomainsWithCrossPageStorageAccess(HashMap<TopFrameDomain, SubResourceDomain>&& domains, CompletionHandler<void()>&& completionHandler)
+{    
+    auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
+    
+    for (auto* processPool : WebProcessPool::allProcessPools())
+        processPool->setDomainsWithCrossPageStorageAccess(HashMap<TopFrameDomain, SubResourceDomain> { domains }, [callbackAggregator] { });
+}
+
 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
 
 void NetworkProcessProxy::setPrivateClickMeasurementDebugMode(bool debugMode)

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (269806 => 269807)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2020-11-14 00:55:05 UTC (rev 269807)
@@ -200,6 +200,7 @@
     void setFirstPartyHostCNAMEDomainForTesting(PAL::SessionID, const String& firstPartyHost, const RegistrableDomain& cnameDomain, CompletionHandler<void()>&&);
     void setThirdPartyCNAMEDomainForTesting(PAL::SessionID, const WebCore::RegistrableDomain&, CompletionHandler<void()>&&);
     void setDomainsWithUserInteraction(HashSet<WebCore::RegistrableDomain>&&);
+    void setDomainsWithCrossPageStorageAccess(HashMap<TopFrameDomain, SubResourceDomain>&&, CompletionHandler<void()>&&);
 #endif
 
     void setPrivateClickMeasurementDebugMode(bool);

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in (269806 => 269807)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in	2020-11-14 00:55:05 UTC (rev 269807)
@@ -48,6 +48,7 @@
     DeleteWebsiteDataInUIProcessForRegistrableDomains(PAL::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> dataTypes, OptionSet<WebKit::WebsiteDataFetchOption> fetchOptions, Vector<WebCore::RegistrableDomain> domains) -> (HashSet<WebCore::RegistrableDomain> domainsWithMatchingDataRecords) Async
     DidCommitCrossSiteLoadWithDataTransferFromPrevalentResource(WebKit::WebPageProxyIdentifier pageID)
     SetDomainsWithUserInteraction(HashSet<WebCore::RegistrableDomain> domains)
+    SetDomainsWithCrossPageStorageAccess(HashMap<WebCore::RegistrableDomain, WebCore::RegistrableDomain> domains) -> () Async
 #endif
 #if ENABLE(CONTENT_EXTENSIONS)
     ContentExtensionRules(WebKit::UserContentControllerIdentifier identifier)

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.cpp (269806 => 269807)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2020-11-14 00:55:05 UTC (rev 269807)
@@ -756,6 +756,7 @@
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
         websiteDataStore.thirdPartyCookieBlockingMode(),
         m_domainsWithUserInteraction,
+        m_domainsWithCrossPageStorageAccessQuirk,
 #endif
         websiteDataStore.resourceLoadStatisticsEnabled()
     };
@@ -1955,6 +1956,17 @@
     m_domainsWithUserInteraction = WTFMove(domains);
 }
 
+void WebProcessPool::setDomainsWithCrossPageStorageAccess(HashMap<TopFrameDomain, SubResourceDomain>&& domains, CompletionHandler<void()>&& completionHandler)
+{    
+    auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
+
+    for (auto& process : processes())
+        process->sendWithAsyncReply(Messages::WebProcess::SetDomainsWithCrossPageStorageAccess(domains), [callbackAggregator] { });
+
+    for (auto& topDomain : domains.keys())
+        m_domainsWithCrossPageStorageAccessQuirk.add(topDomain, domains.get(topDomain));
+}
+
 void WebProcessPool::seedResourceLoadStatisticsForTesting(const RegistrableDomain& firstPartyDomain, const RegistrableDomain& thirdPartyDomain, bool shouldScheduleNotification, CompletionHandler<void()>&& completionHandler)
 {
     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (269806 => 269807)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.h	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h	2020-11-14 00:55:05 UTC (rev 269807)
@@ -454,6 +454,7 @@
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     void setDomainsWithUserInteraction(HashSet<WebCore::RegistrableDomain>&&);
+    void setDomainsWithCrossPageStorageAccess(HashMap<TopFrameDomain, SubResourceDomain>&&, CompletionHandler<void()>&&);
     void seedResourceLoadStatisticsForTesting(const WebCore::RegistrableDomain& firstPartyDomain, const WebCore::RegistrableDomain& thirdPartyDomain, bool shouldScheduleNotification, CompletionHandler<void()>&&);
     void sendResourceLoadStatisticsDataImmediately(CompletionHandler<void()>&&);
 #endif
@@ -763,6 +764,7 @@
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     HashSet<WebCore::RegistrableDomain> m_domainsWithUserInteraction;
+    HashMap<TopFrameDomain, SubResourceDomain> m_domainsWithCrossPageStorageAccessQuirk;
 #endif
 };
 

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebResourceLoadObserver.cpp (269806 => 269807)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebResourceLoadObserver.cpp	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebResourceLoadObserver.cpp	2020-11-14 00:55:05 UTC (rev 269807)
@@ -418,6 +418,24 @@
         m_notificationTimer.stop();
 }
 
+bool WebResourceLoadObserver::hasCrossPageStorageAccess(const SubFrameDomain& subDomain, const TopFrameDomain& topDomain) const
+{
+    auto it = m_domainsWithCrossPageStorageAccess.find(topDomain);
+
+    if (it != m_domainsWithCrossPageStorageAccess.end())
+        return it->value == subDomain;
+
+    return false;
+}
+
+void WebResourceLoadObserver::setDomainsWithCrossPageStorageAccess(HashMap<TopFrameDomain, SubFrameDomain>&& domains, CompletionHandler<void()>&& completionHandler)
+{
+    for (auto& topDomain : domains.keys())
+        m_domainsWithCrossPageStorageAccess.add(topDomain, domains.get(topDomain));
+
+    completionHandler();
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebResourceLoadObserver.h (269806 => 269807)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebResourceLoadObserver.h	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebResourceLoadObserver.h	2020-11-14 00:55:05 UTC (rev 269807)
@@ -39,6 +39,9 @@
 
 class WebResourceLoadObserver final : public WebCore::ResourceLoadObserver {
 public:
+    using TopFrameDomain = WebCore::RegistrableDomain;
+    using SubFrameDomain = WebCore::RegistrableDomain;
+
     WebResourceLoadObserver(WebCore::ResourceLoadStatistics::IsEphemeral);
     ~WebResourceLoadObserver();
 
@@ -63,7 +66,10 @@
     bool hasStatistics() const final { return !m_resourceStatisticsMap.isEmpty(); }
 
     void setDomainsWithUserInteraction(HashSet<WebCore::RegistrableDomain>&& domains) final { m_domainsWithUserInteraction = WTFMove(domains); }
+    void setDomainsWithCrossPageStorageAccess(HashMap<TopFrameDomain, SubFrameDomain>&&, CompletionHandler<void()>&&) final;
     bool hasHadUserInteraction(const WebCore::RegistrableDomain&) const final;
+    bool hasCrossPageStorageAccess(const SubFrameDomain&, const TopFrameDomain&) const final;
+
 private:
     WebCore::ResourceLoadStatistics& ensureResourceStatisticsForRegistrableDomain(const WebCore::RegistrableDomain&);
     void scheduleNotificationIfNeeded();
@@ -81,6 +87,7 @@
     WebCore::Timer m_notificationTimer;
 
     HashSet<WebCore::RegistrableDomain> m_domainsWithUserInteraction;
+    HashMap<TopFrameDomain, SubFrameDomain> m_domainsWithCrossPageStorageAccess;
 #if !RELEASE_LOG_DISABLED
     uint64_t m_loggingCounter { 0 };
     static bool shouldLogUserInteraction;

Modified: trunk/Source/WebKit/WebProcess/WebProcess.cpp (269806 => 269807)


--- trunk/Source/WebKit/WebProcess/WebProcess.cpp	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/WebProcess/WebProcess.cpp	2020-11-14 00:55:05 UTC (rev 269807)
@@ -521,6 +521,8 @@
         if (!ResourceLoadObserver::sharedIfExists())
             ResourceLoadObserver::setShared(*new WebResourceLoadObserver(parameters.sessionID.isEphemeral() ? WebCore::ResourceLoadStatistics::IsEphemeral::Yes : WebCore::ResourceLoadStatistics::IsEphemeral::No));
         ResourceLoadObserver::shared().setDomainsWithUserInteraction(WTFMove(parameters.domainsWithUserInteraction));
+        if (!parameters.sessionID.isEphemeral())
+            ResourceLoadObserver::shared().setDomainsWithCrossPageStorageAccess(WTFMove(parameters.domainsWithStorageAccessQuirk), [] { });
     }
     
 #endif
@@ -1865,6 +1867,15 @@
     ResourceLoadObserver::shared().setDomainsWithUserInteraction(WTFMove(domains));
 }
 
+void WebProcess::setDomainsWithCrossPageStorageAccess(HashMap<TopFrameDomain, SubResourceDomain>&& domains, CompletionHandler<void()>&& completionHandler)
+{
+    for (auto& domain : domains.keys()) {
+        for (auto& webPage : m_pageMap.values())
+            webPage->addDomainWithPageLevelStorageAccess(domain, domains.get(domain));
+    }
+    ResourceLoadObserver::shared().setDomainsWithCrossPageStorageAccess(WTFMove(domains), WTFMove(completionHandler));
+}
+
 void WebProcess::sendResourceLoadStatisticsDataImmediately(CompletionHandler<void()>&& completionHandler)
 {
     ResourceLoadObserver::shared().updateCentralStatisticsStore(WTFMove(completionHandler));

Modified: trunk/Source/WebKit/WebProcess/WebProcess.h (269806 => 269807)


--- trunk/Source/WebKit/WebProcess/WebProcess.h	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/WebProcess/WebProcess.h	2020-11-14 00:55:05 UTC (rev 269807)
@@ -146,6 +146,9 @@
 {
     WTF_MAKE_FAST_ALLOCATED;
 public:
+    using TopFrameDomain = WebCore::RegistrableDomain;
+    using SubResourceDomain = WebCore::RegistrableDomain;
+
     static WebProcess& singleton();
     static constexpr ProcessType processType = ProcessType::WebContent;
 
@@ -487,6 +490,7 @@
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     void setThirdPartyCookieBlockingMode(WebCore::ThirdPartyCookieBlockingMode, CompletionHandler<void()>&&);
     void setDomainsWithUserInteraction(HashSet<WebCore::RegistrableDomain>&&);
+    void setDomainsWithCrossPageStorageAccess(HashMap<TopFrameDomain, SubResourceDomain>&&, CompletionHandler<void()>&&);
     void sendResourceLoadStatisticsDataImmediately(CompletionHandler<void()>&&);
 #endif
 

Modified: trunk/Source/WebKit/WebProcess/WebProcess.messages.in (269806 => 269807)


--- trunk/Source/WebKit/WebProcess/WebProcess.messages.in	2020-11-14 00:20:47 UTC (rev 269806)
+++ trunk/Source/WebKit/WebProcess/WebProcess.messages.in	2020-11-14 00:55:05 UTC (rev 269807)
@@ -158,6 +158,7 @@
     SeedResourceLoadStatisticsForTesting(WebCore::RegistrableDomain firstPartyDomain, WebCore::RegistrableDomain thirdPartyDomain, bool shouldScheduleNotification) -> () Async
     SetThirdPartyCookieBlockingMode(enum:uint8_t WebCore::ThirdPartyCookieBlockingMode blockingMode) -> () Async
     SetDomainsWithUserInteraction(HashSet<WebCore::RegistrableDomain> domains)
+    SetDomainsWithCrossPageStorageAccess(HashMap<WebCore::RegistrableDomain, WebCore::RegistrableDomain> domains) -> () Async
     SendResourceLoadStatisticsDataImmediately() -> () Async
 #endif
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to