Changeset 243632 in webkit


Ignore:
Timestamp:
Mar 28, 2019 6:15:59 PM (5 years ago)
Author:
wilander@apple.com
Message:

Resource Load Statistics: IPC to the WebsiteDataStore in the UI process from NetworkProcess::deleteWebsiteDataForRegistrableDomains()
https://bugs.webkit.org/show_bug.cgi?id=196281
<rdar://problem/48938748>

Reviewed by Alex Christensen.

Source/WebKit:

The move of Resource Load Statistics to the network process requires that it
calls the UI process when clearing website data (previously the other way
around). This patch achieves that.

Specifically, NetworkProcess::deleteWebsiteDataForRegistrableDomains() now
filters its WebsiteDataTypes down to just the ones applicable for the UI
process and then calls DeleteWebsiteDataInUIProcessForRegistrableDomains over
IPC.

NetworkProcessProxy::deleteWebsiteDataInUIProcessForRegistrableDomains() on
the UI process side makes use of the re-introduced
WebsiteDataStore::fetchDataForRegistrableDomains() function to get the relevant
data records and call WebsiteDataStore::removeData(). The re-introduced
WebsiteDataStore::fetchDataForRegistrableDomains() was removed as dead code in
https://trac.webkit.org/changeset/242056/webkit, then under the name
WebsiteDataStore::fetchDataForTopPrivatelyControlledDomains(). The reason it
was dead code was the lack of IPC call that this patch adds.

  • NetworkProcess/NetworkProcess.cpp:

(WebKit::NetworkProcess::deleteWebsiteDataForRegistrableDomains):

Now calls DeleteWebsiteDataInUIProcessForRegistrableDomains over IPC if there
are WebsiteDataTypes applicable to the UI process.

  • NetworkProcess/NetworkProcess.h:
  • Shared/WebsiteData/WebsiteData.cpp:

(WebKit::WebsiteData::ownerProcess):
(WebKit::WebsiteData::filter):

Convenience functions to manage process ownership of website data types.

  • Shared/WebsiteData/WebsiteData.h:
  • UIProcess/API/C/WKWebsiteDataStoreRef.cpp:

(WKWebsiteDataStoreStatisticsHasLocalStorage):

Test infrastructure, called by the TestRunner.

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

(WebKit::NetworkProcessProxy::deleteWebsiteDataInUIProcessForRegistrableDomains):

New function to be called from the network process.

  • UIProcess/Network/NetworkProcessProxy.h:
  • UIProcess/Network/NetworkProcessProxy.messages.in:
  • UIProcess/WebsiteData/WebsiteDataRecord.cpp:

(WebKit::WebsiteDataRecord::matches const):

Now matches with WebCore::RegistrableDomain instead of a string.

(WebKit::WebsiteDataRecord::matchesTopPrivatelyControlledDomain const): Deleted.

Replaced by WebsiteDataRecord::matches().

  • UIProcess/WebsiteData/WebsiteDataRecord.h:
  • UIProcess/WebsiteData/WebsiteDataStore.cpp:

(WebKit::WebsiteDataStore::fetchDataForRegistrableDomains):

Re-introduced. It was removed as dead code in r242056.

(WebKit::computeNetworkProcessAccessTypeForDataRemoval):
(WebKit::WebsiteDataStore::hasLocalStorageForTesting const):

Test infrastructure, called by the TestRunner.

  • UIProcess/WebsiteData/WebsiteDataStore.h:

Tools:

This patch adds the function isStatisticsHasLocalStorage() to the
TestRunner. With it, the page can query the WebsiteDataStore in the
UI process to make sure that it sees LocalStorage.

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

(WTR::TestRunner::isStatisticsHasLocalStorage):

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

(WTR::TestController::isStatisticsHasLocalStorage):

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

(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):

LayoutTests:

This test now covers LocalStorage too.

  • http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration-expected.txt:
  • http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration.html:
