Title: [273897] trunk
Revision
273897
Author
commit-qu...@webkit.org
Date
2021-03-04 10:00:49 -0800 (Thu, 04 Mar 2021)

Log Message

Introduce "websocket", "fetch", and "other" resource types to WKContentRuleList
https://bugs.webkit.org/show_bug.cgi?id=222709
<rdar://problem/71552078>

Patch by Alex Christensen <achristen...@webkit.org> on 2021-03-04
Reviewed by Youenn Fablet.

Source/WebCore:

"raw" didn't give the desired granularity.  This keeps support for "raw", but splits it into 3 subcategories:
"websocket" which only applies to WebSocket requests,
"fetch" which applies to XMLHTTPRequest and fetch API requests.
"other" which applies to other "raw" requests, such as beacons.

Covered by API tests.

* Modules/websockets/ThreadableWebSocketChannel.cpp:
(WebCore::ThreadableWebSocketChannel::validateURL):
* contentextensions/ContentExtensionParser.cpp:
(WebCore::ContentExtensions::getTypeFlags):
* css/StyleSheetContents.cpp:
(WebCore::StyleSheetContents::subresourcesAllowReuse const):
* loader/NetscapePlugInStreamLoader.cpp:
(WebCore::NetscapePlugInStreamLoader::NetscapePlugInStreamLoader):
* loader/ResourceLoadInfo.cpp:
(WebCore::ContentExtensions::toResourceType):
(WebCore::ContentExtensions::readResourceType):
(WebCore::ContentExtensions::readLoadType):
(WebCore::ContentExtensions::ResourceLoadInfo::getResourceFlags const):
* loader/ResourceLoadInfo.h:
* loader/ResourceLoader.cpp:
(WebCore::ResourceLoader::willSendRequestInternal):
* loader/ResourceLoader.h:
* loader/SubresourceLoader.cpp:
(WebCore::SubresourceLoader::SubresourceLoader):
* loader/cache/CachedResourceLoader.cpp:
(WebCore::CachedResourceLoader::requestResource):

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm:
(TEST):
(webSocketAcceptValue):
* TestWebKitAPI/cocoa/HTTPServer.mm:
(TestWebKitAPI::statusText):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (273896 => 273897)


--- trunk/Source/WebCore/ChangeLog	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Source/WebCore/ChangeLog	2021-03-04 18:00:49 UTC (rev 273897)
@@ -1,3 +1,40 @@
+2021-03-04  Alex Christensen  <achristen...@webkit.org>
+
+        Introduce "websocket", "fetch", and "other" resource types to WKContentRuleList
+        https://bugs.webkit.org/show_bug.cgi?id=222709
+        <rdar://problem/71552078>
+
+        Reviewed by Youenn Fablet.
+
+        "raw" didn't give the desired granularity.  This keeps support for "raw", but splits it into 3 subcategories:
+        "websocket" which only applies to WebSocket requests,
+        "fetch" which applies to XMLHTTPRequest and fetch API requests.
+        "other" which applies to other "raw" requests, such as beacons.
+
+        Covered by API tests.
+
+        * Modules/websockets/ThreadableWebSocketChannel.cpp:
+        (WebCore::ThreadableWebSocketChannel::validateURL):
+        * contentextensions/ContentExtensionParser.cpp:
+        (WebCore::ContentExtensions::getTypeFlags):
+        * css/StyleSheetContents.cpp:
+        (WebCore::StyleSheetContents::subresourcesAllowReuse const):
+        * loader/NetscapePlugInStreamLoader.cpp:
+        (WebCore::NetscapePlugInStreamLoader::NetscapePlugInStreamLoader):
+        * loader/ResourceLoadInfo.cpp:
+        (WebCore::ContentExtensions::toResourceType):
+        (WebCore::ContentExtensions::readResourceType):
+        (WebCore::ContentExtensions::readLoadType):
+        (WebCore::ContentExtensions::ResourceLoadInfo::getResourceFlags const):
+        * loader/ResourceLoadInfo.h:
+        * loader/ResourceLoader.cpp:
+        (WebCore::ResourceLoader::willSendRequestInternal):
+        * loader/ResourceLoader.h:
+        * loader/SubresourceLoader.cpp:
+        (WebCore::SubresourceLoader::SubresourceLoader):
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::CachedResourceLoader::requestResource):
+
 2021-03-04  Antoine Quint  <grao...@webkit.org>
 
         Adjust progress parameter before calling blend() for discrete interpolations

