Unreviewed, rolling out r239727.
[WebKit-https.git] / Source / WebCore / loader / ResourceLoadStatistics.cpp
index 9e2b7cf..c5ad746 100644 (file)
@@ -29,6 +29,7 @@
 #include "KeyedCoding.h"
 #include "PublicSuffix.h"
 #include <wtf/MainThread.h>
+#include <wtf/text/ASCIILiteral.h>
 #include <wtf/text/StringBuilder.h>
 #include <wtf/text/StringHash.h>
 
@@ -49,13 +50,43 @@ static void encodeHashCountedSet(KeyedEncoder& encoder, const String& label, con
     });
 }
 
-static void encodeHashSet(KeyedEncoder& encoder, const String& label, const HashSet<String>& hashSet)
+static void encodeHashSet(KeyedEncoder& encoder, const String& label,  const String& key, const HashSet<String>& hashSet)
 {
     if (hashSet.isEmpty())
         return;
     
-    encoder.encodeObjects(label, hashSet.begin(), hashSet.end(), [](KeyedEncoder& encoderInner, const String& origin) {
-        encoderInner.encodeString("origin", origin);
+    encoder.encodeObjects(label, hashSet.begin(), hashSet.end(), [&key](KeyedEncoder& encoderInner, const String& origin) {
+        encoderInner.encodeString(key, origin);
+    });
+}
+
+static void encodeOriginHashSet(KeyedEncoder& encoder, const String& label, const HashSet<String>& hashSet)
+{
+    encodeHashSet(encoder, label, "origin", hashSet);
+}
+
+template<typename T>
+static void encodeOptionSet(KeyedEncoder& encoder, const String& label, const OptionSet<T>& optionSet)
+{
+    if (optionSet.isEmpty())
+        return;
+    
+    uint64_t optionSetBitMask = optionSet.toRaw();
+    encoder.encodeUInt64(label, optionSetBitMask);
+}
+    
+static void encodeFontHashSet(KeyedEncoder& encoder, const String& label, const HashSet<String>& hashSet)
+{
+    encodeHashSet(encoder, label, "font", hashSet);
+}
+    
+static void encodeCanvasActivityRecord(KeyedEncoder& encoder, const String& label, const CanvasActivityRecord& canvasActivityRecord)
+{
+    encoder.encodeObject(label, canvasActivityRecord, [] (KeyedEncoder& encoderInner, const CanvasActivityRecord& canvasActivityRecord) {
+        encoderInner.encodeBool("wasDataRead", canvasActivityRecord.wasDataRead);
+        encoderInner.encodeObjects("textWritten", canvasActivityRecord.textWritten.begin(), canvasActivityRecord.textWritten.end(), [] (KeyedEncoder& encoderInner2, const String& text) {
+            encoderInner2.encodeString("text", text);
+        });
     });
 }
 
@@ -71,7 +102,7 @@ void ResourceLoadStatistics::encode(KeyedEncoder& encoder) const
     encoder.encodeBool("grandfathered", grandfathered);
 
     // Storage access
-    encodeHashSet(encoder, "storageAccessUnderTopFrameOrigins", storageAccessUnderTopFrameOrigins);
+    encodeOriginHashSet(encoder, "storageAccessUnderTopFrameOrigins", storageAccessUnderTopFrameOrigins);
 
     // Top frame stats
     encodeHashCountedSet(encoder, "topFrameUniqueRedirectsTo", topFrameUniqueRedirectsTo);
@@ -92,6 +123,13 @@ void ResourceLoadStatistics::encode(KeyedEncoder& encoder) const
 
     encoder.encodeUInt32("timesAccessedAsFirstPartyDueToUserInteraction", timesAccessedAsFirstPartyDueToUserInteraction);
     encoder.encodeUInt32("timesAccessedAsFirstPartyDueToStorageAccessAPI", timesAccessedAsFirstPartyDueToStorageAccessAPI);
+    
+    encodeFontHashSet(encoder, "fontsFailedToLoad", fontsFailedToLoad);
+    encodeFontHashSet(encoder, "fontsSuccessfullyLoaded", fontsSuccessfullyLoaded);
+    encodeHashCountedSet(encoder, "topFrameRegistrableDomainsWhichAccessedWebAPIs", topFrameRegistrableDomainsWhichAccessedWebAPIs);
+    encodeCanvasActivityRecord(encoder, "canvasActivityRecord", canvasActivityRecord);
+    encodeOptionSet(encoder, "navigatorFunctionsAccessedBitMask", navigatorFunctionsAccessed);
+    encodeOptionSet(encoder, "screenFunctionsAccessedBitMask", screenFunctionsAccessed);
 }
 
 static void decodeHashCountedSet(KeyedDecoder& decoder, const String& label, HashCountedSet<String>& hashCountedSet)
@@ -110,11 +148,11 @@ static void decodeHashCountedSet(KeyedDecoder& decoder, const String& label, Has
     });
 }
 
