ResourceLoadStatisticsMemoryStore.h [plain text]
#pragma once
#include "ResourceLoadStatisticsClassifier.h"
#include "WebResourceLoadStatisticsStore.h"
#include <wtf/CompletionHandler.h>
#include <wtf/Vector.h>
#include <wtf/WeakPtr.h>
#include <wtf/WorkQueue.h>
#if HAVE(CORE_PREDICTION)
#include "ResourceLoadStatisticsClassifierCocoa.h"
#endif
namespace WebCore {
class KeyedDecoder;
class KeyedEncoder;
struct ResourceLoadStatistics;
}
namespace WebKit {
class OperatingDate;
class ResourceLoadStatisticsPersistentStorage;
class ResourceLoadStatisticsMemoryStore : public CanMakeWeakPtr<ResourceLoadStatisticsMemoryStore> {
public:
ResourceLoadStatisticsMemoryStore(WebResourceLoadStatisticsStore&, WorkQueue&);
~ResourceLoadStatisticsMemoryStore();
void setPersistentStorage(ResourceLoadStatisticsPersistentStorage&);
void clear();
bool isEmpty() const { return m_resourceStatisticsMap.isEmpty(); }
std::unique_ptr<WebCore::KeyedEncoder> createEncoderFromData() const;
void mergeWithDataFromDecoder(WebCore::KeyedDecoder&);
void mergeStatistics(Vector<WebCore::ResourceLoadStatistics>&&);
void processStatistics(const Function<void(const WebCore::ResourceLoadStatistics&)>&) const;
void resetCookiePartitioningState();
void updateCookiePartitioning(CompletionHandler<void()>&&);
void updateCookiePartitioningForDomains(const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, ShouldClearFirst, CompletionHandler<void()>&&);
void clearPartitioningStateForDomains(const Vector<String>& domains, CompletionHandler<void()>&&);
void includeTodayAsOperatingDateIfNecessary();
void processStatisticsAndDataRecords();
void requestStorageAccessUnderOpener(String&& primaryDomainInNeedOfStorageAccess, uint64_t openerPageID, String&& openerPrimaryDomain, bool isTriggeredByUserGesture);
void removeAllStorageAccess();
void grandfatherExistingWebsiteData(CompletionHandler<void()>&&);
void cancelPendingStatisticsProcessingRequest();
bool isRegisteredAsSubFrameUnder(const String& subFramePrimaryDomain, const String& topFramePrimaryDomain) const;
bool isRegisteredAsRedirectingTo(const String& hostRedirectedFromPrimaryDomain, const String& hostRedirectedToPrimaryDomain) const;
void clearPrevalentResource(const String& primaryDomain);
bool isPrevalentResource(const String& primaryDomain) const;
bool isVeryPrevalentResource(const String& primaryDomain) const;
void setPrevalentResource(const String& primaryDomain);
void setVeryPrevalentResource(const String& primaryDomain);
void setGrandfathered(const String& primaryDomain, bool value);
bool isGrandfathered(const String& primaryDomain) const;
void setSubframeUnderTopFrameOrigin(const String& primarySubFrameDomain, const String& primaryTopFrameDomain);
void setSubresourceUnderTopFrameOrigin(const String& primarySubresourceDomain, const String& primaryTopFrameDomain);
void setSubresourceUniqueRedirectTo(const String& primarySubresourceDomain, const String& primaryRedirectDomain);
void setSubresourceUniqueRedirectFrom(const String& primarySubresourceDomain, const String& primaryRedirectDomain);
void setTopFrameUniqueRedirectTo(const String& topFramePrimaryDomain, const String& primaryRedirectDomain);
void setTopFrameUniqueRedirectFrom(const String& topFramePrimaryDomain, const String& primaryRedirectDomain);
void logTestingEvent(const String&);
void setMaxStatisticsEntries(size_t maximumEntryCount);
void setPruneEntriesDownTo(size_t pruneTargetCount);
void resetParametersToDefaultValues();
void calculateAndSubmitTelemetry() const;
void setNotifyPagesWhenDataRecordsWereScanned(bool);
void setShouldClassifyResourcesBeforeDataRecordsRemoval(bool);
void setShouldSubmitTelemetry(bool);
void setTimeToLiveUserInteraction(Seconds);
void setTimeToLiveCookiePartitionFree(Seconds);
void setMinimumTimeBetweenDataRecordsRemoval(Seconds);
void setGrandfatheringTime(Seconds);
void setResourceLoadStatisticsDebugMode(bool);
void hasStorageAccess(const String& subFramePrimaryDomain, const String& topFramePrimaryDomain, uint64_t frameID, uint64_t pageID, CompletionHandler<void(bool)>&&);
void requestStorageAccess(String&& subFramePrimaryDomain, String&& topFramePrimaryDomain, uint64_t frameID, uint64_t pageID, bool promptEnabled, CompletionHandler<void(StorageAccessStatus)>&&);
void grantStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, bool userWasPromptedNow, CompletionHandler<void(bool)>&&);
void logNonRecentUserInteraction(const String& primaryDomain);
void logFrameNavigation(const String& targetPrimaryDomain, const String& mainFramePrimaryDomain, const String& sourcePrimaryDomain, const String& targetHost, const String& mainFrameHost, bool areTargetAndMainFrameDomainsAssociated, bool areTargetAndSourceDomainsAssociated, bool isRedirect, bool isMainFrame);
void logUserInteraction(const String& primaryDomain);
void clearUserInteraction(const String& primaryDomain);
bool hasHadUserInteraction(const String& primaryDomain);
void setLastSeen(const String& primaryDomain, Seconds);
private:
static bool shouldPartitionCookies(const WebCore::ResourceLoadStatistics&);
static bool shouldBlockCookies(const WebCore::ResourceLoadStatistics&);
static bool hasUserGrantedStorageAccessThroughPrompt(const WebCore::ResourceLoadStatistics&, const String& firstPartyPrimaryDomain);
bool hasHadUnexpiredRecentUserInteraction(WebCore::ResourceLoadStatistics&) const;
bool hasStatisticsExpired(const WebCore::ResourceLoadStatistics&) const;
bool wasAccessedAsFirstPartyDueToUserInteraction(const WebCore::ResourceLoadStatistics& current, const WebCore::ResourceLoadStatistics& updated) const;
void setPrevalentResource(WebCore::ResourceLoadStatistics&, ResourceLoadPrevalence);
unsigned recursivelyGetAllDomainsThatHaveRedirectedToThisDomain(const WebCore::ResourceLoadStatistics&, HashSet<String>& domainsThatHaveRedirectedTo, unsigned numberOfRecursiveCalls) const;
void setStorageAccessPromptsEnabled(bool enabled) { m_storageAccessPromptsEnabled = enabled; }
bool shouldRemoveDataRecords() const;
void setDebugLogggingEnabled(bool enabled) { m_debugLoggingEnabled = enabled; }
void setDataRecordsBeingRemoved(bool);
void scheduleStatisticsProcessingRequestIfNecessary();
void grantStorageAccessInternal(String&& subFrameHost, String&& topFrameHost, std::optional<uint64_t> frameID, uint64_t pageID, bool userWasPromptedNowOrEarlier, CompletionHandler<void(bool)>&&);
void markAsPrevalentIfHasRedirectedToPrevalent(WebCore::ResourceLoadStatistics&);
void removeDataRecords(CompletionHandler<void()>&&);
void pruneStatisticsIfNeeded();
WebCore::ResourceLoadStatistics& ensureResourceStatisticsForPrimaryDomain(const String&);
Vector<String> topPrivatelyControlledDomainsToRemoveWebsiteDataFor();
#if PLATFORM(COCOA)
void registerUserDefaultsIfNeeded();
#endif
struct Parameters {
size_t pruneEntriesDownTo { 800 };
size_t maxStatisticsEntries { 1000 };
std::optional<Seconds> timeToLiveUserInteraction;
Seconds timeToLiveCookiePartitionFree { 24_h };
Seconds minimumTimeBetweenDataRecordsRemoval { 1_h };
Seconds grandfatheringTime { 24_h * 7 };
bool shouldNotifyPagesWhenDataRecordsWereScanned { false };
bool shouldClassifyResourcesBeforeDataRecordsRemoval { true };
bool shouldSubmitTelemetry { true };
};
WebResourceLoadStatisticsStore& m_store;
Ref<WorkQueue> m_workQueue;
WeakPtr<ResourceLoadStatisticsPersistentStorage> m_persistentStorage;
HashMap<String, WebCore::ResourceLoadStatistics> m_resourceStatisticsMap;
#if HAVE(CORE_PREDICTION)
ResourceLoadStatisticsClassifierCocoa m_resourceLoadStatisticsClassifier;
#else
ResourceLoadStatisticsClassifier m_resourceLoadStatisticsClassifier;
#endif
#if ENABLE(NETSCAPE_PLUGIN_API)
HashSet<uint64_t> m_activePluginTokens;
#endif
Parameters m_parameters;
Vector<OperatingDate> m_operatingDates;
WallTime m_endOfGrandfatheringTimestamp;
bool m_debugLoggingEnabled { false };
bool m_debugModeEnabled { false };
bool m_storageAccessPromptsEnabled { false };
bool m_dataRecordsBeingRemoved { false };
MonotonicTime m_lastTimeDataRecordsWereRemoved;
uint64_t m_lastStatisticsProcessingRequestIdentifier { 0 };
std::optional<uint64_t> m_pendingStatisticsProcessingRequestIdentifier;
};
}