Modified: trunk/Source/WebCore/Modules/websockets/ThreadableWebSocketChannel.cpp (273896 => 273897)


--- trunk/Source/WebCore/Modules/websockets/ThreadableWebSocketChannel.cpp	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Source/WebCore/Modules/websockets/ThreadableWebSocketChannel.cpp	2021-03-04 18:00:49 UTC (rev 273897)
@@ -93,7 +93,7 @@
             return { };
 #if ENABLE(CONTENT_EXTENSIONS)
         if (auto* documentLoader = document.loader()) {
-            auto results = page->userContentProvider().processContentRuleListsForLoad(*page, validatedURL.url, ContentExtensions::ResourceType::Raw, *documentLoader);
+            auto results = page->userContentProvider().processContentRuleListsForLoad(*page, validatedURL.url, { ContentExtensions::ResourceType::Raw, ContentExtensions::ResourceType::WebSocket }, *documentLoader);
             if (results.summary.blockedLoad)
                 return { };
             if (results.summary.madeHTTPS) {

Modified: trunk/Source/WebCore/contentextensions/ContentExtensionParser.cpp (273896 => 273897)


--- trunk/Source/WebCore/contentextensions/ContentExtensionParser.cpp	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionParser.cpp	2021-03-04 18:00:49 UTC (rev 273897)
@@ -94,7 +94,8 @@
     return strings;
 }
 
-static std::error_code getTypeFlags(JSGlobalObject& lexicalGlobalObject, const JSValue& typeValue, ResourceFlags& flags, uint16_t (*stringToType)(const String&))
+template<typename T>
+static std::error_code getTypeFlags(JSGlobalObject& lexicalGlobalObject, const JSValue& typeValue, ResourceFlags& flags, Optional<OptionSet<T>> (*stringToType)(const String&))
 {
     VM& vm = lexicalGlobalObject.vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
@@ -116,11 +117,11 @@
             return ContentExtensionError::JSONInvalidObjectInTriggerFlagsArray;
         
         String name = value.toWTFString(&lexicalGlobalObject);
-        uint16_t type = stringToType(name);
+        auto type = stringToType(name);
         if (!type)
             return ContentExtensionError::JSONInvalidStringInTriggerFlagsArray;
 
-        flags |= type;
+        flags |= static_cast<ResourceFlags>(type->toRaw());
     }
 
     return { };

Modified: trunk/Source/WebCore/css/StyleSheetContents.cpp (273896 => 273897)


--- trunk/Source/WebCore/css/StyleSheetContents.cpp	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Source/WebCore/css/StyleSheetContents.cpp	2021-03-04 18:00:49 UTC (rev 273897)
@@ -508,7 +508,7 @@
         auto* documentLoader = loader.documentLoader();
         if (page && documentLoader) {
             const auto& request = resource.resourceRequest();
-            auto results = page->userContentProvider().processContentRuleListsForLoad(*page, request.url(), ContentExtensions::toResourceType(resource.type()), *documentLoader);
+            auto results = page->userContentProvider().processContentRuleListsForLoad(*page, request.url(), ContentExtensions::toResourceType(resource.type(), resource.resourceRequest().requester()), *documentLoader);
             if (results.summary.blockedLoad || results.summary.madeHTTPS)
                 return true;
         }

Modified: trunk/Source/WebCore/loader/NetscapePlugInStreamLoader.cpp (273896 => 273897)


--- trunk/Source/WebCore/loader/NetscapePlugInStreamLoader.cpp	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Source/WebCore/loader/NetscapePlugInStreamLoader.cpp	2021-03-04 18:00:49 UTC (rev 273897)
@@ -60,7 +60,7 @@
     , m_client(makeWeakPtr(client))
 {
 #if ENABLE(CONTENT_EXTENSIONS)
-    m_resourceType = ContentExtensions::ResourceType::PlugInStream;
+    m_resourceType = { ContentExtensions::ResourceType::PlugInStream };
 #endif
 }
 

Modified: trunk/Source/WebCore/loader/ResourceLoadInfo.cpp (273896 => 273897)


--- trunk/Source/WebCore/loader/ResourceLoadInfo.cpp	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Source/WebCore/loader/ResourceLoadInfo.cpp	2021-03-04 18:00:49 UTC (rev 273897)
@@ -34,84 +34,94 @@
 namespace WebCore {
 namespace ContentExtensions {
 
-ResourceType toResourceType(CachedResource::Type type)
+OptionSet<ResourceType> toResourceType(CachedResource::Type type, ResourceRequestBase::Requester requester)
 {
     switch (type) {
     case CachedResource::Type::LinkPrefetch:
     case CachedResource::Type::MainResource:
-        return ResourceType::Document;
+        return { ResourceType::Document };
     case CachedResource::Type::SVGDocumentResource:
-        return ResourceType::SVGDocument;
+        return { ResourceType::SVGDocument };
     case CachedResource::Type::ImageResource:
-        return ResourceType::Image;
+        return { ResourceType::Image };
     case CachedResource::Type::CSSStyleSheet:
 #if ENABLE(XSLT)
     case CachedResource::Type::XSLStyleSheet:
 #endif
-        return ResourceType::StyleSheet;
+        return { ResourceType::StyleSheet };
 
     case CachedResource::Type::Script:
-        return ResourceType::Script;
+        return { ResourceType::Script };
 
     case CachedResource::Type::FontResource:
     case CachedResource::Type::SVGFontResource:
-        return ResourceType::Font;
+        return { ResourceType::Font };
 
     case CachedResource::Type::MediaResource:
-        return ResourceType::Media;
+        return { ResourceType::Media };
 
+    case CachedResource::Type::RawResource:
+        if (requester == ResourceRequestBase::Requester::XHR
+            || requester == ResourceRequestBase::Requester::Fetch)
+            return {{ ResourceType::Raw, ResourceType::Fetch }};
+        FALLTHROUGH;
     case CachedResource::Type::Beacon:
     case CachedResource::Type::Ping:
     case CachedResource::Type::Icon:
-    case CachedResource::Type::RawResource:
 #if ENABLE(MODEL_ELEMENT)
     case CachedResource::Type::ModelResource:
 #endif
-        return ResourceType::Raw;
+#if ENABLE(APPLICATION_MANIFEST)
+    case CachedResource::Type::ApplicationManifest:
+#endif
+        return {{ ResourceType::Raw, ResourceType::Other }};
 
     case CachedResource::Type::TextTrackResource:
-        return ResourceType::Media;
+        return { ResourceType::Media };
 
-#if ENABLE(APPLICATION_MANIFEST)
-    case CachedResource::Type::ApplicationManifest:
-        return ResourceType::Raw;
-#endif
     };
-    return ResourceType::Raw;
+    ASSERT_NOT_REACHED();
+    return { };
 }
 
-uint16_t readResourceType(const String& name)
+Optional<OptionSet<ResourceType>> readResourceType(const String& name)
 {
     if (name == "document")
-        return static_cast<uint16_t>(ResourceType::Document);
+        return { ResourceType::Document };
     if (name == "image")
-        return static_cast<uint16_t>(ResourceType::Image);
+        return { ResourceType::Image };
     if (name == "style-sheet")
-        return static_cast<uint16_t>(ResourceType::StyleSheet);
+        return { ResourceType::StyleSheet };
     if (name == "script")
-        return static_cast<uint16_t>(ResourceType::Script);
+        return { ResourceType::Script };
     if (name == "font")
-        return static_cast<uint16_t>(ResourceType::Font);
+        return { ResourceType::Font };
     if (name == "raw")
-        return static_cast<uint16_t>(ResourceType::Raw);
+        return { ResourceType::Raw };
+    if (name == "websocket")
+        return { ResourceType::WebSocket };
+    if (name == "fetch")
+        return { ResourceType::Fetch };
+    if (name == "other")
+        return { ResourceType::Other };
     if (name == "svg-document")
-        return static_cast<uint16_t>(ResourceType::SVGDocument);
+        return { ResourceType::SVGDocument };
     if (name == "media")
-        return static_cast<uint16_t>(ResourceType::Media);
+        return { ResourceType::Media };
     if (name == "popup")
-        return static_cast<uint16_t>(ResourceType::Popup);
+        return { ResourceType::Popup };
     if (name == "ping")
-        return static_cast<uint16_t>(ResourceType::Ping);
-    return static_cast<uint16_t>(ResourceType::Invalid);
+        return { ResourceType::Ping };
+    return WTF::nullopt;
 }
 
-uint16_t readLoadType(const String& name)
+Optional<OptionSet<LoadType>> readLoadType(const String& name)
 {
     if (name == "first-party")
-        return static_cast<uint16_t>(LoadType::FirstParty);
+        return { LoadType::FirstParty };
     if (name == "third-party")
-        return static_cast<uint16_t>(LoadType::ThirdParty);
-    return static_cast<uint16_t>(LoadType::Invalid);
+        return { LoadType::ThirdParty };
+    return WTF::nullopt;
 }
 
 bool ResourceLoadInfo::isThirdParty() const
@@ -125,7 +135,7 @@
 ResourceFlags ResourceLoadInfo::getResourceFlags() const
 {
     ResourceFlags flags = 0;
-    ASSERT(type != ResourceType::Invalid);
+    ASSERT(!type.isEmpty());
     flags |= type.toRaw();
     flags |= isThirdParty() ? static_cast<ResourceFlags>(LoadType::ThirdParty) : static_cast<ResourceFlags>(LoadType::FirstParty);
     return flags;

Modified: trunk/Source/WebCore/loader/ResourceLoadInfo.h (273896 => 273897)


--- trunk/Source/WebCore/loader/ResourceLoadInfo.h	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Source/WebCore/loader/ResourceLoadInfo.h	2021-03-04 18:00:49 UTC (rev 273897)
@@ -35,13 +35,12 @@
 namespace ContentExtensions {
 
 enum class ResourceType : uint16_t {
-    Invalid = 0x0000,
     Document = 0x0001,
     Image = 0x0002,
     StyleSheet = 0x0004,
     Script = 0x0008,
     Font = 0x0010,
-    Raw = 0x0020,
+    Raw = 0x0020, // This bit can be reused next time we increment CurrentContentRuleListFileVersion. It is equivalent to using Fetch | WebSocket | Other.
     SVGDocument = 0x0040,
     Media = 0x0080,
     PlugInStream = 0x0100,
@@ -48,11 +47,13 @@
     Popup = 0x0200,
     // 0x0400 and 0x0800 are used by LoadType.
     Ping = 0x1000,
+    Fetch = 0x2000,
+    WebSocket = 0x4000,
+    Other = 0x8000,
 };
-const uint16_t ResourceTypeMask = 0x13FF;
+const uint16_t ResourceTypeMask = 0xF3FF;
 
 enum class LoadType : uint16_t {
-    Invalid = 0x0000,
     FirstParty = 0x0400,
     ThirdParty = 0x0800,
 };
@@ -72,9 +73,9 @@
 const uint64_t ActionFlagMask = 0x0000FFFF00000000;
 const uint64_t IfConditionFlag = 0x0001000000000000;
 
-ResourceType toResourceType(CachedResource::Type);
-uint16_t readResourceType(const String&);
-uint16_t readLoadType(const String&);
+OptionSet<ResourceType> toResourceType(CachedResource::Type, ResourceRequestBase::Requester);
+Optional<OptionSet<ResourceType>> readResourceType(const String&);
+Optional<OptionSet<LoadType>> readLoadType(const String&);
 
 struct ResourceLoadInfo {
     URL resourceURL;

Modified: trunk/Source/WebCore/loader/ResourceLoader.cpp (273896 => 273897)


--- trunk/Source/WebCore/loader/ResourceLoader.cpp	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Source/WebCore/loader/ResourceLoader.cpp	2021-03-04 18:00:49 UTC (rev 273897)
@@ -341,7 +341,7 @@
 
     ASSERT(!m_reachedTerminalState);
 #if ENABLE(CONTENT_EXTENSIONS)
-    ASSERT(m_resourceType != ContentExtensions::ResourceType::Invalid);
+    ASSERT(!m_resourceType.isEmpty());
 #endif
 
     // We need a resource identifier for all requests, even if FrameLoader is never going to see it (such as with CORS preflight requests).

Modified: trunk/Source/WebCore/loader/ResourceLoader.h (273896 => 273897)


--- trunk/Source/WebCore/loader/ResourceLoader.h	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Source/WebCore/loader/ResourceLoader.h	2021-03-04 18:00:49 UTC (rev 273897)
@@ -246,7 +246,7 @@
 
 #if ENABLE(CONTENT_EXTENSIONS)
 protected:
-    ContentExtensions::ResourceType m_resourceType { ContentExtensions::ResourceType::Invalid };
+    OptionSet<ContentExtensions::ResourceType> m_resourceType;
 #endif
 };
 

Modified: trunk/Source/WebCore/loader/SubresourceLoader.cpp (273896 => 273897)


--- trunk/Source/WebCore/loader/SubresourceLoader.cpp	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Source/WebCore/loader/SubresourceLoader.cpp	2021-03-04 18:00:49 UTC (rev 273897)
@@ -100,7 +100,7 @@
     subresourceLoaderCounter.increment();
 #endif
 #if ENABLE(CONTENT_EXTENSIONS)
-    m_resourceType = ContentExtensions::toResourceType(resource.type());
+    m_resourceType = ContentExtensions::toResourceType(resource.type(), resource.resourceRequest().requester());
 #endif
     m_canCrossOriginRequestsAskUserForCredentials = resource.type() == CachedResource::Type::MainResource || frame.settings().allowCrossOriginSubresourcesToAskForCredentials();
 }

Modified: trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp (273896 => 273897)


--- trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp	2021-03-04 18:00:49 UTC (rev 273897)
@@ -907,7 +907,7 @@
 #if ENABLE(CONTENT_EXTENSIONS)
     if (m_documentLoader) {
         const auto& resourceRequest = request.resourceRequest();
-        auto results = page.userContentProvider().processContentRuleListsForLoad(page, resourceRequest.url(), ContentExtensions::toResourceType(type), *m_documentLoader);
+        auto results = page.userContentProvider().processContentRuleListsForLoad(page, resourceRequest.url(), ContentExtensions::toResourceType(type, request.resourceRequest().requester()), *m_documentLoader);
         bool blockedLoad = results.summary.blockedLoad;
         bool madeHTTPS = results.summary.madeHTTPS;
         request.applyResults(WTFMove(results), &page);

Modified: trunk/Tools/ChangeLog (273896 => 273897)


--- trunk/Tools/ChangeLog	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Tools/ChangeLog	2021-03-04 18:00:49 UTC (rev 273897)
@@ -1,3 +1,17 @@
+2021-03-04  Alex Christensen  <achristen...@webkit.org>
+
+        Introduce "websocket", "fetch", and "other" resource types to WKContentRuleList
+        https://bugs.webkit.org/show_bug.cgi?id=222709
+        <rdar://problem/71552078>
+
+        Reviewed by Youenn Fablet.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm:
+        (TEST):
+        (webSocketAcceptValue):
+        * TestWebKitAPI/cocoa/HTTPServer.mm:
+        (TestWebKitAPI::statusText):
+
 2021-03-04  Youenn Fablet  <you...@apple.com>
 
         Update camera and microphone capture state control WKWebView API

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm (273896 => 273897)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm	2021-03-04 18:00:49 UTC (rev 273897)
@@ -25,7 +25,11 @@
 
 #import "config.h"
 
+#import "HTTPServer.h"
 #import "PlatformUtilities.h"
+#import "Test.h"
+#import "TestUIDelegate.h"
+#import "TestURLSchemeHandler.h"
 #import <WebKit/WKContentRuleListPrivate.h>
 #import <WebKit/WKContentRuleListStore.h>
 #import <WebKit/WKNavigationDelegatePrivate.h>
@@ -34,8 +38,10 @@
 #import <WebKit/WKWebView.h>
 #import <WebKit/_WKContentRuleListAction.h>
 #import <wtf/RetainPtr.h>
+#import <wtf/SHA1.h>
 #import <wtf/URL.h>
 #import <wtf/cocoa/VectorCocoa.h>
+#import <wtf/text/Base64.h>
 #import <wtf/text/WTFString.h>
 
 static bool receivedNotification;
@@ -117,7 +123,7 @@
     return contentRuleList;
 }
 
-TEST(WebKit, ContentRuleListNotificationMainResource)
+TEST(ContentRuleList, NotificationMainResource)
 {
     auto delegate = adoptNS([[ContentRuleListNotificationDelegate alloc] init]);
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
@@ -131,7 +137,7 @@
     EXPECT_STREQ([notificationIdentifier UTF8String], "testidentifier");
 }
 
-TEST(WebKit, ContentRuleListNotificationSubresource)
+TEST(ContentRuleList, NotificationSubresource)
 {
     auto delegate = adoptNS([[ContentRuleListNotificationDelegate alloc] init]);
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
@@ -147,7 +153,7 @@
     EXPECT_STREQ([notificationIdentifier UTF8String], "testidentifier");
 }
 
-TEST(WebKit, PerformedActionForURL)
+TEST(ContentRuleList, PerformedActionForURL)
 {
     NSString *firstList = @"[{\"action\":{\"type\":\"notify\",\"notification\":\"testnotification\"},\"trigger\":{\"url-filter\":\"notify\"}}]";
     NSString *secondList = @"[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block\"}}]";
@@ -171,6 +177,101 @@
     EXPECT_TRUE(expectedNotifications == notificationList);
 }
 
+static String webSocketAcceptValue(const Vector<char>& request)
+{
+    constexpr auto* keyHeaderField = "Sec-WebSocket-Key: ";
+    const char* keyBegin = strnstr(request.data(), keyHeaderField, request.size()) + strlen(keyHeaderField);
+    EXPECT_NOT_NULL(keyBegin);
+    const char* keyEnd = strnstr(keyBegin, "\r\n", request.size() + (keyBegin - request.data()));
+    EXPECT_NOT_NULL(keyEnd);
+
+    constexpr auto* webSocketKeyGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+    SHA1 sha1;
+    sha1.addBytes(reinterpret_cast<const uint8_t*>(keyBegin), keyEnd - keyBegin);
+    sha1.addBytes(reinterpret_cast<const uint8_t*>(webSocketKeyGUID), strlen(webSocketKeyGUID));
+    SHA1::Digest hash;
+    sha1.computeHash(hash);
+    return base64Encode(hash.data(), SHA1::hashSize);
+}
+
+TEST(ContentRuleList, ResourceTypes)
+{
+    using namespace TestWebKitAPI;
+    HTTPServer webSocketServer([](Connection connection) {
+        connection.receiveHTTPRequest([=](Vector<char>&& request) {
+            connection.send(HTTPResponse(101, {
+                { "Upgrade", "websocket" },
+                { "Connection", "Upgrade" },
+                { "Sec-WebSocket-Accept", webSocketAcceptValue(request) }
+            }).serialize(HTTPResponse::IncludeContentLength::No));
+        });
+    });
+    auto serverPort = webSocketServer.port();
+
+    auto handler = [[TestURLSchemeHandler new] autorelease];
+    handler.startURLSchemeTaskHandler = ^(WKWebView *, id<WKURLSchemeTask> task) {
+        auto respond = [task] (const char* html) {
+            NSURLResponse *response = [[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:strlen(html) textEncodingName:nil] autorelease];
+            [task didReceiveResponse:response];
+            [task didReceiveData:[NSData dataWithBytes:html length:strlen(html)]];
+            [task didFinish];
+        };
+        NSString *path = task.request.URL.path;
+        if ([path isEqualToString:@"/checkWebSocket.html"])
+            return respond([NSString stringWithFormat:@"<script>var ws = new WebSocket('ws://localhost:%d/test');ws._onopen_=()=>{alert('onopen')};ws._onerror_=()=>{alert('onerror')}</script>", serverPort].UTF8String);
+        if ([path isEqualToString:@"/checkFetch.html"])
+            return respond("<script>fetch('test:///fetchContent').then(()=>{alert('fetched')}).catch(()=>{alert('did not fetch')})</script>");
+        if ([path isEqualToString:@"/fetchContent"])
+            return respond("hello");
+        if ([path isEqualToString:@"/checkXHR.html"])
+            return respond("<script>var xhr = new XMLHttpRequest();xhr.open('GET', 'test:///fetchContent');xhr._onreadystatechange_=()=>{if(xhr.readyState==4){setTimeout(()=>{alert('xhr finished')}, 0)}};xhr._onerror_=()=>{alert('xhr error')};xhr.send()</script>");
+
+        ASSERT_NOT_REACHED();
+    };
+    auto configuration = [[WKWebViewConfiguration new] autorelease];
+    [configuration setURLSchemeHandler:handler forURLScheme:@"test"];
+    configuration.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
+    auto webView = [[[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration] autorelease];
+
+    auto listWithResourceType = [] (const char* type) {
+        return makeContentRuleList([NSString stringWithFormat:@"[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*test\",\"resource-type\":[\"%s\"]}}]", type]);
+    };
+
+    WKUserContentController *userContentController = webView.configuration.userContentController;
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///checkWebSocket.html"]]];
+    EXPECT_WK_STREQ([webView _test_waitForAlert], "onopen");
+    [userContentController addContentRuleList:listWithResourceType("websocket").get()];
+    [webView reload];
+    EXPECT_WK_STREQ([webView _test_waitForAlert], "onerror");
+
+    [userContentController removeAllContentRuleLists];
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///checkFetch.html"]]];
+    EXPECT_WK_STREQ([webView _test_waitForAlert], "fetched");
+    [userContentController addContentRuleList:listWithResourceType("fetch").get()];
+    [webView reload];
+    EXPECT_WK_STREQ([webView _test_waitForAlert], "did not fetch");
+    
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///checkXHR.html"]]];
+    EXPECT_WK_STREQ([webView _test_waitForAlert], "xhr error");
+    EXPECT_WK_STREQ([webView _test_waitForAlert], "xhr finished");
+    [userContentController removeAllContentRuleLists];
+    [webView reload];
+    EXPECT_WK_STREQ([webView _test_waitForAlert], "xhr finished");
+    
+    HTTPServer beaconServer({
+        { "/", { "<script>navigator.sendBeacon('/testBeaconTarget', 'hello');fetch('/testFetchTarget').then(()=>{alert('fetch done')})</script>" } },
+        { "/testBeaconTarget", { "hi" } },
+        { "/testFetchTarget", { "hi" } },
+    });
+    [webView loadRequest:beaconServer.request()];
+    EXPECT_WK_STREQ([webView _test_waitForAlert], "fetch done");
+    EXPECT_EQ(beaconServer.totalRequests(), 3u);
+    [userContentController addContentRuleList:listWithResourceType("other").get()];
+    [webView reload];
+    EXPECT_WK_STREQ([webView _test_waitForAlert], "fetch done");
+    EXPECT_EQ(beaconServer.totalRequests(), 5u);
+}
+
 TEST(ContentRuleList, SupportsRegex)
 {
     NSArray<NSString *> *allowed = @[

Modified: trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm (273896 => 273897)


--- trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm	2021-03-04 17:57:32 UTC (rev 273896)
+++ trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm	2021-03-04 18:00:49 UTC (rev 273897)
@@ -172,6 +172,8 @@
 static String statusText(unsigned statusCode)
 {
     switch (statusCode) {
+    case 101:
+        return "Switching Protocols"_s;
     case 200:
         return "OK"_s;
     case 301:
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to