Diff
Modified: trunk/Source/WebKit/ChangeLog (219903 => 219904)
--- trunk/Source/WebKit/ChangeLog 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Source/WebKit/ChangeLog 2017-07-26 05:44:05 UTC (rev 219904)
@@ -1,3 +1,57 @@
+2017-07-25 Brady Eidson <beid...@apple.com>
+
+ ResourceLoadStatistics grandfathering happens much too often.
+ <rdar://problem/32655834> and https://bugs.webkit.org/show_bug.cgi?id=174825
+
+ Reviewed by Chris Dumez.
+
+ The ResourceLoadStatistics grandfathering procedure happens too often.
+ - With an empty memory store, even though an empty memory store is a perfectly valid state.
+ - On each launch, even if grandfathering happened on the last launch - because grandfathering
+ data would not automatically be saved to disk.
+ - After clearing all website data, at which point no grandfathering can possibly be relevant
+ because there is no data to grandfather.
+
+ This patch fixes those cases and adds API tests to verify they remain fixed.
+
+ * Shared/WebsiteData/WebsiteDataType.h:
+
+ * UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
+ (+[WKWebsiteDataStore _allWebsiteDataTypesIncludingPrivate]): allWebsiteDataTypes, but even with the private ones.
+ (-[WKWebsiteDataStore _resourceLoadStatisticsClearInMemoryAndPersistentStore]): If the types being cleared cover all of
+ the types that ResourceLoadStatistics care about, don't grandfather afterwards.
+ (-[WKWebsiteDataStore _resourceLoadStatisticsClearInMemoryAndPersistentStoreModifiedSinceHours:]): Ditto.
+ (-[WKWebsiteDataStore _setResourceLoadStatisticsTestingCallback:]):
+ * UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
+
+ * UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.cpp:
+ (WebKit::ResourceLoadStatisticsPersistentStorage::populateMemoryStoreFromDisk): Don't grandfather if the store read from
+ disk is empty (as being empty is perfectly fine), and also log the event of "populated without grandfathering".
+ * UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.h:
+
+ * UIProcess/WebProcessProxy.cpp:
+ (WebKit::WebProcessProxy::topPrivatelyControlledDomainsWithWebsiteData):
+
+ * UIProcess/WebResourceLoadStatisticsStore.cpp:
+ (WebKit::WebResourceLoadStatisticsStore::monitoredDataTypes):
+ (WebKit::WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore):
+ (WebKit::WebResourceLoadStatisticsStore::~WebResourceLoadStatisticsStore):
+ (WebKit::WebResourceLoadStatisticsStore::removeDataRecords):
+ (WebKit::WebResourceLoadStatisticsStore::grandfatherExistingWebsiteData): Schedule a write right away so we don't re-grandfather
+ on next launch, and also log the grandfathering event.
+ (WebKit::WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent): Takes a ShouldGrandfather flag
+ to tell whether or not data should be re-grandfathered after the store is cleared.
+ (WebKit::WebResourceLoadStatisticsStore::logTestingEvent): Log the event to the testing client.
+ (WebKit::dataTypesToRemove): Deleted.
+ * UIProcess/WebResourceLoadStatisticsStore.h:
+
+ * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+ (WebKit::WebsiteDataStore::removeData):
+ (WebKit::WebsiteDataStore::setResourceLoadStatisticsEnabled):
+ (WebKit::WebsiteDataStore::enableResourceLoadStatisticsAndSetTestingCallback): Handles enabling ResourceLoadStatistics both
+ with and without a testing callback.
+ * UIProcess/WebsiteData/WebsiteDataStore.h:
+
2017-07-25 Andy Estes <aes...@apple.com>
[Apple Pay] Add "carteBancaire" as a supported payment network
Modified: trunk/Source/WebKit/Shared/WebsiteData/WebsiteDataType.h (219903 => 219904)
--- trunk/Source/WebKit/Shared/WebsiteData/WebsiteDataType.h 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Source/WebKit/Shared/WebsiteData/WebsiteDataType.h 2017-07-26 05:44:05 UTC (rev 219904)
@@ -43,11 +43,8 @@
#if ENABLE(NETSCAPE_PLUGIN_API)
PlugInData = 1 << 11,
#endif
-#if ENABLE(MEDIA_STREAM)
- MediaDeviceIdentifier = 1 << 12,
-#endif
- ResourceLoadStatistics = 1 << 13,
- Credentials = 1 << 14,
+ ResourceLoadStatistics = 1 << 12,
+ Credentials = 1 << 13,
};
};
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm (219903 => 219904)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm 2017-07-26 05:44:05 UTC (rev 219904)
@@ -157,6 +157,23 @@
@implementation WKWebsiteDataStore (WKPrivate)
++ (NSSet<NSString *> *)_allWebsiteDataTypesIncludingPrivate
+{
+ static dispatch_once_t onceToken;
+ static NSSet *allWebsiteDataTypes;
+ dispatch_once(&onceToken, ^ {
+ auto *privateTypes = @[_WKWebsiteDataTypeHSTSCache, _WKWebsiteDataTypeMediaKeys, _WKWebsiteDataTypeSearchFieldRecentSearches, _WKWebsiteDataTypeResourceLoadStatistics, _WKWebsiteDataTypeCredentials
+#if !TARGET_OS_IPHONE
+ , _WKWebsiteDataTypePlugInData
+#endif
+ ];
+
+ allWebsiteDataTypes = [[[self allWebsiteDataTypes] setByAddingObjectsFromArray:privateTypes] retain];
+ });
+
+ return allWebsiteDataTypes;
+}
+
- (instancetype)_initWithConfiguration:(_WKWebsiteDataStoreConfiguration *)configuration
{
if (!(self = [super init]))
@@ -449,7 +466,7 @@
if (!store)
return;
- store->scheduleClearInMemoryAndPersistent();
+ store->scheduleClearInMemoryAndPersistent(WebKit::WebResourceLoadStatisticsStore::ShouldGrandfather::Yes);
}
- (void)_resourceLoadStatisticsClearInMemoryAndPersistentStoreModifiedSinceHours:(unsigned)hours
@@ -458,7 +475,7 @@
if (!store)
return;
- store->scheduleClearInMemoryAndPersistent(std::chrono::system_clock::now() - std::chrono::hours(hours));
+ store->scheduleClearInMemoryAndPersistent(std::chrono::system_clock::now() - std::chrono::hours(hours), WebKit::WebResourceLoadStatisticsStore::ShouldGrandfather::Yes);
}
- (void)_resourceLoadStatisticsResetToConsistentState
@@ -473,6 +490,22 @@
store->scheduleClearInMemory();
}
+- (void)_setResourceLoadStatisticsTestingCallback:(void (^)(WKWebsiteDataStore *, NSString *))callback
+{
+ if (callback) {
+ _websiteDataStore->websiteDataStore().enableResourceLoadStatisticsAndSetTestingCallback([callback = makeBlockPtr(callback), self](const String& event) {
+ callback(self, (NSString *)event);
+ });
+ return;
+ }
+
+ auto* store = _websiteDataStore->websiteDataStore().resourceLoadStatistics();
+ if (!store)
+ return;
+
+ store->setStatisticsTestingCallback(nullptr);
+}
+
@end
#endif // WK_API_ENABLED
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h (219903 => 219904)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h 2017-07-26 05:44:05 UTC (rev 219904)
@@ -37,6 +37,8 @@
@interface WKWebsiteDataStore (WKPrivate)
++ (NSSet<NSString *> *)_allWebsiteDataTypesIncludingPrivate;
+
- (instancetype)_initWithConfiguration:(_WKWebsiteDataStoreConfiguration *)configuration WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
- (void)_fetchDataRecordsOfTypes:(NSSet<NSString *> *)dataTypes withOptions:(_WKWebsiteDataStoreFetchOptions)options completionHandler:(void (^)(NSArray<WKWebsiteDataRecord *> *))completionHandler;
@@ -71,6 +73,7 @@
- (void)_resourceLoadStatisticsClearInMemoryAndPersistentStore WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
- (void)_resourceLoadStatisticsClearInMemoryAndPersistentStoreModifiedSinceHours:(unsigned)hours WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
- (void)_resourceLoadStatisticsResetToConsistentState WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (void)_setResourceLoadStatisticsTestingCallback:(nullable void (^)(WKWebsiteDataStore *, NSString *))callback;
@end
Modified: trunk/Source/WebKit/UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.cpp (219903 => 219904)
--- trunk/Source/WebKit/UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.cpp 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Source/WebKit/UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.cpp 2017-07-26 05:44:05 UTC (rev 219904)
@@ -234,8 +234,7 @@
m_lastStatisticsFileSyncTime = readTime;
- if (m_memoryStore.isEmpty())
- m_memoryStore.grandfatherExistingWebsiteData();
+ m_memoryStore.logTestingEvent(ASCIILiteral("PopulatedWithoutGrandfathering"));
}
void ResourceLoadStatisticsPersistentStorage::asyncWriteTimerFired()
@@ -280,12 +279,12 @@
startMonitoringDisk();
}
-void ResourceLoadStatisticsPersistentStorage::scheduleOrWriteMemoryStore()
+void ResourceLoadStatisticsPersistentStorage::scheduleOrWriteMemoryStore(ForceImmediateWrite forceImmediateWrite)
{
ASSERT(!RunLoop::isMain());
auto timeSinceLastWrite = MonotonicTime::now() - m_lastStatisticsWriteTime;
- if (timeSinceLastWrite < minimumWriteInterval) {
+ if (forceImmediateWrite != ForceImmediateWrite::Yes && timeSinceLastWrite < minimumWriteInterval) {
if (!m_hasPendingWrite) {
m_hasPendingWrite = true;
Seconds delay = minimumWriteInterval - timeSinceLastWrite + 1_s;
Modified: trunk/Source/WebKit/UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.h (219903 => 219904)
--- trunk/Source/WebKit/UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.h 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Source/WebKit/UIProcess/Storage/ResourceLoadStatisticsPersistentStorage.h 2017-07-26 05:44:05 UTC (rev 219904)
@@ -45,7 +45,6 @@
~ResourceLoadStatisticsPersistentStorage();
void initialize();
- void scheduleOrWriteMemoryStore();
void clear();
void finishAllPendingWorkSynchronously();
@@ -53,6 +52,12 @@
void ref();
void deref();
+ enum class ForceImmediateWrite {
+ No,
+ Yes,
+ };
+ void scheduleOrWriteMemoryStore(ForceImmediateWrite);
+
private:
String storageDirectoryPath() const;
String resourceLogFilePath() const;
Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp (219903 => 219904)
--- trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp 2017-07-26 05:44:05 UTC (rev 219904)
@@ -327,6 +327,10 @@
callbackAggregator->removePendingCallback();
});
}
+
+ // FIXME: It's bizarre that this call is on WebProcessProxy and that it doesn't work if there are no visited pages.
+ // This should actually be a function of WebsiteDataStore and it should work even if there are no WebViews instances.
+ callbackAggregator->callIfNeeded();
}
void WebProcessProxy::notifyPageStatisticsAndDataRecordsProcessed()
Modified: trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp (219903 => 219904)
--- trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp 2017-07-26 05:44:05 UTC (rev 219904)
@@ -33,7 +33,6 @@
#include "WebResourceLoadStatisticsTelemetry.h"
#include "WebsiteDataFetchOption.h"
#include "WebsiteDataStore.h"
-#include "WebsiteDataType.h"
#include <WebCore/KeyedCoding.h>
#include <WebCore/ResourceLoadStatistics.h>
#include <wtf/CrossThreadCopier.h>
@@ -54,15 +53,12 @@
return ResourceLoadStatistics::primaryDomain(value).isolatedCopy();
}
-static const OptionSet<WebsiteDataType>& dataTypesToRemove()
+const OptionSet<WebsiteDataType>& WebResourceLoadStatisticsStore::monitoredDataTypes()
{
static NeverDestroyed<OptionSet<WebsiteDataType>> dataTypes(std::initializer_list<WebsiteDataType>({
WebsiteDataType::Cookies,
WebsiteDataType::IndexedDBDatabases,
WebsiteDataType::LocalStorage,
-#if ENABLE(MEDIA_STREAM)
- WebsiteDataType::MediaDeviceIdentifier,
-#endif
WebsiteDataType::MediaKeys,
WebsiteDataType::OfflineWebApplicationCache,
#if ENABLE(NETSCAPE_PLUGIN_API)
@@ -149,11 +145,12 @@
return mergedDates;
}
-WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore(const String& resourceLoadStatisticsDirectory, UpdateCookiePartitioningForDomainsHandler&& updateCookiePartitioningForDomainsHandler)
+WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore(const String& resourceLoadStatisticsDirectory, Function<void (const String&)>&& testingCallback, UpdateCookiePartitioningForDomainsHandler&& updateCookiePartitioningForDomainsHandler)
: m_statisticsQueue(WorkQueue::create("WebResourceLoadStatisticsStore Process Data Queue", WorkQueue::Type::Serial, WorkQueue::QOS::Utility))
, m_persistentStorage(*this, resourceLoadStatisticsDirectory)
, m_updateCookiePartitioningForDomainsHandler(WTFMove(updateCookiePartitioningForDomainsHandler))
, m_dailyTasksTimer(RunLoop::main(), this, &WebResourceLoadStatisticsStore::performDailyTasks)
+ , m_statisticsTestingCallback(WTFMove(testingCallback))
{
ASSERT(RunLoop::isMain());
@@ -192,7 +189,7 @@
setDataRecordsBeingRemoved(true);
RunLoop::main().dispatch([prevalentResourceDomains = CrossThreadCopier<Vector<String>>::copy(prevalentResourceDomains), this, protectedThis = makeRef(*this)] () mutable {
- WebProcessProxy::deleteWebsiteDataForTopPrivatelyControlledDomainsInAllPersistentDataStores(dataTypesToRemove(), WTFMove(prevalentResourceDomains), m_parameters.shouldNotifyPagesWhenDataRecordsWereScanned, [this, protectedThis = WTFMove(protectedThis)](const HashSet<String>& domainsWithDeletedWebsiteData) mutable {
+ WebProcessProxy::deleteWebsiteDataForTopPrivatelyControlledDomainsInAllPersistentDataStores(WebResourceLoadStatisticsStore::monitoredDataTypes(), WTFMove(prevalentResourceDomains), m_parameters.shouldNotifyPagesWhenDataRecordsWereScanned, [this, protectedThis = WTFMove(protectedThis)](const HashSet<String>& domainsWithDeletedWebsiteData) mutable {
m_statisticsQueue->dispatch([this, protectedThis = WTFMove(protectedThis), topDomains = CrossThreadCopier<HashSet<String>>::copy(domainsWithDeletedWebsiteData)] () mutable {
for (auto& prevalentResourceDomain : topDomains) {
auto& statistic = ensureResourceStatisticsForPrimaryDomain(prevalentResourceDomain);
@@ -232,7 +229,7 @@
});
}
- m_persistentStorage.scheduleOrWriteMemoryStore();
+ m_persistentStorage.scheduleOrWriteMemoryStore(ResourceLoadStatisticsPersistentStorage::ForceImmediateWrite::No);
}
void WebResourceLoadStatisticsStore::resourceLoadStatisticsUpdated(Vector<WebCore::ResourceLoadStatistics>&& origins)
@@ -250,7 +247,9 @@
ASSERT(!RunLoop::isMain());
RunLoop::main().dispatch([this, protectedThis = makeRef(*this)] () mutable {
- WebProcessProxy::topPrivatelyControlledDomainsWithWebsiteData(dataTypesToRemove(), m_parameters.shouldNotifyPagesWhenDataRecordsWereScanned, [this, protectedThis = WTFMove(protectedThis)] (HashSet<String>&& topPrivatelyControlledDomainsWithWebsiteData) mutable {
+ // FIXME: This method being a static call on WebProcessProxy is wrong.
+ // It should be on the data store that this object belongs to.
+ WebProcessProxy::topPrivatelyControlledDomainsWithWebsiteData(WebResourceLoadStatisticsStore::monitoredDataTypes(), m_parameters.shouldNotifyPagesWhenDataRecordsWereScanned, [this, protectedThis = WTFMove(protectedThis)] (HashSet<String>&& topPrivatelyControlledDomainsWithWebsiteData) mutable {
m_statisticsQueue->dispatch([this, protectedThis = WTFMove(protectedThis), topDomains = CrossThreadCopier<HashSet<String>>::copy(topPrivatelyControlledDomainsWithWebsiteData)] () mutable {
for (auto& topPrivatelyControlledDomain : topDomains) {
auto& statistic = ensureResourceStatisticsForPrimaryDomain(topPrivatelyControlledDomain);
@@ -257,7 +256,10 @@
statistic.grandfathered = true;
}
m_endOfGrandfatheringTimestamp = WallTime::now() + m_parameters.grandfatheringTime;
+ m_persistentStorage.scheduleOrWriteMemoryStore(ResourceLoadStatisticsPersistentStorage::ForceImmediateWrite::Yes);
});
+
+ logTestingEvent(ASCIILiteral("Grandfathered"));
});
});
}
@@ -483,21 +485,23 @@
});
}
-void WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent()
+void WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent(ShouldGrandfather shouldGrandfather)
{
ASSERT(RunLoop::isMain());
- m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this)] {
+ m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this), shouldGrandfather] {
clearInMemory();
m_persistentStorage.clear();
- grandfatherExistingWebsiteData();
+
+ if (shouldGrandfather == ShouldGrandfather::Yes)
+ grandfatherExistingWebsiteData();
});
}
-void WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent(std::chrono::system_clock::time_point modifiedSince)
+void WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent(std::chrono::system_clock::time_point modifiedSince, ShouldGrandfather shouldGrandfather)
{
// For now, be conservative and clear everything regardless of modifiedSince.
UNUSED_PARAM(modifiedSince);
- scheduleClearInMemoryAndPersistent();
+ scheduleClearInMemoryAndPersistent(shouldGrandfather);
}
void WebResourceLoadStatisticsStore::setTimeToLiveUserInteraction(Seconds seconds)
@@ -824,5 +828,20 @@
{
m_parameters = { };
}
-
+
+void WebResourceLoadStatisticsStore::logTestingEvent(const String& event)
+{
+ if (!m_statisticsTestingCallback)
+ return;
+
+ if (RunLoop::isMain())
+ m_statisticsTestingCallback(event);
+ else {
+ RunLoop::main().dispatch([this, protectedThis = makeRef(*this), event = event.isolatedCopy()] {
+ if (m_statisticsTestingCallback)
+ m_statisticsTestingCallback(event);
+ });
+ }
+}
+
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h (219903 => 219904)
--- trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h 2017-07-26 05:44:05 UTC (rev 219904)
@@ -28,6 +28,7 @@
#include "Connection.h"
#include "ResourceLoadStatisticsClassifier.h"
#include "ResourceLoadStatisticsPersistentStorage.h"
+#include "WebsiteDataType.h"
#include <wtf/MonotonicTime.h>
#include <wtf/RunLoop.h>
#include <wtf/Vector.h>
@@ -59,13 +60,15 @@
class WebResourceLoadStatisticsStore final : public IPC::Connection::WorkQueueMessageReceiver {
public:
using UpdateCookiePartitioningForDomainsHandler = WTF::Function<void(const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, ShouldClearFirst)>;
- static Ref<WebResourceLoadStatisticsStore> create(const String& resourceLoadStatisticsDirectory, UpdateCookiePartitioningForDomainsHandler&& updateCookiePartitioningForDomainsHandler = { })
+ static Ref<WebResourceLoadStatisticsStore> create(const String& resourceLoadStatisticsDirectory, Function<void (const String&)>&& testingCallback, UpdateCookiePartitioningForDomainsHandler&& updateCookiePartitioningForDomainsHandler = { })
{
- return adoptRef(*new WebResourceLoadStatisticsStore(resourceLoadStatisticsDirectory, WTFMove(updateCookiePartitioningForDomainsHandler)));
+ return adoptRef(*new WebResourceLoadStatisticsStore(resourceLoadStatisticsDirectory, WTFMove(testingCallback), WTFMove(updateCookiePartitioningForDomainsHandler)));
}
~WebResourceLoadStatisticsStore();
+ static const OptionSet<WebsiteDataType>& monitoredDataTypes();
+
bool isEmpty() const { return m_resourceStatisticsMap.isEmpty(); }
WorkQueue& statisticsQueue() { return m_statisticsQueue.get(); }
@@ -98,8 +101,13 @@
void scheduleCookiePartitioningStateReset();
void scheduleClearInMemory();
- void scheduleClearInMemoryAndPersistent();
- void scheduleClearInMemoryAndPersistent(std::chrono::system_clock::time_point modifiedSince);
+
+ enum class ShouldGrandfather {
+ No,
+ Yes,
+ };
+ void scheduleClearInMemoryAndPersistent(ShouldGrandfather);
+ void scheduleClearInMemoryAndPersistent(std::chrono::system_clock::time_point modifiedSince, ShouldGrandfather);
void setTimeToLiveUserInteraction(Seconds);
void setTimeToLiveCookiePartitionFree(Seconds);
@@ -117,9 +125,12 @@
void mergeWithDataFromDecoder(WebCore::KeyedDecoder&);
void clearInMemory();
void grandfatherExistingWebsiteData();
-
+
+ void setStatisticsTestingCallback(Function<void (const String&)>&& callback) { m_statisticsTestingCallback = WTFMove(callback); }
+ void logTestingEvent(const String&);
+
private:
- WebResourceLoadStatisticsStore(const String&, UpdateCookiePartitioningForDomainsHandler&&);
+ WebResourceLoadStatisticsStore(const String&, Function<void (const String&)>&& testingCallback, UpdateCookiePartitioningForDomainsHandler&&);
void removeDataRecords();
@@ -178,6 +189,8 @@
Parameters m_parameters;
bool m_dataRecordsBeingRemoved { false };
+
+ Function<void (const String&)> m_statisticsTestingCallback;
};
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp (219903 => 219904)
--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp 2017-07-26 05:44:05 UTC (rev 219904)
@@ -813,9 +813,20 @@
}
#endif
- if (dataTypes.contains(WebsiteDataType::ResourceLoadStatistics) && m_resourceLoadStatistics)
- m_resourceLoadStatistics->scheduleClearInMemoryAndPersistent(modifiedSince);
+ // FIXME <rdar://problem/33491222>; scheduleClearInMemoryAndPersistent does not have a completion handler,
+ // so the completion handler for this removeData() call can be called prematurely.
+ if (dataTypes.contains(WebsiteDataType::ResourceLoadStatistics) && m_resourceLoadStatistics) {
+ auto deletedTypesRaw = dataTypes.toRaw();
+ auto monitoredTypesRaw = WebResourceLoadStatisticsStore::monitoredDataTypes().toRaw();
+ // If we are deleting all of the data types that the resource load statistics store monitors
+ // we do not need to re-grandfather old data.
+ if ((monitoredTypesRaw & deletedTypesRaw) == monitoredTypesRaw)
+ m_resourceLoadStatistics->scheduleClearInMemoryAndPersistent(modifiedSince, WebResourceLoadStatisticsStore::ShouldGrandfather::No);
+ else
+ m_resourceLoadStatistics->scheduleClearInMemoryAndPersistent(modifiedSince, WebResourceLoadStatisticsStore::ShouldGrandfather::Yes);
+ }
+
// There's a chance that we don't have any pending callbacks. If so, we want to dispatch the completion handler right away.
callbackAggregator->callIfNeeded();
}
@@ -1082,9 +1093,20 @@
}
#endif
- if (dataTypes.contains(WebsiteDataType::ResourceLoadStatistics) && m_resourceLoadStatistics)
- m_resourceLoadStatistics->scheduleClearInMemoryAndPersistent();
+ // FIXME <rdar://problem/33491222>; scheduleClearInMemoryAndPersistent does not have a completion handler,
+ // so the completion handler for this removeData() call can be called prematurely.
+ if (dataTypes.contains(WebsiteDataType::ResourceLoadStatistics) && m_resourceLoadStatistics) {
+ auto deletedTypesRaw = dataTypes.toRaw();
+ auto monitoredTypesRaw = WebResourceLoadStatisticsStore::monitoredDataTypes().toRaw();
+ // If we are deleting all of the data types that the resource load statistics store monitors
+ // we do not need to re-grandfather old data.
+ if ((monitoredTypesRaw & deletedTypesRaw) == monitoredTypesRaw)
+ m_resourceLoadStatistics->scheduleClearInMemoryAndPersistent(WebResourceLoadStatisticsStore::ShouldGrandfather::No);
+ else
+ m_resourceLoadStatistics->scheduleClearInMemoryAndPersistent(WebResourceLoadStatisticsStore::ShouldGrandfather::Yes);
+ }
+
// There's a chance that we don't have any pending callbacks. If so, we want to dispatch the completion handler right away.
callbackAggregator->callIfNeeded();
}
@@ -1270,18 +1292,33 @@
return;
if (enabled) {
+ ASSERT(!m_resourceLoadStatistics);
+ enableResourceLoadStatisticsAndSetTestingCallback(nullptr);
+ return;
+ }
+
+ m_resourceLoadStatistics = nullptr;
+ for (auto& processPool : processPools())
+ processPool->setResourceLoadStatisticsEnabled(false);
+}
+
+void WebsiteDataStore::enableResourceLoadStatisticsAndSetTestingCallback(Function<void (const String&)>&& callback)
+{
+ if (m_resourceLoadStatistics) {
+ m_resourceLoadStatistics->setStatisticsTestingCallback(WTFMove(callback));
+ return;
+ }
+
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
- m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(m_configuration.resourceLoadStatisticsDirectory, [this] (const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, ShouldClearFirst shouldClearFirst) {
- updateCookiePartitioningForTopPrivatelyOwnedDomains(domainsToRemove, domainsToAdd, shouldClearFirst);
- });
+ m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(m_configuration.resourceLoadStatisticsDirectory, WTFMove(callback), [this] (const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, ShouldClearFirst shouldClearFirst) {
+ updateCookiePartitioningForTopPrivatelyOwnedDomains(domainsToRemove, domainsToAdd, shouldClearFirst);
+ });
#else
- m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(m_configuration.resourceLoadStatisticsDirectory);
+ m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(m_configuration.resourceLoadStatisticsDirectory, nullptr);
#endif
- } else
- m_resourceLoadStatistics = nullptr;
for (auto& processPool : processPools())
- processPool->setResourceLoadStatisticsEnabled(enabled);
+ processPool->setResourceLoadStatisticsEnabled(true);
}
DatabaseProcessCreationParameters WebsiteDataStore::databaseProcessParameters()
Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h (219903 => 219904)
--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h 2017-07-26 05:44:05 UTC (rev 219904)
@@ -127,6 +127,8 @@
void addPendingCookie(const WebCore::Cookie&);
void removePendingCookie(const WebCore::Cookie&);
+ void enableResourceLoadStatisticsAndSetTestingCallback(Function<void (const String&)>&& callback);
+
private:
explicit WebsiteDataStore(WebCore::SessionID);
explicit WebsiteDataStore(Configuration, WebCore::SessionID);
Modified: trunk/Tools/ChangeLog (219903 => 219904)
--- trunk/Tools/ChangeLog 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Tools/ChangeLog 2017-07-26 05:44:05 UTC (rev 219904)
@@ -1,3 +1,15 @@
+2017-07-25 Brady Eidson <beid...@apple.com>
+
+ ResourceLoadStatistics grandfathering happens much too often.
+ <rdar://problem/32655834> and https://bugs.webkit.org/show_bug.cgi?id=174825
+
+ Reviewed by Chris Dumez.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKit2Cocoa/EmptyGrandfatheredResourceLoadStatistics.plist: Added.
+ * TestWebKitAPI/Tests/WebKit2Cocoa/ResourceLoadStatistics.mm: Added.
+ (TEST):
+
2017-07-25 Matthew Stewart <matthew_r_stew...@apple.com>
Fix autoinstaller failing on autoinstall_everything
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (219903 => 219904)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2017-07-26 04:42:19 UTC (rev 219903)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2017-07-26 05:44:05 UTC (rev 219904)
@@ -173,6 +173,8 @@
51BCEE4E1C84F53B0042C82E /* IndexedDBMultiProcess-1.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51BCEE4C1C84F52C0042C82E /* IndexedDBMultiProcess-1.html */; };
51BCEE4F1C84F53B0042C82E /* IndexedDBMultiProcess-2.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51BCEE4D1C84F52C0042C82E /* IndexedDBMultiProcess-2.html */; };
51C683DE1EA134E800650183 /* WKURLSchemeHandler-1.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51C683DD1EA134DB00650183 /* WKURLSchemeHandler-1.mm */; };
+ 51C8E1A51F26AF4C00BF731B /* ResourceLoadStatistics.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51C8E1A41F26AC5400BF731B /* ResourceLoadStatistics.mm */; };
+ 51C8E1A91F27F49600BF731B /* EmptyGrandfatheredResourceLoadStatistics.plist in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51C8E1A81F27F47300BF731B /* EmptyGrandfatheredResourceLoadStatistics.plist */; };
51CD1C6C1B38CE4300142CA5 /* ModalAlerts.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51CD1C6A1B38CE3600142CA5 /* ModalAlerts.mm */; };
51CD1C721B38D48400142CA5 /* modal-alerts-in-new-about-blank-window.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51CD1C711B38D48400142CA5 /* modal-alerts-in-new-about-blank-window.html */; };
51D124981E763B02002B2820 /* WKHTTPCookieStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51D124971E763AF8002B2820 /* WKHTTPCookieStore.mm */; };
@@ -376,7 +378,6 @@
7CCE7EC11A411A7E00447C4C /* HTMLCollectionNamedItem.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B4F8FA3159D52B1002D9F94 /* HTMLCollectionNamedItem.mm */; };
7CCE7EC21A411A7E00447C4C /* HTMLFormCollectionNamedItem.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B26FC6B159D061000CC3765 /* HTMLFormCollectionNamedItem.mm */; };
7CCE7EC31A411A7E00447C4C /* InspectorBar.mm in Sources */ = {isa = PBXBuildFile; fileRef = C507E8A614C6545B005D6B3B /* InspectorBar.mm */; };
- 95646E5B1F1DB60E00DE0EB9 /* InspectorValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 953F47911F1DB40300E3D1E3 /* InspectorValue.cpp */; };
7CCE7EC41A411A7E00447C4C /* JSWrapperForNodeInWebFrame.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4160116815B2600824238 /* JSWrapperForNodeInWebFrame.mm */; };
7CCE7EC51A411A7E00447C4C /* MemoryCacheDisableWithinResourceLoadDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E1220D9F155B25480013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.mm */; };
7CCE7EC61A411A7E00447C4C /* MemoryCachePruneWithinResourceLoadDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 517E7DFB15110EA600D0B008 /* MemoryCachePruneWithinResourceLoadDelegate.mm */; };
@@ -512,6 +513,7 @@
93F56DA71E5F9174003EDE84 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 7C83E0331D0A5F2700FEBCF3 /* libicucore.dylib */; };
93F56DA91E5F919D003EDE84 /* WKWebViewSnapshot.mm in Sources */ = {isa = PBXBuildFile; fileRef = 93F56DA81E5F9181003EDE84 /* WKWebViewSnapshot.mm */; };
93F7E86F14DC8E5C00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F7E86E14DC8E5B00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp */; };
+ 95646E5B1F1DB60E00DE0EB9 /* InspectorValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 953F47911F1DB40300E3D1E3 /* InspectorValue.cpp */; };
9984FACC1CFFAF60008D198C /* WKWebViewTextInput.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9984FACA1CFFAEEE008D198C /* WKWebViewTextInput.mm */; };
9984FACE1CFFB090008D198C /* editable-body.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9984FACD1CFFB038008D198C /* editable-body.html */; };
9B0786A51C5885C300D159E3 /* InjectedBundleMakeAllShadowRootsOpen_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B0786A41C5885C300D159E3 /* InjectedBundleMakeAllShadowRootsOpen_Bundle.cpp */; };
@@ -743,6 +745,7 @@
dstPath = TestWebKitAPI.resources;
dstSubfolderSpec = 7;
files = (
+ 51C8E1A91F27F49600BF731B /* EmptyGrandfatheredResourceLoadStatistics.plist in Copy Resources */,
F45B63FB1F197F4A009D38B9 /* image-map.html in Copy Resources */,
F407FE391F1D0DFC0017CF25 /* enormous.svg in Copy Resources */,
F4D5E4E81F0C5D38008C1A49 /* dragstart-clear-selection.html in Copy Resources */,
@@ -1210,6 +1213,8 @@
51BCEE4C1C84F52C0042C82E /* IndexedDBMultiProcess-1.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "IndexedDBMultiProcess-1.html"; sourceTree = "<group>"; };
51BCEE4D1C84F52C0042C82E /* IndexedDBMultiProcess-2.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "IndexedDBMultiProcess-2.html"; sourceTree = "<group>"; };
51C683DD1EA134DB00650183 /* WKURLSchemeHandler-1.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "WKURLSchemeHandler-1.mm"; sourceTree = "<group>"; };
+ 51C8E1A41F26AC5400BF731B /* ResourceLoadStatistics.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ResourceLoadStatistics.mm; sourceTree = "<group>"; };
+ 51C8E1A81F27F47300BF731B /* EmptyGrandfatheredResourceLoadStatistics.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = EmptyGrandfatheredResourceLoadStatistics.plist; sourceTree = "<group>"; };
51CB4AD71B3A079C00C1B1C6 /* ModalAlertsSPI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModalAlertsSPI.cpp; sourceTree = "<group>"; };
51CD1C6A1B38CE3600142CA5 /* ModalAlerts.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ModalAlerts.mm; sourceTree = "<group>"; };
51CD1C711B38D48400142CA5 /* modal-alerts-in-new-about-blank-window.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "modal-alerts-in-new-about-blank-window.html"; sourceTree = "<group>"; };
@@ -1398,6 +1403,7 @@
93F56DA81E5F9181003EDE84 /* WKWebViewSnapshot.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewSnapshot.mm; sourceTree = "<group>"; };
93F7E86B14DC8E4D00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutFrames.cpp; sourceTree = "<group>"; };
93F7E86E14DC8E5B00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp; sourceTree = "<group>"; };
+ 953F47911F1DB40300E3D1E3 /* InspectorValue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorValue.cpp; sourceTree = "<group>"; };
9984FACA1CFFAEEE008D198C /* WKWebViewTextInput.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewTextInput.mm; sourceTree = "<group>"; };
9984FACD1CFFB038008D198C /* editable-body.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "editable-body.html"; sourceTree = "<group>"; };
9B0786A21C58830F00D159E3 /* InjectedBundleMakeAllShadowRootsOpen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundleMakeAllShadowRootsOpen.cpp; sourceTree = "<group>"; };
@@ -1540,7 +1546,6 @@
C2CF975916CEC69E0054E99D /* JSContextBackForwardCache2.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = JSContextBackForwardCache2.html; sourceTree = "<group>"; };
C2EB2DD116CAC7AC009B52EE /* WebViewDidCreateJavaScriptContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebViewDidCreateJavaScriptContext.mm; sourceTree = "<group>"; };
C507E8A614C6545B005D6B3B /* InspectorBar.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorBar.mm; sourceTree = "<group>"; };
- 953F47911F1DB40300E3D1E3 /* InspectorValue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorValue.cpp; sourceTree = "<group>"; };
C5101C4E176B8BB900EE9B15 /* findRanges.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = findRanges.html; sourceTree = "<group>"; };
C51AFB98169F49FF009CCF66 /* FindMatches.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FindMatches.mm; sourceTree = "<group>"; };
C540F775152E4DA000A40C8C /* SimplifyMarkup.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SimplifyMarkup.mm; sourceTree = "<group>"; };
@@ -1890,6 +1895,7 @@
A12DDBFC1E836FF100CF6CAE /* RenderedImageWithOptionsPlugIn.mm */,
A12DDC011E8374F500CF6CAE /* RenderedImageWithOptionsProtocol.h */,
CD9E292B1C90A71F000BB800 /* RequiresUserActionForPlayback.mm */,
+ 51C8E1A41F26AC5400BF731B /* ResourceLoadStatistics.mm */,
A180C0F91EE67DF000468F47 /* RunOpenPanel.mm */,
37BCA61B1B596BA9002012CA /* ShouldOpenExternalURLsInNewWindowActions.mm */,
2D9A53AE1B31FA8D0074D5AA /* ShrinkToFit.mm */,
@@ -2086,6 +2092,7 @@
5714ECBC1CA8C21800051AC8 /* DownloadRequestOriginalURL2.html */,
5714ECBA1CA8BFD100051AC8 /* DownloadRequestOriginalURLFrame.html */,
A155022B1E050BC500A24C57 /* duplicate-completion-handler-calls.html */,
+ 51C8E1A81F27F47300BF731B /* EmptyGrandfatheredResourceLoadStatistics.plist */,
9984FACD1CFFB038008D198C /* editable-body.html */,
F407FE381F1D0DE60017CF25 /* enormous.svg */,
F4C2AB211DD6D94100E06D5B /* enormous-video-with-sound.html */,
@@ -3067,6 +3074,7 @@
7C83E0BB1D0A650000FEBCF3 /* FindInPage.mm in Sources */,
7CCE7EF41A411AE600447C4C /* FindMatches.mm in Sources */,
7C83E0401D0A63E300FEBCF3 /* FirstResponderScrollingPosition.mm in Sources */,
+ 51C8E1A51F26AF4C00BF731B /* ResourceLoadStatistics.mm in Sources */,
7C83E0BC1D0A650700FEBCF3 /* FixedLayoutSize.mm in Sources */,
7A909A7E1D877480007E10F8 /* FloatPoint.cpp in Sources */,
7A909A7F1D877480007E10F8 /* FloatRect.cpp in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/EmptyGrandfatheredResourceLoadStatistics.plist (0 => 219904)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/EmptyGrandfatheredResourceLoadStatistics.plist (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/EmptyGrandfatheredResourceLoadStatistics.plist 2017-07-26 05:44:05 UTC (rev 219904)
@@ -0,0 +1 @@
+bplist00\xD4^operatingDates_browsingStatistics_endOfGrandfatheringTimestampWversion\xA0\xA0#A\xD6]\xE5ھ\xF2\xD8 5T\]^g i
\ No newline at end of file
Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ResourceLoadStatistics.mm (0 => 219904)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ResourceLoadStatistics.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ResourceLoadStatistics.mm 2017-07-26 05:44:05 UTC (rev 219904)
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#import "PlatformUtilities.h"
+#import <WebKit/WKFoundation.h>
+#import <WebKit/WKWebsiteDataRecordPrivate.h>
+#import <WebKit/WKWebsiteDataStorePrivate.h>
+#import <wtf/RetainPtr.h>
+
+#if WK_API_ENABLED
+
+TEST(ResourceLoadStatistics, GrandfatherCallback)
+{
+ auto *dataStore = [WKWebsiteDataStore defaultDataStore];
+ [dataStore _setResourceLoadStatisticsEnabled:NO];
+
+ NSURL *statisticsDirectoryURL = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/ResourceLoadStatistics" stringByExpandingTildeInPath] isDirectory:YES];
+ NSURL *fileURL = [statisticsDirectoryURL URLByAppendingPathComponent:@"full_browsing_session_resourceLog.plist"];
+ [[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
+ [[NSFileManager defaultManager] removeItemAtURL:statisticsDirectoryURL error:nil];
+ EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:statisticsDirectoryURL.path]);
+
+ static bool doneFlag;
+ static bool grandfatheredFlag;
+
+ [dataStore _setResourceLoadStatisticsTestingCallback:^(WKWebsiteDataStore *, NSString *message) {
+ ASSERT_TRUE([message isEqualToString:@"Grandfathered"]);
+ grandfatheredFlag = true;
+ }];
+
+ TestWebKitAPI::Util::run(&grandfatheredFlag);
+
+ // Spin the runloop until the resource load statistics file has written to disk.
+ // If the test enters a spin loop here, it has failed.
+ while (true) {
+ if ([[NSFileManager defaultManager] fileExistsAtPath:fileURL.path])
+ break;
+ TestWebKitAPI::Util::spinRunLoop(1);
+ }
+
+ grandfatheredFlag = false;
+ [dataStore removeDataOfTypes:[WKWebsiteDataStore _allWebsiteDataTypesIncludingPrivate] modifiedSince:[NSDate distantPast] completionHandler:^ {
+ doneFlag = true;
+ }];
+
+ TestWebKitAPI::Util::run(&doneFlag);
+ TestWebKitAPI::Util::spinRunLoop(10);
+
+ // The website data store remove should have completed, but since we removed all of the data types that are monitored by resource load statistics,
+ // no grandfathering call should have been made.
+ EXPECT_FALSE(grandfatheredFlag);
+ EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:fileURL.path]);
+
+ doneFlag = false;
+ [dataStore removeDataOfTypes:[NSSet setWithObjects:WKWebsiteDataTypeCookies, _WKWebsiteDataTypeResourceLoadStatistics, nil] modifiedSince:[NSDate distantPast] completionHandler:^ {
+ doneFlag = true;
+ }];
+
+ // Since we did not remove every data type covered by resource load statistics, we do expect that grandfathering took place again.
+ // If the test hangs waiting on either of these conditions, it has failed.
+ TestWebKitAPI::Util::run(&grandfatheredFlag);
+ TestWebKitAPI::Util::run(&doneFlag);
+
+ // Spin the runloop until the resource load statistics file has written to disk.
+ // If the test enters a spin loop here, it has failed.
+ while (true) {
+ if ([[NSFileManager defaultManager] fileExistsAtPath:fileURL.path])
+ break;
+ TestWebKitAPI::Util::spinRunLoop(1);
+ }
+}
+
+TEST(ResourceLoadStatistics, ShouldNotGrandfatherOnStartup)
+{
+ auto *dataStore = [WKWebsiteDataStore defaultDataStore];
+ [dataStore _setResourceLoadStatisticsEnabled:NO];
+
+ NSURL *statisticsDirectoryURL = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/ResourceLoadStatistics" stringByExpandingTildeInPath] isDirectory:YES];
+ NSURL *targetURL = [statisticsDirectoryURL URLByAppendingPathComponent:@"full_browsing_session_resourceLog.plist"];
+ NSURL *testResourceURL = [[NSBundle mainBundle] URLForResource:@"EmptyGrandfatheredResourceLoadStatistics" withExtension:@"plist" subdirectory:@"TestWebKitAPI.resources"];
+
+ [[NSFileManager defaultManager] createDirectoryAtURL:statisticsDirectoryURL withIntermediateDirectories:YES attributes:nil error:nil];
+ [[NSFileManager defaultManager] copyItemAtURL:testResourceURL toURL:targetURL error:nil];
+
+ EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:targetURL.path]);
+
+ static bool callbackFlag;
+ [dataStore _setResourceLoadStatisticsTestingCallback:^(WKWebsiteDataStore *, NSString *message) {
+ ASSERT_TRUE([message isEqualToString:@"PopulatedWithoutGrandfathering"]);
+ callbackFlag = true;
+ }];
+
+ TestWebKitAPI::Util::run(&callbackFlag);
+}
+#endif
+