Location:
trunk
Files:
24 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r243629 r243632  
     12019-03-28  John Wilander  <wilander@apple.com>
     2
     3        Resource Load Statistics: IPC to the WebsiteDataStore in the UI process from NetworkProcess::deleteWebsiteDataForRegistrableDomains()
     4        https://bugs.webkit.org/show_bug.cgi?id=196281
     5        <rdar://problem/48938748>
     6
     7        Reviewed by Alex Christensen.
     8
     9        This test now covers LocalStorage too.
     10
     11        * http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration-expected.txt:
     12        * http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration.html:
     13
    1142019-03-28  Shawn Roberts  <sroberts@apple.com>
    215
  • trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration-expected.txt

    r243181 r243632  
    44Before deletion: HttpOnly cookie exists.
    55Before deletion: Regular server-side cookie exists.
    6 
     6Before deletion: LocalStorage entry does exist.
    77Before deletion: IDB entry does exist.
    88
     
    1010After deletion: Client-side cookie exists.
    1111After deletion: Regular server-side cookie exists.
    12 
     12After deletion: LocalStorage entry does not exist.
    1313After deletion: IDB entry does not exist.
    1414
  • trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration.html

    r243181 r243632  
    9292    }
    9393
     94    const maxIntervals = 20;
     95    let intervalCounter;
     96    let checkLocalStorageCallback;
     97    let checkLocalStorageIntervalID;
     98    const localStorageName = "test";
     99    const localStorageValue = "value";
     100    function checkLocalStorageExists(isAfterDeletion, callback) {
     101        intervalCounter = 0;
     102        checkLocalStorageCallback = callback;
     103        if (!isAfterDeletion) {
     104            // Check until there is LocalStorage.
     105            checkLocalStorageIntervalID = setInterval(function() {
     106                if (++intervalCounter === maxIntervals) {
     107                    clearInterval(checkLocalStorageIntervalID);
     108                    checkLocalStorageCallback();
     109                } else if (testRunner.isStatisticsHasLocalStorage(destinationOrigin)) {
     110                    clearInterval(checkLocalStorageIntervalID);
     111                    let value = localStorage.getItem(localStorageName);
     112                    addOutput("Before deletion: LocalStorage entry " + (value === localStorageValue ? "does" : "does not") + " exist.");
     113                    checkLocalStorageCallback();
     114                }
     115            }, 100);
     116        } else {
     117            // Check until there is no LocalStorage.
     118            checkLocalStorageIntervalID = setInterval(function() {
     119                if (++intervalCounter === maxIntervals) {
     120                    clearInterval(checkLocalStorageIntervalID);
     121                    checkLocalStorageCallback();
     122                } else if (!testRunner.isStatisticsHasLocalStorage(destinationOrigin)) {
     123                    clearInterval(checkLocalStorageIntervalID);
     124                    let value = localStorage.getItem(localStorageName);
     125                    addOutput("After deletion: LocalStorage entry " + (value === localStorageValue ? "does" : "does not") + " exist.");
     126                    checkLocalStorageCallback();
     127                }
     128            }, 100);
     129        }
     130    }
     131
    94132    async function writeWebsiteDataAndContinue() {
    95133        // Write cookies.
     
    99137
    100138        checkCookies(false);
    101         addLinebreakToOutput();
    102139
    103         // Write IndexedDB.
    104         createIDBDataStore(function () {
    105             checkIDBDataStoreExists(false, processWebsiteDataAndContinue);
     140        // Write LocalStorage
     141        localStorage.setItem(localStorageName, localStorageValue);
     142        checkLocalStorageExists(false, function() {
     143
     144            // Write IndexedDB.
     145            createIDBDataStore(function () {
     146                checkIDBDataStoreExists(false, function() {
     147                    addLinebreakToOutput();
     148                    processWebsiteDataAndContinue();
     149                });
     150            });
    106151        });
    107152    }
     
    109154    function processWebsiteDataAndContinue() {
    110155        testRunner.statisticsProcessStatisticsAndDataRecords();
     156        checkWebsiteDataAndContinue();
     157    }
    111158
    112         addLinebreakToOutput();
     159    function checkWebsiteDataAndContinue() {
    113160        checkCookies(true);
    114         addLinebreakToOutput();
    115         checkIDBDataStoreExists(true, finishTest);
     161        checkLocalStorageExists(true, function () {
     162            checkIDBDataStoreExists(true, finishTest);
     163        });
    116164    }
    117165
  • trunk/Source/WebKit/ChangeLog

    r243631 r243632  
     12019-03-28  John Wilander  <wilander@apple.com>
     2
     3        Resource Load Statistics: IPC to the WebsiteDataStore in the UI process from NetworkProcess::deleteWebsiteDataForRegistrableDomains()
     4        https://bugs.webkit.org/show_bug.cgi?id=196281
     5        <rdar://problem/48938748>
     6
     7        Reviewed by Alex Christensen.
     8
     9        The move of Resource Load Statistics to the network process requires that it
     10        calls the UI process when clearing website data (previously the other way
     11        around). This patch achieves that.
     12
     13        Specifically, NetworkProcess::deleteWebsiteDataForRegistrableDomains() now
     14        filters its WebsiteDataTypes down to just the ones applicable for the UI
     15        process and then calls DeleteWebsiteDataInUIProcessForRegistrableDomains over
     16        IPC.
     17
     18        NetworkProcessProxy::deleteWebsiteDataInUIProcessForRegistrableDomains() on
     19        the UI process side makes use of the re-introduced
     20        WebsiteDataStore::fetchDataForRegistrableDomains() function to get the relevant
     21        data records and call WebsiteDataStore::removeData(). The re-introduced
     22        WebsiteDataStore::fetchDataForRegistrableDomains() was removed as dead code in
     23        https://trac.webkit.org/changeset/242056/webkit, then under the name
     24        WebsiteDataStore::fetchDataForTopPrivatelyControlledDomains(). The reason it
     25        was dead code was the lack of IPC call that this patch adds.
     26
     27        * NetworkProcess/NetworkProcess.cpp:
     28        (WebKit::NetworkProcess::deleteWebsiteDataForRegistrableDomains):
     29           Now calls DeleteWebsiteDataInUIProcessForRegistrableDomains over IPC if there
     30           are WebsiteDataTypes applicable to the UI process.
     31        * NetworkProcess/NetworkProcess.h:
     32        * Shared/WebsiteData/WebsiteData.cpp:
     33        (WebKit::WebsiteData::ownerProcess):
     34        (WebKit::WebsiteData::filter):
     35            Convenience functions to manage process ownership of website data types.
     36        * Shared/WebsiteData/WebsiteData.h:
     37        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
     38        (WKWebsiteDataStoreStatisticsHasLocalStorage):
     39            Test infrastructure, called by the TestRunner.
     40        * UIProcess/API/C/WKWebsiteDataStoreRef.h:
     41        * UIProcess/Network/NetworkProcessProxy.cpp:
     42        (WebKit::NetworkProcessProxy::deleteWebsiteDataInUIProcessForRegistrableDomains):
     43            New function to be called from the network process.
     44        * UIProcess/Network/NetworkProcessProxy.h:
     45        * UIProcess/Network/NetworkProcessProxy.messages.in:
     46        * UIProcess/WebsiteData/WebsiteDataRecord.cpp:
     47        (WebKit::WebsiteDataRecord::matches const):
     48            Now matches with WebCore::RegistrableDomain instead of a string.
     49        (WebKit::WebsiteDataRecord::matchesTopPrivatelyControlledDomain const): Deleted.
     50            Replaced by WebsiteDataRecord::matches().
     51        * UIProcess/WebsiteData/WebsiteDataRecord.h:
     52        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
     53        (WebKit::WebsiteDataStore::fetchDataForRegistrableDomains):
     54            Re-introduced. It was removed as dead code in r242056.
     55        (WebKit::computeNetworkProcessAccessTypeForDataRemoval):
     56        (WebKit::WebsiteDataStore::hasLocalStorageForTesting const):
     57            Test infrastructure, called by the TestRunner.
     58        * UIProcess/WebsiteData/WebsiteDataStore.h:
     59
    1602019-03-28  Jiewen Tan  <jiewen_tan@apple.com>
    261
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp

    r243427 r243632  
    5858#include "WebSWServerConnection.h"
    5959#include "WebSWServerToContextConnection.h"
    60 #include "WebsiteData.h"
    6160#include "WebsiteDataFetchOption.h"
    6261#include "WebsiteDataStore.h"
     
    15261525        ~CallbackAggregator()
    15271526        {
    1528             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] () mutable {
    1529                 HashSet<RegistrableDomain> domains;
    1530                 for (const auto& hostnameWithCookies : websiteData.hostNamesWithCookies)
    1531                     domains.add(RegistrableDomain::uncheckedCreateFromHost(hostnameWithCookies));
    1532 
    1533                 for (const auto& hostnameWithHSTS : websiteData.hostNamesWithHSTSCache)
    1534                     domains.add(RegistrableDomain::uncheckedCreateFromHost(hostnameWithHSTS));
    1535 
    1536                 for (const auto& entry : websiteData.entries)
    1537                     domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
    1538 
     1527            RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), domains = WTFMove(m_domains)] () mutable {
    15391528                completionHandler(domains);
    15401529            });
     
    15421531       
    15431532        CompletionHandler<void(const HashSet<RegistrableDomain>&)> m_completionHandler;
    1544         WebsiteData m_websiteData;
     1533        HashSet<RegistrableDomain> m_domains;
    15451534    };
    15461535   
     
    15541543    }));
    15551544
    1556     auto& websiteDataStore = callbackAggregator->m_websiteData;
     1545    HashSet<String> hostNamesWithCookies;
     1546    HashSet<String> hostNamesWithHSTSCache;
    15571547
    15581548    Vector<RegistrableDomain> domainsToDeleteCookiesFor;
     
    15761566        }
    15771567        if (auto* networkStorageSession = storageSession(sessionID)) {
    1578             networkStorageSession->getHostnamesWithCookies(websiteDataStore.hostNamesWithCookies);
    1579 
    1580             hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteCookiesFor, websiteDataStore.hostNamesWithCookies);
     1568            networkStorageSession->getHostnamesWithCookies(hostNamesWithCookies);
     1569
     1570            hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteCookiesFor, hostNamesWithCookies);
    15811571            networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::Yes);
    15821572
    1583             hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteAllButHttpOnlyCookiesFor, websiteDataStore.hostNamesWithCookies);
     1573            for (const auto& host : hostnamesWithCookiesToDelete)
     1574                callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
     1575
     1576            hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteAllButHttpOnlyCookiesFor, hostNamesWithCookies);
    15841577            networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::No);
     1578
     1579            for (const auto& host : hostnamesWithCookiesToDelete)
     1580                callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
    15851581        }
    15861582    } else {
     
    15931589    if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
    15941590        if (auto* networkStorageSession = storageSession(sessionID)) {
    1595             getHostNamesWithHSTSCache(*networkStorageSession, websiteDataStore.hostNamesWithHSTSCache);
    1596             hostnamesWithHSTSToDelete = filterForRegistrableDomains(domainsToDeleteAllButCookiesFor, websiteDataStore.hostNamesWithHSTSCache);
     1591            getHostNamesWithHSTSCache(*networkStorageSession, hostNamesWithHSTSCache);
     1592            hostnamesWithHSTSToDelete = filterForRegistrableDomains(domainsToDeleteAllButCookiesFor, hostNamesWithHSTSCache);
     1593
     1594            for (const auto& host : hostnamesWithHSTSToDelete)
     1595                callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
     1596
    15971597            deleteHSTSCacheForHostNames(*networkStorageSession, hostnamesWithHSTSToDelete);
    15981598        }
     
    16021602    /*
    16031603    // FIXME: No API to delete credentials by origin
     1604    HashSet<String> originsWithCredentials;
    16041605    if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
    16051606        if (storageSession(sessionID))
    1606             websiteDataStore.originsWithCredentials = storageSession(sessionID)->credentialStorage().originsWithCredentials();
     1607            originsWithCredentials = storageSession(sessionID)->credentialStorage().originsWithCredentials();
    16071608    }
    16081609    */
     
    16131614            auto entriesToDelete = filterForRegistrableDomains(domainsToDeleteAllButCookiesFor, entries);
    16141615
    1615             callbackAggregator->m_websiteData.entries.appendVector(entriesToDelete);
    1616            
     1616            for (const auto& entry : entriesToDelete)
     1617                callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
     1618
    16171619            for (auto& entry : entriesToDelete)
    16181620                CacheStorage::Engine::clearCachesForOrigin(*this, sessionID, SecurityOriginData { entry.origin }, [callbackAggregator = callbackAggregator.copyRef()] { });
     
    16281630                Vector<SecurityOriginData> entriesToDelete;
    16291631                for (const auto& securityOrigin : securityOrigins) {
    1630                     if (!domainsToDeleteAllButCookiesFor.contains(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host)))
     1632                    auto domain = RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host);
     1633                    if (!domainsToDeleteAllButCookiesFor.contains(domain))
    16311634                        continue;
    16321635
    16331636                    entriesToDelete.append(securityOrigin);
    1634                     callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::IndexedDBDatabases, 0 });
     1637                    callbackAggregator->m_domains.add(domain);
    16351638                }
    16361639
     
    16481651                if (!domainsToDeleteAllButCookiesFor.contains(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host)))
    16491652                    continue;
    1650                 callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::ServiceWorkerRegistrations, 0 });
     1653                callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host));
    16511654                swServerForSession(sessionID).clear(securityOrigin, [callbackAggregator = callbackAggregator.copyRef()] { });
    16521655            }
     
    16631666                    continue;
    16641667                entriesToDelete.append(entry.origin);
    1665                 callbackAggregator->m_websiteData.entries.append(entry);
     1668                callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
    16661669            }
    16671670            clearDiskCacheEntries(cache(), entriesToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
    16681671        });
     1672    }
     1673
     1674    auto dataTypesForUIProcess = WebsiteData::filter(websiteDataTypes, WebsiteDataProcessType::UI);
     1675    if (!dataTypesForUIProcess.isEmpty() && !domainsToDeleteAllButCookiesFor.isEmpty()) {
     1676        CompletionHandler<void(const HashSet<RegistrableDomain>&)> completionHandler = [callbackAggregator = callbackAggregator.copyRef()] (const HashSet<RegistrableDomain>& domains) {
     1677            for (auto& domain : domains)
     1678                callbackAggregator->m_domains.add(domain);
     1679        };
     1680        parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::DeleteWebsiteDataInUIProcessForRegistrableDomains(sessionID, dataTypesForUIProcess, fetchOptions, domainsToDeleteAllButCookiesFor), WTFMove(completionHandler));
    16691681    }
    16701682}
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.h

    r243427 r243632  
    3434#include "SandboxExtension.h"
    3535#include "WebResourceLoadStatisticsStore.h"
     36#include "WebsiteData.h"
    3637#include <WebCore/AdClickAttribution.h>
    3738#include <WebCore/ClientOrigin.h>
  • trunk/Source/WebKit/Shared/WebsiteData/WebsiteData.cpp

    r243163 r243632  
    2828
    2929#include "ArgumentCoders.h"
     30#include "WebsiteDataType.h"
    3031#include <WebCore/SecurityOriginData.h>
    3132#include <wtf/text/StringHash.h>
     
    8788}
    8889
     90WebsiteDataProcessType WebsiteData::ownerProcess(WebsiteDataType dataType)
     91{
     92    switch (dataType) {
     93    case WebsiteDataType::Cookies:
     94        return WebsiteDataProcessType::Network;
     95    case WebsiteDataType::DiskCache:
     96        return WebsiteDataProcessType::Network;
     97    case WebsiteDataType::MemoryCache:
     98        return WebsiteDataProcessType::Web;
     99    case WebsiteDataType::OfflineWebApplicationCache:
     100        return WebsiteDataProcessType::UI;
     101    case WebsiteDataType::SessionStorage:
     102        return WebsiteDataProcessType::UI;
     103    case WebsiteDataType::LocalStorage:
     104        return WebsiteDataProcessType::UI;
     105    case WebsiteDataType::WebSQLDatabases:
     106        return WebsiteDataProcessType::UI;
     107    case WebsiteDataType::IndexedDBDatabases:
     108        return WebsiteDataProcessType::Network;
     109    case WebsiteDataType::MediaKeys:
     110        return WebsiteDataProcessType::UI;
     111    case WebsiteDataType::HSTSCache:
     112        return WebsiteDataProcessType::Network;
     113    case WebsiteDataType::SearchFieldRecentSearches:
     114        return WebsiteDataProcessType::UI;
     115#if ENABLE(NETSCAPE_PLUGIN_API)
     116    case WebsiteDataType::PlugInData:
     117        return WebsiteDataProcessType::UI;
     118#endif
     119    case WebsiteDataType::ResourceLoadStatistics:
     120        return WebsiteDataProcessType::Network;
     121    case WebsiteDataType::Credentials:
     122        return WebsiteDataProcessType::Network;
     123#if ENABLE(SERVICE_WORKER)
     124    case WebsiteDataType::ServiceWorkerRegistrations:
     125        return WebsiteDataProcessType::Network;
     126#endif
     127    case WebsiteDataType::DOMCache:
     128        return WebsiteDataProcessType::Network;
     129    case WebsiteDataType::DeviceIdHashSalt:
     130        return WebsiteDataProcessType::UI;
     131    }
    89132}
     133
     134OptionSet<WebsiteDataType> WebsiteData::filter(OptionSet<WebsiteDataType> unfilteredWebsiteDataTypes, WebsiteDataProcessType WebsiteDataProcessType)
     135{
     136    OptionSet<WebsiteDataType> filtered;
     137    for (auto dataType : unfilteredWebsiteDataTypes) {
     138        if (ownerProcess(dataType) == WebsiteDataProcessType)
     139            filtered.add(dataType);
     140    }
     141   
     142    return filtered;
     143}
     144
     145}
  • trunk/Source/WebKit/Shared/WebsiteData/WebsiteData.h

    r239427 r243632  
    2929#include <wtf/HashMap.h>
    3030#include <wtf/HashSet.h>
     31#include <wtf/OptionSet.h>
    3132#include <wtf/Vector.h>
    3233
     
    3940
    4041enum class WebsiteDataType;
     42
     43enum class WebsiteDataProcessType { Network, UI, Web };
    4144
    4245struct WebsiteData {
     
    6366    void encode(IPC::Encoder&) const;
    6467    static bool decode(IPC::Decoder&, WebsiteData&);
     68    static WebsiteDataProcessType ownerProcess(WebsiteDataType);
     69    static OptionSet<WebsiteDataType> filter(OptionSet<WebsiteDataType>, WebsiteDataProcessType);
    6570};
    6671
  • trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp

    r243181 r243632  
    450450}
    451451
     452void WKWebsiteDataStoreStatisticsHasLocalStorage(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, void* context, WKWebsiteDataStoreStatisticsHasLocalStorageFunction callback)
     453{
     454#if ENABLE(RESOURCE_LOAD_STATISTICS)
     455    WebKit::toImpl(dataStoreRef)->websiteDataStore().hasLocalStorageForTesting(URL(URL(), WebKit::toImpl(host)->string()), [context, callback](bool hasLocalStorage) {
     456        callback(hasLocalStorage, context);
     457    });
     458#else
     459    callback(false, context);
     460#endif
     461}
     462
    452463void WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap(WKWebsiteDataStoreRef dataStoreRef, double seconds, void* context, WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction callback)
    453464{
  • trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h

    r243181 r243632  
    100100typedef void (*WKWebsiteDataStoreStatisticsDeleteCookiesForTestingFunction)(void* functionContext);
    101101WK_EXPORT void WKWebsiteDataStoreStatisticsDeleteCookiesForTesting(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, bool includeHttpOnlyCookies, void* context, WKWebsiteDataStoreStatisticsDeleteCookiesForTestingFunction callback);
     102typedef void (*WKWebsiteDataStoreStatisticsHasLocalStorageFunction)(bool hasLocalStorage, void* functionContext);
     103WK_EXPORT void WKWebsiteDataStoreStatisticsHasLocalStorage(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, void* context, WKWebsiteDataStoreStatisticsHasLocalStorageFunction callback);
    102104typedef void (*WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction)(void* functionContext);
    103105WK_EXPORT void WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap(WKWebsiteDataStoreRef dataStoreRef, double seconds, void* context, WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction);
  • trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp

    r243181 r243632  
    992992    sendWithAsyncReply(Messages::NetworkProcess::DeleteCookiesForTesting(sessionID, domain, includeHttpOnlyCookies), WTFMove(completionHandler));
    993993}
     994
     995void NetworkProcessProxy::deleteWebsiteDataInUIProcessForRegistrableDomains(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, Vector<RegistrableDomain> domains, CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&& completionHandler)
     996{
     997    auto* websiteDataStore = websiteDataStoreFromSessionID(sessionID);
     998    if (!websiteDataStore || dataTypes.isEmpty() || domains.isEmpty()) {
     999        completionHandler({ });
     1000        return;
     1001    }
     1002
     1003    websiteDataStore->fetchDataForRegistrableDomains(dataTypes, fetchOptions, domains, [dataTypes, websiteDataStore = makeRef(*websiteDataStore), completionHandler = WTFMove(completionHandler)] (Vector<WebsiteDataRecord>&& matchingDataRecords, HashSet<WebCore::RegistrableDomain>&& domainsWithMatchingDataRecords) mutable {
     1004        websiteDataStore->removeData(dataTypes, WTFMove(matchingDataRecords), [domainsWithMatchingDataRecords = WTFMove(domainsWithMatchingDataRecords), completionHandler = WTFMove(completionHandler)] () mutable {
     1005            completionHandler(WTFMove(domainsWithMatchingDataRecords));
     1006        });
     1007    });
     1008}
     1009
    9941010#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
    9951011
  • trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h

    r243181 r243632  
    150150    void resetCrossSiteLoadsWithLinkDecorationForTesting(PAL::SessionID, CompletionHandler<void()>&&);
    151151    void deleteCookiesForTesting(PAL::SessionID, const RegistrableDomain&, bool includeHttpOnlyCookies, CompletionHandler<void()>&&);
     152    void deleteWebsiteDataInUIProcessForRegistrableDomains(PAL::SessionID, OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, Vector<RegistrableDomain>, CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&&);
    152153#endif
    153154
  • trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in

    r242905 r243632  
    4949    NotifyResourceLoadStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
    5050    RequestStorageAccessConfirm(uint64_t pageID, uint64_t frameID, WebCore::RegistrableDomain subFrameDomain, WebCore::RegistrableDomain topFrameDomain) -> (bool userDidGrantAccess) Async
     51    DeleteWebsiteDataInUIProcessForRegistrableDomains(PAL::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> dataTypes, OptionSet<WebKit::WebsiteDataFetchOption> fetchOptions, Vector<WebCore::RegistrableDomain> domains) -> (HashSet<WebCore::RegistrableDomain> domainsWithMatchingDataRecords) Async
    5152#endif
    5253#if ENABLE(CONTENT_EXTENSIONS)
  • trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataRecord.cpp

    r235560 r243632  
    2929#include <WebCore/LocalizedStrings.h>
    3030#include <WebCore/PublicSuffix.h>
     31#include <WebCore/RegistrableDomain.h>
    3132#include <WebCore/SecurityOrigin.h>
    3233
     
    114115}
    115116
    116 bool WebsiteDataRecord::matchesTopPrivatelyControlledDomain(const String& topPrivatelyControlledDomain) const
     117bool WebsiteDataRecord::matches(const WebCore::RegistrableDomain& domain) const
    117118{
    118     if (topPrivatelyControlledDomain.isEmpty())
     119    if (domain.isEmpty())
    119120        return false;
    120121
    121122    if (types.contains(WebsiteDataType::Cookies)) {
    122123        for (const auto& hostName : cookieHostNames) {
    123             if (hostIsInDomain(hostName, topPrivatelyControlledDomain))
     124            if (hostIsInDomain(hostName, domain.string()))
    124125                return true;
    125126        }
     
    127128
    128129    for (const auto& dataRecordOriginData : origins) {
    129         if (hostIsInDomain(dataRecordOriginData.host, topPrivatelyControlledDomain))
     130        if (hostIsInDomain(dataRecordOriginData.host, domain.string()))
    130131            return true;
    131132    }
  • trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataRecord.h

    r239427 r243632  
    3737
    3838namespace WebCore {
     39class RegistrableDomain;
    3940class SecurityOrigin;
    4041}
     
    7374    HashSet<String> HSTSCacheHostNames;
    7475
    75     bool matchesTopPrivatelyControlledDomain(const String&) const;
     76    bool matches(const WebCore::RegistrableDomain&) const;
    7677    String topPrivatelyControlledDomain();
    7778};
  • trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp

    r243375 r243632  
    624624}
    625625
     626#if ENABLE(RESOURCE_LOAD_STATISTICS)
     627void WebsiteDataStore::fetchDataForRegistrableDomains(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, const Vector<WebCore::RegistrableDomain>& domains, CompletionHandler<void(Vector<WebsiteDataRecord>&&, HashSet<WebCore::RegistrableDomain>&&)>&& completionHandler)
     628{
     629    fetchDataAndApply(dataTypes, fetchOptions, m_queue.copyRef(), [domains = crossThreadCopy(domains), completionHandler = WTFMove(completionHandler)] (auto&& existingDataRecords) mutable {
     630        ASSERT(!RunLoop::isMain());
     631       
     632        Vector<WebsiteDataRecord> matchingDataRecords;
     633        HashSet<WebCore::RegistrableDomain> domainsWithMatchingDataRecords;
     634        for (auto&& dataRecord : existingDataRecords) {
     635            for (auto& domain : domains) {
     636                if (dataRecord.matches(domain)) {
     637                    matchingDataRecords.append(WTFMove(dataRecord));
     638                    domainsWithMatchingDataRecords.add(domain.isolatedCopy());
     639                    break;
     640                }
     641            }
     642        }
     643        RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), matchingDataRecords = WTFMove(matchingDataRecords), domainsWithMatchingDataRecords = WTFMove(domainsWithMatchingDataRecords)] () mutable {
     644            completionHandler(WTFMove(matchingDataRecords), WTFMove(domainsWithMatchingDataRecords));
     645        });
     646    });
     647}
     648#endif
     649
    626650static ProcessAccessType computeNetworkProcessAccessTypeForDataRemoval(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
    627651{
    628652    ProcessAccessType processAccessType = ProcessAccessType::None;
    629653
    630     if (dataTypes.contains(WebsiteDataType::Cookies)) {
    631         if (isNonPersistentStore)
    632             processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched);
    633         else
    634             processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
    635     }
    636 
    637     if (dataTypes.contains(WebsiteDataType::DiskCache) && !isNonPersistentStore)
    638         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
    639 
    640     if (dataTypes.contains(WebsiteDataType::HSTSCache))
    641         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
    642 
    643     if (dataTypes.contains(WebsiteDataType::Credentials))
    644         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
    645 
    646     if (dataTypes.contains(WebsiteDataType::DOMCache))
    647         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
    648 
    649     if (dataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !isNonPersistentStore)
    650         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
    651    
    652 #if ENABLE(SERVICE_WORKER)
    653     if (dataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !isNonPersistentStore)
    654         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
    655 #endif
    656 
     654    for (auto dataType : dataTypes) {
     655        if (dataType == WebsiteDataType::Cookies) {
     656            if (isNonPersistentStore)
     657                processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched);
     658            else
     659                processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
     660        } else if (WebsiteData::ownerProcess(dataType) == WebsiteDataProcessType::Network)
     661            return ProcessAccessType::Launch;
     662    }
     663   
    657664    return processAccessType;
    658665}
     
    17961803    }
    17971804}
     1805
     1806void WebsiteDataStore::hasLocalStorageForTesting(const URL& url, CompletionHandler<void(bool)>&& completionHandler) const
     1807{
     1808    if (!m_storageManager) {
     1809        completionHandler(false);
     1810        return;
     1811    }
     1812
     1813    m_storageManager->getLocalStorageOrigins([url, completionHandler = WTFMove(completionHandler)](HashSet<WebCore::SecurityOriginData>&& origins) mutable {
     1814        for (auto& origin : origins) {
     1815            if (origin.host == url.host()) {
     1816                completionHandler(true);
     1817                return;
     1818            }
     1819        }
     1820
     1821        completionHandler(false);
     1822    });
     1823}
    17981824#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
    17991825
  • trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h

    r243181 r243632  
    6262
    6363namespace WebCore {
     64class RegistrableDomain;
    6465class SecurityOrigin;
    6566}
     
    126127
    127128#if ENABLE(RESOURCE_LOAD_STATISTICS)
     129    void fetchDataForRegistrableDomains(OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, const Vector<WebCore::RegistrableDomain>&, CompletionHandler<void(Vector<WebsiteDataRecord>&&, HashSet<WebCore::RegistrableDomain>&&)>&&);
    128130    void clearPrevalentResource(const URL&, CompletionHandler<void()>&&);
    129131    void clearUserInteraction(const URL&, CompletionHandler<void()>&&);
     
    172174    void resetCrossSiteLoadsWithLinkDecorationForTesting(CompletionHandler<void()>&&);
    173175    void deleteCookiesForTesting(const URL&, bool includeHttpOnlyCookies, CompletionHandler<void()>&&);
     176    void hasLocalStorageForTesting(const URL&, CompletionHandler<void(bool)>&&) const;
    174177#endif
    175178    void setCacheMaxAgeCapForPrevalentResources(Seconds, CompletionHandler<void()>&&);
  • trunk/Tools/ChangeLog

    r243631 r243632  
     12019-03-28  John Wilander  <wilander@apple.com>
     2
     3        Resource Load Statistics: IPC to the WebsiteDataStore in the UI process from NetworkProcess::deleteWebsiteDataForRegistrableDomains()
     4        https://bugs.webkit.org/show_bug.cgi?id=196281
     5        <rdar://problem/48938748>
     6
     7        Reviewed by Alex Christensen.
     8
     9        This patch adds the function isStatisticsHasLocalStorage() to the
     10        TestRunner. With it, the page can query the WebsiteDataStore in the
     11        UI process to make sure that it sees LocalStorage.
     12
     13        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
     14        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
     15        (WTR::TestRunner::isStatisticsHasLocalStorage):
     16        * WebKitTestRunner/InjectedBundle/TestRunner.h:
     17        * WebKitTestRunner/TestController.cpp:
     18        (WTR::TestController::isStatisticsHasLocalStorage):
     19        * WebKitTestRunner/TestController.h:
     20        * WebKitTestRunner/TestInvocation.cpp:
     21        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
     22
    1232019-03-28  Jiewen Tan  <jiewen_tan@apple.com>
    224
  • trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl

    r243181 r243632  
    322322    void statisticsClearThroughWebsiteDataRemoval(object callback);
    323323    void statisticsDeleteCookiesForHost(DOMString hostName, boolean includeHttpOnlyCookies);
     324    boolean isStatisticsHasLocalStorage(DOMString hostName);
    324325    void setStatisticsCacheMaxAgeCap(double seconds);
    325326    void statisticsResetToConsistentState(object completionHandler);
  • trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp

    r243181 r243632  
    20712071}
    20722072
     2073bool TestRunner::isStatisticsHasLocalStorage(JSStringRef hostName)
     2074{
     2075    auto messageName = adoptWK(WKStringCreateWithUTF8CString("IsStatisticsHasLocalStorage"));
     2076    auto messageBody = adoptWK(WKStringCreateWithJSString(hostName));
     2077    WKTypeRef returnData = nullptr;
     2078    WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
     2079    ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
     2080    return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
     2081}
     2082
    20732083void TestRunner::setStatisticsCacheMaxAgeCap(double seconds)
    20742084{
  • trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h

    r243181 r243632  
    432432    void statisticsDeleteCookiesForHost(JSStringRef hostName, bool includeHttpOnlyCookies);
    433433    void statisticsCallClearThroughWebsiteDataRemovalCallback();
     434    bool isStatisticsHasLocalStorage(JSStringRef hostName);
    434435    void setStatisticsCacheMaxAgeCap(double seconds);
    435436    void statisticsResetToConsistentState(JSValueRef completionHandler);
  • trunk/Tools/WebKitTestRunner/TestController.cpp

    r243559 r243632  
    34213421}
    34223422
     3423bool TestController::isStatisticsHasLocalStorage(WKStringRef host)
     3424{
     3425    auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
     3426    ResourceStatisticsCallbackContext context(*this);
     3427    WKWebsiteDataStoreStatisticsHasLocalStorage(dataStore, host, &context, resourceStatisticsBooleanResultCallback);
     3428    runUntil(context.done, noTimeout);
     3429    return context.result;
     3430}
     3431
    34233432void TestController::setStatisticsCacheMaxAgeCap(double seconds)
    34243433{
  • trunk/Tools/WebKitTestRunner/TestController.h

    r243559 r243632  
    243243    void statisticsClearThroughWebsiteDataRemoval();
    244244    void statisticsDeleteCookiesForHost(WKStringRef host, bool includeHttpOnlyCookies);
     245    bool isStatisticsHasLocalStorage(WKStringRef hostName);
    245246    void setStatisticsCacheMaxAgeCap(double seconds);
    246247    void statisticsResetToConsistentState();
  • trunk/Tools/WebKitTestRunner/TestInvocation.cpp

    r243181 r243632  
    14281428    }
    14291429
     1430    if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsHasLocalStorage")) {
     1431        ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
     1432       
     1433        WKStringRef hostName = static_cast<WKStringRef>(messageBody);
     1434        bool hasLocalStorage = TestController::singleton().isStatisticsHasLocalStorage(hostName);
     1435        auto result = adoptWK(WKBooleanCreate(hasLocalStorage));
     1436        return result;
     1437    }
     1438
    14301439    if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsCacheMaxAgeCap")) {
    14311440        ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID());
Note: See TracChangeset for help on using the changeset viewer.