-static void decodeHashSet(KeyedDecoder& decoder, const String& label, HashSet<String>& hashSet)
+static void decodeHashSet(KeyedDecoder& decoder, const String& label, const String& key, HashSet<String>& hashSet)
 {
     Vector<String> ignore;
-    decoder.decodeObjects(label, ignore, [&hashSet](KeyedDecoder& decoderInner, String& origin) {
-        if (!decoderInner.decodeString("origin", origin))
+    decoder.decodeObjects(label, ignore, [&hashSet, &key](KeyedDecoder& decoderInner, String& origin) {
+        if (!decoderInner.decodeString(key, origin))
             return false;
         
         hashSet.add(origin);
@@ -122,6 +160,40 @@ static void decodeHashSet(KeyedDecoder& decoder, const String& label, HashSet<St
     });
 }
 
+static void decodeOriginHashSet(KeyedDecoder& decoder, const String& label, HashSet<String>& hashSet)
+{
+    decodeHashSet(decoder, label, "origin", hashSet);
+}
+
+template<typename T>
+static void decodeOptionSet(KeyedDecoder& decoder, const String& label, OptionSet<T>& optionSet)
+{
+    uint64_t optionSetBitMask = 0;
+    decoder.decodeUInt64(label, optionSetBitMask);
+    optionSet = OptionSet<T>::fromRaw(optionSetBitMask);
+}
+    
+static void decodeFontHashSet(KeyedDecoder& decoder, const String& label, HashSet<String>& hashSet)
+{
+    decodeHashSet(decoder, label, "font", hashSet);
+}
+    
+static void decodeCanvasActivityRecord(KeyedDecoder& decoder, const String& label, CanvasActivityRecord& canvasActivityRecord)
+{
+    decoder.decodeObject(label, canvasActivityRecord, [] (KeyedDecoder& decoderInner, CanvasActivityRecord& canvasActivityRecord) {
+        if (!decoderInner.decodeBool("wasDataRead", canvasActivityRecord.wasDataRead))
+            return false;
+        Vector<String> ignore;
+        decoderInner.decodeObjects("textWritten", ignore, [&canvasActivityRecord] (KeyedDecoder& decoderInner2, String& text) {
+            if (!decoderInner2.decodeString("text", text))
+                return false;
+            canvasActivityRecord.textWritten.add(text);
+            return true;
+        });
+        return true;
+    });
+}
+
 bool ResourceLoadStatistics::decode(KeyedDecoder& decoder, unsigned modelVersion)
 {
     if (!decoder.decodeString("PrevalentResourceOrigin", highLevelDomain))
@@ -132,7 +204,7 @@ bool ResourceLoadStatistics::decode(KeyedDecoder& decoder, unsigned modelVersion
         return false;
 
     // Storage access
-    decodeHashSet(decoder, "storageAccessUnderTopFrameOrigins", storageAccessUnderTopFrameOrigins);
+    decodeOriginHashSet(decoder, "storageAccessUnderTopFrameOrigins", storageAccessUnderTopFrameOrigins);
 
     // Top frame stats
     if (modelVersion >= 11) {
@@ -141,8 +213,9 @@ bool ResourceLoadStatistics::decode(KeyedDecoder& decoder, unsigned modelVersion
     }
 
     // Subframe stats
-    decodeHashCountedSet(decoder, "subframeUnderTopFrameOrigins", subframeUnderTopFrameOrigins);
-    
+    if (modelVersion >= 14)
+        decodeHashCountedSet(decoder, "subframeUnderTopFrameOrigins", subframeUnderTopFrameOrigins);
+
     // Subresource stats
     decodeHashCountedSet(decoder, "subresourceUnderTopFrameOrigins", subresourceUnderTopFrameOrigins);
     decodeHashCountedSet(decoder, "subresourceUniqueRedirectsTo", subresourceUniqueRedirectsTo);
@@ -158,6 +231,12 @@ bool ResourceLoadStatistics::decode(KeyedDecoder& decoder, unsigned modelVersion
             return false;
     }
 
+    // Trigger re-classification based on model 14.
+    if (modelVersion < 14) {
+        isPrevalentResource = false;
+        isVeryPrevalentResource = false;
+    }
+
     if (!decoder.decodeUInt32("dataRecordsRemoved", dataRecordsRemoved))
         return false;
 
@@ -180,6 +259,16 @@ bool ResourceLoadStatistics::decode(KeyedDecoder& decoder, unsigned modelVersion
         if (!decoder.decodeUInt32("timesAccessedAsFirstPartyDueToStorageAccessAPI", timesAccessedAsFirstPartyDueToStorageAccessAPI))
             timesAccessedAsFirstPartyDueToStorageAccessAPI = 0;
     }
+    
+    if (modelVersion >= 13) {
+        decodeFontHashSet(decoder, "fontsFailedToLoad", fontsFailedToLoad);
+        decodeFontHashSet(decoder, "fontsSuccessfullyLoaded", fontsSuccessfullyLoaded);
+        decodeHashCountedSet(decoder, "topFrameRegistrableDomainsWhichAccessedWebAPIs", topFrameRegistrableDomainsWhichAccessedWebAPIs);
+        decodeCanvasActivityRecord(decoder, "canvasActivityRecord", canvasActivityRecord);
+        decodeOptionSet(decoder, "navigatorFunctionsAccessedBitMask", navigatorFunctionsAccessed);
+        decodeOptionSet(decoder, "screenFunctionsAccessedBitMask", screenFunctionsAccessed);
+    }
+    
     return true;
 }
 
@@ -225,11 +314,81 @@ static void appendHashSet(StringBuilder& builder, const String& label, const Has
     }
 }
 
+static ASCIILiteral navigatorAPIEnumToString(ResourceLoadStatistics::NavigatorAPI navigatorEnum)
+{
+    switch (navigatorEnum) {
+    case ResourceLoadStatistics::NavigatorAPI::JavaEnabled:
+        return "javaEnabled"_s;
+    case ResourceLoadStatistics::NavigatorAPI::MimeTypes:
+        return "mimeTypes"_s;
+    case ResourceLoadStatistics::NavigatorAPI::CookieEnabled:
+        return "cookieEnabled"_s;
+    case ResourceLoadStatistics::NavigatorAPI::Plugins:
+        return "plugins"_s;
+    case ResourceLoadStatistics::NavigatorAPI::UserAgent:
+        return "userAgent"_s;
+    case ResourceLoadStatistics::NavigatorAPI::AppVersion:
+        return "appVersion"_s;
+    }
+    ASSERT_NOT_REACHED();
+    return "Invalid navigator API"_s;
+}
+
+static ASCIILiteral screenAPIEnumToString(ResourceLoadStatistics::ScreenAPI screenEnum)
+{
+    switch (screenEnum) {
+    case ResourceLoadStatistics::ScreenAPI::Height:
+        return "height"_s;
+    case ResourceLoadStatistics::ScreenAPI::Width:
+        return "width"_s;
+    case ResourceLoadStatistics::ScreenAPI::ColorDepth:
+        return "colorDepth"_s;
+    case ResourceLoadStatistics::ScreenAPI::PixelDepth:
+        return "pixelDepth"_s;
+    case ResourceLoadStatistics::ScreenAPI::AvailLeft:
+        return "availLeft"_s;
+    case ResourceLoadStatistics::ScreenAPI::AvailTop:
+        return "availTop"_s;
+    case ResourceLoadStatistics::ScreenAPI::AvailHeight:
+        return "availHeight"_s;
+    case ResourceLoadStatistics::ScreenAPI::AvailWidth:
+        return "availWidth"_s;
+    }
+    ASSERT_NOT_REACHED();
+    return "Invalid screen API"_s;
+}
+    
+static void appendNavigatorAPIOptionSet(StringBuilder& builder, const OptionSet<ResourceLoadStatistics::NavigatorAPI>& optionSet)
+{
+    if (optionSet.isEmpty())
+        return;
+    builder.appendLiteral("    navigatorFunctionsAccessed:\n");
+    for (auto navigatorAPI : optionSet) {
+        builder.appendLiteral("        ");
+        builder.append(navigatorAPIEnumToString(navigatorAPI).characters());
+        builder.append('\n');
+    }
+}
+    
+static void appendScreenAPIOptionSet(StringBuilder& builder, const OptionSet<ResourceLoadStatistics::ScreenAPI>& optionSet)
+{
+    if (optionSet.isEmpty())
+        return;
+    builder.appendLiteral("    screenFunctionsAccessed:\n");
+    for (auto screenAPI : optionSet) {
+        builder.appendLiteral("        ");
+        builder.append(screenAPIEnumToString(screenAPI).characters());
+        builder.append('\n');
+    }
+}
+
 String ResourceLoadStatistics::toString() const
 {
     StringBuilder builder;
-    
-    builder.appendLiteral("lastSeen");
+    builder.appendLiteral("High level domain: ");
+    builder.append(highLevelDomain);
+    builder.append('\n');
+    builder.appendLiteral("    lastSeen: ");
     builder.appendNumber(lastSeen.secondsSinceEpoch().value());
     builder.append('\n');
     
@@ -239,7 +398,7 @@ String ResourceLoadStatistics::toString() const
     builder.appendLiteral("    mostRecentUserInteraction: ");
     builder.appendNumber(mostRecentUserInteractionTime.secondsSinceEpoch().value());
     builder.append('\n');
-    appendBoolean(builder, "    grandfathered", grandfathered);
+    appendBoolean(builder, "grandfathered", grandfathered);
     builder.append('\n');
 
     // Storage access
@@ -259,15 +418,21 @@ String ResourceLoadStatistics::toString() const
 
     // Prevalent Resource
     appendBoolean(builder, "isPrevalentResource", isPrevalentResource);
-    appendBoolean(builder, "    isVeryPrevalentResource", isVeryPrevalentResource);
+    builder.append('\n');
+    appendBoolean(builder, "isVeryPrevalentResource", isVeryPrevalentResource);
+    builder.append('\n');
     builder.appendLiteral("    dataRecordsRemoved: ");
     builder.appendNumber(dataRecordsRemoved);
     builder.append('\n');
 
-    // In-memory only
-    appendBoolean(builder, "isMarkedForCookieBlocking", isMarkedForCookieBlocking);
+    appendHashSet(builder, "fontsFailedToLoad", fontsFailedToLoad);
+    appendHashSet(builder, "fontsSuccessfullyLoaded", fontsSuccessfullyLoaded);
+    appendHashCountedSet(builder, "topFrameRegistrableDomainsWhichAccessedWebAPIs", topFrameRegistrableDomainsWhichAccessedWebAPIs);
+    appendNavigatorAPIOptionSet(builder, navigatorFunctionsAccessed);
+    appendScreenAPIOptionSet(builder, screenFunctionsAccessed);
+    appendHashSet(builder, "canvasTextWritten", canvasActivityRecord.textWritten);
+    appendBoolean(builder, "canvasReadData", canvasActivityRecord.wasDataRead);
     builder.append('\n');
-
     builder.append('\n');
 
     return builder.toString();
@@ -328,8 +493,12 @@ void ResourceLoadStatistics::merge(const ResourceLoadStatistics& other)
     isVeryPrevalentResource |= other.isVeryPrevalentResource;
     dataRecordsRemoved = std::max(dataRecordsRemoved, other.dataRecordsRemoved);
     
-    // In-memory only
-    isMarkedForCookieBlocking |= other.isMarkedForCookieBlocking;
+    mergeHashSet(fontsFailedToLoad, other.fontsFailedToLoad);
+    mergeHashSet(fontsSuccessfullyLoaded, other.fontsSuccessfullyLoaded);
+    mergeHashCountedSet(topFrameRegistrableDomainsWhichAccessedWebAPIs, other.topFrameRegistrableDomainsWhichAccessedWebAPIs);
+    canvasActivityRecord.mergeWith(other.canvasActivityRecord);
+    navigatorFunctionsAccessed.add(other.navigatorFunctionsAccessed);
+    screenFunctionsAccessed.add(other.screenFunctionsAccessed);
 }
 
 String ResourceLoadStatistics::primaryDomain(const URL& url)