Diff
Modified: trunk/LayoutTests/ChangeLog (243631 => 243632)
--- trunk/LayoutTests/ChangeLog 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/LayoutTests/ChangeLog 2019-03-29 01:15:59 UTC (rev 243632)
@@ -1,3 +1,16 @@
+2019-03-28 John Wilander <[email protected]>
+
+ 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.
+
+ 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:
+
2019-03-28 Shawn Roberts <[email protected]>
The following layout tests are flaky failures
Modified: trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration-expected.txt (243631 => 243632)
--- trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration-expected.txt 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration-expected.txt 2019-03-29 01:15:59 UTC (rev 243632)
@@ -3,13 +3,13 @@
Before deletion: Client-side cookie exists.
Before deletion: HttpOnly cookie exists.
Before deletion: Regular server-side cookie exists.
-
+Before deletion: LocalStorage entry does exist.
Before deletion: IDB entry does exist.
After deletion: HttpOnly cookie exists.
After deletion: Client-side cookie exists.
After deletion: Regular server-side cookie exists.
-
+After deletion: LocalStorage entry does not exist.
After deletion: IDB entry does not exist.
Modified: trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration.html (243631 => 243632)
--- trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration.html 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration.html 2019-03-29 01:15:59 UTC (rev 243632)
@@ -91,6 +91,44 @@
};
}
+ const maxIntervals = 20;
+ let intervalCounter;
+ let checkLocalStorageCallback;
+ let checkLocalStorageIntervalID;
+ const localStorageName = "test";
+ const localStorageValue = "value";
+ function checkLocalStorageExists(isAfterDeletion, callback) {
+ intervalCounter = 0;
+ checkLocalStorageCallback = callback;
+ if (!isAfterDeletion) {
+ // Check until there is LocalStorage.
+ checkLocalStorageIntervalID = setInterval(function() {
+ if (++intervalCounter === maxIntervals) {
+ clearInterval(checkLocalStorageIntervalID);
+ checkLocalStorageCallback();
+ } else if (testRunner.isStatisticsHasLocalStorage(destinationOrigin)) {
+ clearInterval(checkLocalStorageIntervalID);
+ let value = localStorage.getItem(localStorageName);
+ addOutput("Before deletion: LocalStorage entry " + (value === localStorageValue ? "does" : "does not") + " exist.");
+ checkLocalStorageCallback();
+ }
+ }, 100);
+ } else {
+ // Check until there is no LocalStorage.
+ checkLocalStorageIntervalID = setInterval(function() {
+ if (++intervalCounter === maxIntervals) {
+ clearInterval(checkLocalStorageIntervalID);
+ checkLocalStorageCallback();
+ } else if (!testRunner.isStatisticsHasLocalStorage(destinationOrigin)) {
+ clearInterval(checkLocalStorageIntervalID);
+ let value = localStorage.getItem(localStorageName);
+ addOutput("After deletion: LocalStorage entry " + (value === localStorageValue ? "does" : "does not") + " exist.");
+ checkLocalStorageCallback();
+ }
+ }, 100);
+ }
+ }
+
async function writeWebsiteDataAndContinue() {
// Write cookies.
await fetch("/cookies/resources/set-http-only-cookie.php?cookieName=" + httpOnlyCookieName, { credentials: "same-origin" });
@@ -98,21 +136,31 @@
document.cookie = clientSideCookieName + "=1";
checkCookies(false);
- addLinebreakToOutput();
- // Write IndexedDB.
- createIDBDataStore(function () {
- checkIDBDataStoreExists(false, processWebsiteDataAndContinue);
+ // Write LocalStorage
+ localStorage.setItem(localStorageName, localStorageValue);
+ checkLocalStorageExists(false, function() {
+
+ // Write IndexedDB.
+ createIDBDataStore(function () {
+ checkIDBDataStoreExists(false, function() {
+ addLinebreakToOutput();
+ processWebsiteDataAndContinue();
+ });
+ });
});
}
function processWebsiteDataAndContinue() {
testRunner.statisticsProcessStatisticsAndDataRecords();
+ checkWebsiteDataAndContinue();
+ }
- addLinebreakToOutput();
+ function checkWebsiteDataAndContinue() {
checkCookies(true);
- addLinebreakToOutput();
- checkIDBDataStoreExists(true, finishTest);
+ checkLocalStorageExists(true, function () {
+ checkIDBDataStoreExists(true, finishTest);
+ });
}
function finishTest() {
Modified: trunk/Source/WebKit/ChangeLog (243631 => 243632)
--- trunk/Source/WebKit/ChangeLog 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/ChangeLog 2019-03-29 01:15:59 UTC (rev 243632)
@@ -1,3 +1,62 @@
+2019-03-28 John Wilander <[email protected]>
+
+ 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.
+
+ 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:
+
2019-03-28 Jiewen Tan <[email protected]>
API::Data::createWithoutCopying should do a null check before calling CFRelease
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (243631 => 243632)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2019-03-29 01:15:59 UTC (rev 243632)
@@ -57,7 +57,6 @@
#include "WebSWOriginStore.h"
#include "WebSWServerConnection.h"
#include "WebSWServerToContextConnection.h"
-#include "WebsiteData.h"
#include "WebsiteDataFetchOption.h"
#include "WebsiteDataStore.h"
#include "WebsiteDataStoreParameters.h"
@@ -1525,23 +1524,13 @@
~CallbackAggregator()
{
- RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] () mutable {
- HashSet<RegistrableDomain> domains;
- for (const auto& hostnameWithCookies : websiteData.hostNamesWithCookies)
- domains.add(RegistrableDomain::uncheckedCreateFromHost(hostnameWithCookies));
-
- for (const auto& hostnameWithHSTS : websiteData.hostNamesWithHSTSCache)
- domains.add(RegistrableDomain::uncheckedCreateFromHost(hostnameWithHSTS));
-
- for (const auto& entry : websiteData.entries)
- domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
-
+ RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), domains = WTFMove(m_domains)] () mutable {
completionHandler(domains);
});
}
CompletionHandler<void(const HashSet<RegistrableDomain>&)> m_completionHandler;
- WebsiteData m_websiteData;
+ HashSet<RegistrableDomain> m_domains;
};
auto callbackAggregator = adoptRef(*new CallbackAggregator([this, completionHandler = WTFMove(completionHandler), shouldNotifyPage] (const HashSet<RegistrableDomain>& domainsWithData) mutable {
@@ -1553,7 +1542,8 @@
});
}));
- auto& websiteDataStore = callbackAggregator->m_websiteData;
+ HashSet<String> hostNamesWithCookies;
+ HashSet<String> hostNamesWithHSTSCache;
Vector<RegistrableDomain> domainsToDeleteCookiesFor;
Vector<RegistrableDomain> domainsToDeleteAllButHttpOnlyCookiesFor;
@@ -1575,13 +1565,19 @@
}
}
if (auto* networkStorageSession = storageSession(sessionID)) {
- networkStorageSession->getHostnamesWithCookies(websiteDataStore.hostNamesWithCookies);
+ networkStorageSession->getHostnamesWithCookies(hostNamesWithCookies);
- hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteCookiesFor, websiteDataStore.hostNamesWithCookies);
+ hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteCookiesFor, hostNamesWithCookies);
networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::Yes);
- hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteAllButHttpOnlyCookiesFor, websiteDataStore.hostNamesWithCookies);
+ for (const auto& host : hostnamesWithCookiesToDelete)
+ callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
+
+ hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteAllButHttpOnlyCookiesFor, hostNamesWithCookies);
networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::No);
+
+ for (const auto& host : hostnamesWithCookiesToDelete)
+ callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
}
} else {
for (auto& domain : domains.keys())
@@ -1592,8 +1588,12 @@
#if PLATFORM(COCOA)
if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
if (auto* networkStorageSession = storageSession(sessionID)) {
- getHostNamesWithHSTSCache(*networkStorageSession, websiteDataStore.hostNamesWithHSTSCache);
- hostnamesWithHSTSToDelete = filterForRegistrableDomains(domainsToDeleteAllButCookiesFor, websiteDataStore.hostNamesWithHSTSCache);
+ getHostNamesWithHSTSCache(*networkStorageSession, hostNamesWithHSTSCache);
+ hostnamesWithHSTSToDelete = filterForRegistrableDomains(domainsToDeleteAllButCookiesFor, hostNamesWithHSTSCache);
+
+ for (const auto& host : hostnamesWithHSTSToDelete)
+ callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
+
deleteHSTSCacheForHostNames(*networkStorageSession, hostnamesWithHSTSToDelete);
}
}
@@ -1601,9 +1601,10 @@
/*
// FIXME: No API to delete credentials by origin
+ HashSet<String> originsWithCredentials;
if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
if (storageSession(sessionID))
- websiteDataStore.originsWithCredentials = storageSession(sessionID)->credentialStorage().originsWithCredentials();
+ originsWithCredentials = storageSession(sessionID)->credentialStorage().originsWithCredentials();
}
*/
@@ -1612,8 +1613,9 @@
auto entriesToDelete = filterForRegistrableDomains(domainsToDeleteAllButCookiesFor, entries);
- callbackAggregator->m_websiteData.entries.appendVector(entriesToDelete);
-
+ for (const auto& entry : entriesToDelete)
+ callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
+
for (auto& entry : entriesToDelete)
CacheStorage::Engine::clearCachesForOrigin(*this, sessionID, SecurityOriginData { entry.origin }, [callbackAggregator = callbackAggregator.copyRef()] { });
});
@@ -1627,11 +1629,12 @@
RunLoop::main().dispatch([this, sessionID, domainsToDeleteAllButCookiesFor = crossThreadCopy(domainsToDeleteAllButCookiesFor), callbackAggregator = callbackAggregator.copyRef(), securityOrigins = indexedDatabaseOrigins(path)] {
Vector<SecurityOriginData> entriesToDelete;
for (const auto& securityOrigin : securityOrigins) {
- if (!domainsToDeleteAllButCookiesFor.contains(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host)))
+ auto domain = RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host);
+ if (!domainsToDeleteAllButCookiesFor.contains(domain))
continue;
entriesToDelete.append(securityOrigin);
- callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::IndexedDBDatabases, 0 });
+ callbackAggregator->m_domains.add(domain);
}
idbServer(sessionID).closeAndDeleteDatabasesForOrigins(entriesToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
@@ -1647,7 +1650,7 @@
for (auto& securityOrigin : securityOrigins) {
if (!domainsToDeleteAllButCookiesFor.contains(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host)))
continue;
- callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::ServiceWorkerRegistrations, 0 });
+ callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host));
swServerForSession(sessionID).clear(securityOrigin, [callbackAggregator = callbackAggregator.copyRef()] { });
}
});
@@ -1662,11 +1665,20 @@
if (!domainsToDeleteAllButCookiesFor.contains(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host)))
continue;
entriesToDelete.append(entry.origin);
- callbackAggregator->m_websiteData.entries.append(entry);
+ callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
}
clearDiskCacheEntries(cache(), entriesToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
});
}
+
+ auto dataTypesForUIProcess = WebsiteData::filter(websiteDataTypes, WebsiteDataProcessType::UI);
+ if (!dataTypesForUIProcess.isEmpty() && !domainsToDeleteAllButCookiesFor.isEmpty()) {
+ CompletionHandler<void(const HashSet<RegistrableDomain>&)> completionHandler = [callbackAggregator = callbackAggregator.copyRef()] (const HashSet<RegistrableDomain>& domains) {
+ for (auto& domain : domains)
+ callbackAggregator->m_domains.add(domain);
+ };
+ parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::DeleteWebsiteDataInUIProcessForRegistrableDomains(sessionID, dataTypesForUIProcess, fetchOptions, domainsToDeleteAllButCookiesFor), WTFMove(completionHandler));
+ }
}
void NetworkProcess::deleteCookiesForTesting(PAL::SessionID sessionID, RegistrableDomain domain, bool includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (243631 => 243632)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2019-03-29 01:15:59 UTC (rev 243632)
@@ -33,6 +33,7 @@
#include "NetworkHTTPSUpgradeChecker.h"
#include "SandboxExtension.h"
#include "WebResourceLoadStatisticsStore.h"
+#include "WebsiteData.h"
#include <WebCore/AdClickAttribution.h>
#include <WebCore/ClientOrigin.h>
#include <WebCore/DiagnosticLoggingClient.h>
Modified: trunk/Source/WebKit/Shared/WebsiteData/WebsiteData.cpp (243631 => 243632)
--- trunk/Source/WebKit/Shared/WebsiteData/WebsiteData.cpp 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/Shared/WebsiteData/WebsiteData.cpp 2019-03-29 01:15:59 UTC (rev 243632)
@@ -27,6 +27,7 @@
#include "WebsiteData.h"
#include "ArgumentCoders.h"
+#include "WebsiteDataType.h"
#include <WebCore/SecurityOriginData.h>
#include <wtf/text/StringHash.h>
@@ -86,4 +87,59 @@
return true;
}
+WebsiteDataProcessType WebsiteData::ownerProcess(WebsiteDataType dataType)
+{
+ switch (dataType) {
+ case WebsiteDataType::Cookies:
+ return WebsiteDataProcessType::Network;
+ case WebsiteDataType::DiskCache:
+ return WebsiteDataProcessType::Network;
+ case WebsiteDataType::MemoryCache:
+ return WebsiteDataProcessType::Web;
+ case WebsiteDataType::OfflineWebApplicationCache:
+ return WebsiteDataProcessType::UI;
+ case WebsiteDataType::SessionStorage:
+ return WebsiteDataProcessType::UI;
+ case WebsiteDataType::LocalStorage:
+ return WebsiteDataProcessType::UI;
+ case WebsiteDataType::WebSQLDatabases:
+ return WebsiteDataProcessType::UI;
+ case WebsiteDataType::IndexedDBDatabases:
+ return WebsiteDataProcessType::Network;
+ case WebsiteDataType::MediaKeys:
+ return WebsiteDataProcessType::UI;
+ case WebsiteDataType::HSTSCache:
+ return WebsiteDataProcessType::Network;
+ case WebsiteDataType::SearchFieldRecentSearches:
+ return WebsiteDataProcessType::UI;
+#if ENABLE(NETSCAPE_PLUGIN_API)
+ case WebsiteDataType::PlugInData:
+ return WebsiteDataProcessType::UI;
+#endif
+ case WebsiteDataType::ResourceLoadStatistics:
+ return WebsiteDataProcessType::Network;
+ case WebsiteDataType::Credentials:
+ return WebsiteDataProcessType::Network;
+#if ENABLE(SERVICE_WORKER)
+ case WebsiteDataType::ServiceWorkerRegistrations:
+ return WebsiteDataProcessType::Network;
+#endif
+ case WebsiteDataType::DOMCache:
+ return WebsiteDataProcessType::Network;
+ case WebsiteDataType::DeviceIdHashSalt:
+ return WebsiteDataProcessType::UI;
+ }
}
+
+OptionSet<WebsiteDataType> WebsiteData::filter(OptionSet<WebsiteDataType> unfilteredWebsiteDataTypes, WebsiteDataProcessType WebsiteDataProcessType)
+{
+ OptionSet<WebsiteDataType> filtered;
+ for (auto dataType : unfilteredWebsiteDataTypes) {
+ if (ownerProcess(dataType) == WebsiteDataProcessType)
+ filtered.add(dataType);
+ }
+
+ return filtered;
+}
+
+}
Modified: trunk/Source/WebKit/Shared/WebsiteData/WebsiteData.h (243631 => 243632)
--- trunk/Source/WebKit/Shared/WebsiteData/WebsiteData.h 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/Shared/WebsiteData/WebsiteData.h 2019-03-29 01:15:59 UTC (rev 243632)
@@ -28,6 +28,7 @@
#include <WebCore/SecurityOriginData.h>
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
+#include <wtf/OptionSet.h>
#include <wtf/Vector.h>
namespace IPC {
@@ -39,6 +40,8 @@
enum class WebsiteDataType;
+enum class WebsiteDataProcessType { Network, UI, Web };
+
struct WebsiteData {
struct Entry {
WebCore::SecurityOriginData origin;
@@ -62,6 +65,8 @@
void encode(IPC::Encoder&) const;
static bool decode(IPC::Decoder&, WebsiteData&);
+ static WebsiteDataProcessType ownerProcess(WebsiteDataType);
+ static OptionSet<WebsiteDataType> filter(OptionSet<WebsiteDataType>, WebsiteDataProcessType);
};
}
Modified: trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp (243631 => 243632)
--- trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp 2019-03-29 01:15:59 UTC (rev 243632)
@@ -449,6 +449,17 @@
#endif
}
+void WKWebsiteDataStoreStatisticsHasLocalStorage(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, void* context, WKWebsiteDataStoreStatisticsHasLocalStorageFunction callback)
+{
+#if ENABLE(RESOURCE_LOAD_STATISTICS)
+ WebKit::toImpl(dataStoreRef)->websiteDataStore().hasLocalStorageForTesting(URL(URL(), WebKit::toImpl(host)->string()), [context, callback](bool hasLocalStorage) {
+ callback(hasLocalStorage, context);
+ });
+#else
+ callback(false, context);
+#endif
+}
+
void WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap(WKWebsiteDataStoreRef dataStoreRef, double seconds, void* context, WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction callback)
{
#if ENABLE(RESOURCE_LOAD_STATISTICS)
Modified: trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h (243631 => 243632)
--- trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h 2019-03-29 01:15:59 UTC (rev 243632)
@@ -99,6 +99,8 @@
WK_EXPORT void WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemoval(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemovalFunction callback);
typedef void (*WKWebsiteDataStoreStatisticsDeleteCookiesForTestingFunction)(void* functionContext);
WK_EXPORT void WKWebsiteDataStoreStatisticsDeleteCookiesForTesting(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, bool includeHttpOnlyCookies, void* context, WKWebsiteDataStoreStatisticsDeleteCookiesForTestingFunction callback);
+typedef void (*WKWebsiteDataStoreStatisticsHasLocalStorageFunction)(bool hasLocalStorage, void* functionContext);
+WK_EXPORT void WKWebsiteDataStoreStatisticsHasLocalStorage(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, void* context, WKWebsiteDataStoreStatisticsHasLocalStorageFunction callback);
typedef void (*WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction)(void* functionContext);
WK_EXPORT void WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap(WKWebsiteDataStoreRef dataStoreRef, double seconds, void* context, WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction);
typedef void (*WKWebsiteDataStoreStatisticsResetToConsistentStateFunction)(void* functionContext);
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (243631 => 243632)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp 2019-03-29 01:15:59 UTC (rev 243632)
@@ -991,6 +991,22 @@
sendWithAsyncReply(Messages::NetworkProcess::DeleteCookiesForTesting(sessionID, domain, includeHttpOnlyCookies), WTFMove(completionHandler));
}
+
+void NetworkProcessProxy::deleteWebsiteDataInUIProcessForRegistrableDomains(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, Vector<RegistrableDomain> domains, CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&& completionHandler)
+{
+ auto* websiteDataStore = websiteDataStoreFromSessionID(sessionID);
+ if (!websiteDataStore || dataTypes.isEmpty() || domains.isEmpty()) {
+ completionHandler({ });
+ return;
+ }
+
+ websiteDataStore->fetchDataForRegistrableDomains(dataTypes, fetchOptions, domains, [dataTypes, websiteDataStore = makeRef(*websiteDataStore), completionHandler = WTFMove(completionHandler)] (Vector<WebsiteDataRecord>&& matchingDataRecords, HashSet<WebCore::RegistrableDomain>&& domainsWithMatchingDataRecords) mutable {
+ websiteDataStore->removeData(dataTypes, WTFMove(matchingDataRecords), [domainsWithMatchingDataRecords = WTFMove(domainsWithMatchingDataRecords), completionHandler = WTFMove(completionHandler)] () mutable {
+ completionHandler(WTFMove(domainsWithMatchingDataRecords));
+ });
+ });
+}
+
#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
void NetworkProcessProxy::sendProcessWillSuspendImminently()
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (243631 => 243632)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h 2019-03-29 01:15:59 UTC (rev 243632)
@@ -149,6 +149,7 @@
void setCrossSiteLoadWithLinkDecorationForTesting(PAL::SessionID, const NavigatedFromDomain&, const NavigatedToDomain&, CompletionHandler<void()>&&);
void resetCrossSiteLoadsWithLinkDecorationForTesting(PAL::SessionID, CompletionHandler<void()>&&);
void deleteCookiesForTesting(PAL::SessionID, const RegistrableDomain&, bool includeHttpOnlyCookies, CompletionHandler<void()>&&);
+ void deleteWebsiteDataInUIProcessForRegistrableDomains(PAL::SessionID, OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, Vector<RegistrableDomain>, CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&&);
#endif
void processReadyToSuspend();
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in (243631 => 243632)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in 2019-03-29 01:15:59 UTC (rev 243632)
@@ -48,6 +48,7 @@
NotifyWebsiteDataScanForRegistrableDomainsFinished()
NotifyResourceLoadStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
RequestStorageAccessConfirm(uint64_t pageID, uint64_t frameID, WebCore::RegistrableDomain subFrameDomain, WebCore::RegistrableDomain topFrameDomain) -> (bool userDidGrantAccess) Async
+ DeleteWebsiteDataInUIProcessForRegistrableDomains(PAL::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> dataTypes, OptionSet<WebKit::WebsiteDataFetchOption> fetchOptions, Vector<WebCore::RegistrableDomain> domains) -> (HashSet<WebCore::RegistrableDomain> domainsWithMatchingDataRecords) Async
#endif
#if ENABLE(CONTENT_EXTENSIONS)
ContentExtensionRules(WebKit::UserContentControllerIdentifier identifier)
Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataRecord.cpp (243631 => 243632)
--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataRecord.cpp 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataRecord.cpp 2019-03-29 01:15:59 UTC (rev 243632)
@@ -28,6 +28,7 @@
#include <WebCore/LocalizedStrings.h>
#include <WebCore/PublicSuffix.h>
+#include <WebCore/RegistrableDomain.h>
#include <WebCore/SecurityOrigin.h>
#if PLATFORM(COCOA)
@@ -113,20 +114,20 @@
return !suffixOffset || host[suffixOffset - 1] == '.';
}
-bool WebsiteDataRecord::matchesTopPrivatelyControlledDomain(const String& topPrivatelyControlledDomain) const
+bool WebsiteDataRecord::matches(const WebCore::RegistrableDomain& domain) const
{
- if (topPrivatelyControlledDomain.isEmpty())
+ if (domain.isEmpty())
return false;
if (types.contains(WebsiteDataType::Cookies)) {
for (const auto& hostName : cookieHostNames) {
- if (hostIsInDomain(hostName, topPrivatelyControlledDomain))
+ if (hostIsInDomain(hostName, domain.string()))
return true;
}
}
for (const auto& dataRecordOriginData : origins) {
- if (hostIsInDomain(dataRecordOriginData.host, topPrivatelyControlledDomain))
+ if (hostIsInDomain(dataRecordOriginData.host, domain.string()))
return true;
}
Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataRecord.h (243631 => 243632)
--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataRecord.h 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataRecord.h 2019-03-29 01:15:59 UTC (rev 243632)
@@ -36,6 +36,7 @@
#include <wtf/text/WTFString.h>
namespace WebCore {
+class RegistrableDomain;
class SecurityOrigin;
}
@@ -72,7 +73,7 @@
HashSet<String> originsWithCredentials;
HashSet<String> HSTSCacheHostNames;
- bool matchesTopPrivatelyControlledDomain(const String&) const;
+ bool matches(const WebCore::RegistrableDomain&) const;
String topPrivatelyControlledDomain();
};
Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp (243631 => 243632)
--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp 2019-03-29 01:15:59 UTC (rev 243632)
@@ -623,37 +623,44 @@
callbackAggregator->callIfNeeded();
}
+#if ENABLE(RESOURCE_LOAD_STATISTICS)
+void WebsiteDataStore::fetchDataForRegistrableDomains(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, const Vector<WebCore::RegistrableDomain>& domains, CompletionHandler<void(Vector<WebsiteDataRecord>&&, HashSet<WebCore::RegistrableDomain>&&)>&& completionHandler)
+{
+ fetchDataAndApply(dataTypes, fetchOptions, m_queue.copyRef(), [domains = crossThreadCopy(domains), completionHandler = WTFMove(completionHandler)] (auto&& existingDataRecords) mutable {
+ ASSERT(!RunLoop::isMain());
+
+ Vector<WebsiteDataRecord> matchingDataRecords;
+ HashSet<WebCore::RegistrableDomain> domainsWithMatchingDataRecords;
+ for (auto&& dataRecord : existingDataRecords) {
+ for (auto& domain : domains) {
+ if (dataRecord.matches(domain)) {
+ matchingDataRecords.append(WTFMove(dataRecord));
+ domainsWithMatchingDataRecords.add(domain.isolatedCopy());
+ break;
+ }
+ }
+ }
+ RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), matchingDataRecords = WTFMove(matchingDataRecords), domainsWithMatchingDataRecords = WTFMove(domainsWithMatchingDataRecords)] () mutable {
+ completionHandler(WTFMove(matchingDataRecords), WTFMove(domainsWithMatchingDataRecords));
+ });
+ });
+}
+#endif
+
static ProcessAccessType computeNetworkProcessAccessTypeForDataRemoval(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
{
ProcessAccessType processAccessType = ProcessAccessType::None;
- if (dataTypes.contains(WebsiteDataType::Cookies)) {
- if (isNonPersistentStore)
- processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched);
- else
- processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
+ for (auto dataType : dataTypes) {
+ if (dataType == WebsiteDataType::Cookies) {
+ if (isNonPersistentStore)
+ processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched);
+ else
+ processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
+ } else if (WebsiteData::ownerProcess(dataType) == WebsiteDataProcessType::Network)
+ return ProcessAccessType::Launch;
}
-
- if (dataTypes.contains(WebsiteDataType::DiskCache) && !isNonPersistentStore)
- processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
-
- if (dataTypes.contains(WebsiteDataType::HSTSCache))
- processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
-
- if (dataTypes.contains(WebsiteDataType::Credentials))
- processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
-
- if (dataTypes.contains(WebsiteDataType::DOMCache))
- processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
-
- if (dataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !isNonPersistentStore)
- processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
-#if ENABLE(SERVICE_WORKER)
- if (dataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !isNonPersistentStore)
- processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
-#endif
-
return processAccessType;
}
@@ -1795,6 +1802,25 @@
networkProcess->deleteCookiesForTesting(m_sessionID, WebCore::RegistrableDomain { url }, includeHttpOnlyCookies, [callbackAggregator = callbackAggregator.copyRef()] { });
}
}
+
+void WebsiteDataStore::hasLocalStorageForTesting(const URL& url, CompletionHandler<void(bool)>&& completionHandler) const
+{
+ if (!m_storageManager) {
+ completionHandler(false);
+ return;
+ }
+
+ m_storageManager->getLocalStorageOrigins([url, completionHandler = WTFMove(completionHandler)](HashSet<WebCore::SecurityOriginData>&& origins) mutable {
+ for (auto& origin : origins) {
+ if (origin.host == url.host()) {
+ completionHandler(true);
+ return;
+ }
+ }
+
+ completionHandler(false);
+ });
+}
#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
void WebsiteDataStore::setCacheMaxAgeCapForPrevalentResources(Seconds seconds, CompletionHandler<void()>&& completionHandler)
Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h (243631 => 243632)
--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h 2019-03-29 01:15:59 UTC (rev 243632)
@@ -61,6 +61,7 @@
}
namespace WebCore {
+class RegistrableDomain;
class SecurityOrigin;
}
@@ -125,6 +126,7 @@
void removeData(OptionSet<WebsiteDataType>, const Vector<WebsiteDataRecord>&, Function<void()>&& completionHandler);
#if ENABLE(RESOURCE_LOAD_STATISTICS)
+ void fetchDataForRegistrableDomains(OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, const Vector<WebCore::RegistrableDomain>&, CompletionHandler<void(Vector<WebsiteDataRecord>&&, HashSet<WebCore::RegistrableDomain>&&)>&&);
void clearPrevalentResource(const URL&, CompletionHandler<void()>&&);
void clearUserInteraction(const URL&, CompletionHandler<void()>&&);
void dumpResourceLoadStatistics(CompletionHandler<void(const String&)>&&);
@@ -171,6 +173,7 @@
void setCrossSiteLoadWithLinkDecorationForTesting(const URL& fromURL, const URL& toURL, CompletionHandler<void()>&&);
void resetCrossSiteLoadsWithLinkDecorationForTesting(CompletionHandler<void()>&&);
void deleteCookiesForTesting(const URL&, bool includeHttpOnlyCookies, CompletionHandler<void()>&&);
+ void hasLocalStorageForTesting(const URL&, CompletionHandler<void(bool)>&&) const;
#endif
void setCacheMaxAgeCapForPrevalentResources(Seconds, CompletionHandler<void()>&&);
void resetCacheMaxAgeCapForPrevalentResources(CompletionHandler<void()>&&);
Modified: trunk/Tools/ChangeLog (243631 => 243632)
--- trunk/Tools/ChangeLog 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Tools/ChangeLog 2019-03-29 01:15:59 UTC (rev 243632)
@@ -1,3 +1,25 @@
+2019-03-28 John Wilander <[email protected]>
+
+ 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.
+
+ 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):
+
2019-03-28 Jiewen Tan <[email protected]>
API::Data::createWithoutCopying should do a null check before calling CFRelease
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl (243631 => 243632)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl 2019-03-29 01:15:59 UTC (rev 243632)
@@ -321,6 +321,7 @@
void statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned long hours, object callback);
void statisticsClearThroughWebsiteDataRemoval(object callback);
void statisticsDeleteCookiesForHost(DOMString hostName, boolean includeHttpOnlyCookies);
+ boolean isStatisticsHasLocalStorage(DOMString hostName);
void setStatisticsCacheMaxAgeCap(double seconds);
void statisticsResetToConsistentState(object completionHandler);
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (243631 => 243632)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp 2019-03-29 01:15:59 UTC (rev 243632)
@@ -2070,6 +2070,16 @@
WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
}
+bool TestRunner::isStatisticsHasLocalStorage(JSStringRef hostName)
+{
+ auto messageName = adoptWK(WKStringCreateWithUTF8CString("IsStatisticsHasLocalStorage"));
+ auto messageBody = adoptWK(WKStringCreateWithJSString(hostName));
+ WKTypeRef returnData = nullptr;
+ WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
+ ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
+ return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
+}
+
void TestRunner::setStatisticsCacheMaxAgeCap(double seconds)
{
WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsCacheMaxAgeCap"));
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (243631 => 243632)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h 2019-03-29 01:15:59 UTC (rev 243632)
@@ -431,6 +431,7 @@
void statisticsClearThroughWebsiteDataRemoval(JSValueRef callback);
void statisticsDeleteCookiesForHost(JSStringRef hostName, bool includeHttpOnlyCookies);
void statisticsCallClearThroughWebsiteDataRemovalCallback();
+ bool isStatisticsHasLocalStorage(JSStringRef hostName);
void setStatisticsCacheMaxAgeCap(double seconds);
void statisticsResetToConsistentState(JSValueRef completionHandler);
void statisticsCallDidResetToConsistentStateCallback();
Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (243631 => 243632)
--- trunk/Tools/WebKitTestRunner/TestController.cpp 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp 2019-03-29 01:15:59 UTC (rev 243632)
@@ -3420,6 +3420,15 @@
runUntil(context.done, noTimeout);
}
+bool TestController::isStatisticsHasLocalStorage(WKStringRef host)
+{
+ auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
+ ResourceStatisticsCallbackContext context(*this);
+ WKWebsiteDataStoreStatisticsHasLocalStorage(dataStore, host, &context, resourceStatisticsBooleanResultCallback);
+ runUntil(context.done, noTimeout);
+ return context.result;
+}
+
void TestController::setStatisticsCacheMaxAgeCap(double seconds)
{
auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
Modified: trunk/Tools/WebKitTestRunner/TestController.h (243631 => 243632)
--- trunk/Tools/WebKitTestRunner/TestController.h 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Tools/WebKitTestRunner/TestController.h 2019-03-29 01:15:59 UTC (rev 243632)
@@ -242,6 +242,7 @@
void statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned);
void statisticsClearThroughWebsiteDataRemoval();
void statisticsDeleteCookiesForHost(WKStringRef host, bool includeHttpOnlyCookies);
+ bool isStatisticsHasLocalStorage(WKStringRef hostName);
void setStatisticsCacheMaxAgeCap(double seconds);
void statisticsResetToConsistentState();
Modified: trunk/Tools/WebKitTestRunner/TestInvocation.cpp (243631 => 243632)
--- trunk/Tools/WebKitTestRunner/TestInvocation.cpp 2019-03-28 23:47:00 UTC (rev 243631)
+++ trunk/Tools/WebKitTestRunner/TestInvocation.cpp 2019-03-29 01:15:59 UTC (rev 243632)
@@ -1427,6 +1427,15 @@
return nullptr;
}
+ if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsHasLocalStorage")) {
+ ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
+
+ WKStringRef hostName = static_cast<WKStringRef>(messageBody);
+ bool hasLocalStorage = TestController::singleton().isStatisticsHasLocalStorage(hostName);
+ auto result = adoptWK(WKBooleanCreate(hasLocalStorage));
+ return result;
+ }
+
if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsCacheMaxAgeCap")) {
ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID());
WKDoubleRef seconds = static_cast<WKDoubleRef>(messageBody);