Title: [264687] trunk/Tools
Revision
264687
Author
commit-qu...@webkit.org
Date
2020-07-21 18:11:14 -0700 (Tue, 21 Jul 2020)

Log Message

Safari does not present CertificateInfo for service-worker served documents
https://bugs.webkit.org/show_bug.cgi?id=206403

Patch by Alex Christensen <achristen...@webkit.org> on 2020-07-21
Reviewed by Brady Eidson.

This is actually just a failing test that reproduces the issue 100% of the time.

* TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm:
* TestWebKitAPI/cocoa/HTTPServer.h:
* TestWebKitAPI/cocoa/HTTPServer.mm:
(TestWebKitAPI::HTTPServer::cancel):
(TestWebKitAPI::HTTPServer::HTTPServer):
(TestWebKitAPI::m_protocol):
(TestWebKitAPI::HTTPServer::totalRequests const):
(TestWebKitAPI::HTTPServer::respondToRequests):
(TestWebKitAPI::Connection::terminate):
(TestWebKitAPI::Connection::cancel):
(TestWebKitAPI::Connection::terminate const): Deleted.

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (264686 => 264687)


--- trunk/Tools/ChangeLog	2020-07-22 01:10:01 UTC (rev 264686)
+++ trunk/Tools/ChangeLog	2020-07-22 01:11:14 UTC (rev 264687)
@@ -1,3 +1,24 @@
+2020-07-21  Alex Christensen  <achristen...@webkit.org>
+
+        Safari does not present CertificateInfo for service-worker served documents
+        https://bugs.webkit.org/show_bug.cgi?id=206403
+
+        Reviewed by Brady Eidson.
+
+        This is actually just a failing test that reproduces the issue 100% of the time.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm:
+        * TestWebKitAPI/cocoa/HTTPServer.h:
+        * TestWebKitAPI/cocoa/HTTPServer.mm:
+        (TestWebKitAPI::HTTPServer::cancel):
+        (TestWebKitAPI::HTTPServer::HTTPServer):
+        (TestWebKitAPI::m_protocol):
+        (TestWebKitAPI::HTTPServer::totalRequests const):
+        (TestWebKitAPI::HTTPServer::respondToRequests):
+        (TestWebKitAPI::Connection::terminate):
+        (TestWebKitAPI::Connection::cancel):
+        (TestWebKitAPI::Connection::terminate const): Deleted.
+
 2020-07-21  Jonathan Bedard  <jbed...@apple.com>
 
         ImageDiff: Set ALWAYS_SEARCH_USER_PATHS to NO

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm (264686 => 264687)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm	2020-07-22 01:10:01 UTC (rev 264686)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm	2020-07-22 01:11:14 UTC (rev 264687)
@@ -30,6 +30,7 @@
 #import "ServiceWorkerTCPServer.h"
 #import "Test.h"
 #import "TestNavigationDelegate.h"
+#import "TestUIDelegate.h"
 #import "TestWKWebView.h"
 #import <WebKit/WKPreferencesPrivate.h>
 #import <WebKit/WKProcessPoolPrivate.h>
@@ -2112,3 +2113,114 @@
     }];
     TestWebKitAPI::Util::run(&doneRemoving);
 }
+
+#if HAVE(NETWORK_FRAMEWORK) && HAVE(TLS_PROTOCOL_VERSION_T)
+
+static bool isTestServerTrust(SecTrustRef trust)
+{
+    if (!trust)
+        return false;
+    if (SecTrustGetCertificateCount(trust) != 1)
+        return false;
+    if (![adoptNS((NSString *)SecCertificateCopySubjectSummary(SecTrustGetCertificateAtIndex(trust, 0))) isEqualToString:@"Me"])
+        return false;
+    return true;
+}
+
+enum class ResponseType { Synthetic, Cached, Fetched };
+static void runTest(ResponseType responseType)
+{
+    using namespace TestWebKitAPI;
+    
+    __block bool removedAnyExistingData = false;
+    [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
+        removedAnyExistingData = true;
+    }];
+    TestWebKitAPI::Util::run(&removedAnyExistingData);
+
+    static const char* main =
+    "<script>"
+    "try {"
+    "    navigator.serviceWorker.register('/sw.js').then(function(reg) {"
+    "        if (reg.active) {"
+    "            alert('worker unexpectedly already active');"
+    "            return;"
+    "        }"
+    "        worker = reg.installing;"
+    "        worker.addEventListener('statechange', function() {"
+    "            if (worker.state == 'activated')"
+    "                alert('successfully registered');"
+    "        });"
+    "    }).catch(function(error) {"
+    "        alert('Registration failed with: ' + error);"
+    "    });"
+    "} catch(e) {"
+    "    alert('Exception: ' + e);"
+    "}"
+    "</script>";
+    
+    const char* js = nullptr;
+    const char* expectedAlert = nullptr;
+    size_t expectedServerRequests1 = 0;
+    size_t expectedServerRequests2 = 0;
+
+    switch (responseType) {
+    case ResponseType::Synthetic:
+        js = "self.addEventListener('fetch', (event) => { event.respondWith(new Response(new Blob(['<script>alert(\"synthetic response\")</script>'], {type: 'text/html'}))); })";
+        expectedAlert = "synthetic response";
+        expectedServerRequests1 = 2;
+        expectedServerRequests2 = 2;
+        break;
+    case ResponseType::Cached:
+        js = "self.addEventListener('install', (event) => { event.waitUntil( caches.open('v1').then((cache) => { return cache.addAll(['/cached.html']); }) ); });"
+            "self.addEventListener('fetch', (event) => { event.respondWith(caches.match('/cached.html')) });";
+        expectedAlert = "loaded from cache";
+        expectedServerRequests1 = 3;
+        expectedServerRequests2 = 3;
+        break;
+    case ResponseType::Fetched:
+        js = "self.addEventListener('fetch', (event) => { event.respondWith(fetch('/fetched.html')) });";
+        expectedAlert = "fetched from server";
+        expectedServerRequests1 = 2;
+        expectedServerRequests2 = 3;
+        break;
+    }
+
+    HTTPServer server({
+        { "/", { main } },
+        { "/sw.js", { {{ "Content-Type", "application/_javascript_" }}, js } },
+        { "/cached.html", { "<script>alert('loaded from cache')</script>" } },
+        { "/fetched.html", { "<script>alert('fetched from server')</script>" } },
+    }, HTTPServer::Protocol::Https);
+
+    auto webView = adoptNS([WKWebView new]);
+
+    auto delegate = adoptNS([TestNavigationDelegate new]);
+    [delegate setDidReceiveAuthenticationChallenge:^(WKWebView *, NSURLAuthenticationChallenge *challenge, void (^callback)(NSURLSessionAuthChallengeDisposition, NSURLCredential *)) {
+        EXPECT_WK_STREQ(challenge.protectionSpace.authenticationMethod, NSURLAuthenticationMethodServerTrust);
+        callback(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
+    }];
+    webView.get().navigationDelegate = delegate.get();
+
+    [webView loadRequest:server.request()];
+    EXPECT_WK_STREQ([webView _test_waitForAlert], "successfully registered");
+
+    EXPECT_EQ(server.totalRequests(), expectedServerRequests1);
+    EXPECT_TRUE(isTestServerTrust(webView.get().serverTrust));
+    if (responseType != ResponseType::Fetched)
+        server.cancel();
+
+    [webView reload];
+    EXPECT_WK_STREQ([webView _test_waitForAlert], expectedAlert);
+    EXPECT_EQ(server.totalRequests(), expectedServerRequests2);
+    EXPECT_NULL(webView.get().serverTrust); // FIXME: This should be EXPECT_TRUE(isTestServerTrust(webView.get().serverTrust));
+}
+
+TEST(ServiceWorkers, ServerTrust)
+{
+    runTest(ResponseType::Synthetic);
+    runTest(ResponseType::Cached);
+    runTest(ResponseType::Fetched);
+}
+
+#endif // HAVE(NETWORK_FRAMEWORK) && HAVE(TLS_PROTOCOL_VERSION_T)

Modified: trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h (264686 => 264687)


--- trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h	2020-07-22 01:10:01 UTC (rev 264686)
+++ trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h	2020-07-22 01:11:14 UTC (rev 264687)
@@ -52,14 +52,15 @@
     uint16_t port() const;
     NSURLRequest *request(const String& path = "/"_str) const;
     size_t totalRequests() const;
+    void cancel();
 
     static void respondWithChallengeThenOK(Connection);
     
 private:
     static RetainPtr<nw_parameters_t> listenerParameters(Protocol, CertificateVerifier&&);
-    static void respondToRequests(Connection, RefPtr<RequestData>);
+    static void respondToRequests(Connection, Ref<RequestData>);
 
-    RefPtr<RequestData> m_requestData;
+    Ref<RequestData> m_requestData;
     RetainPtr<nw_listener_t> m_listener;
     Protocol m_protocol { Protocol::Http };
 };
@@ -71,7 +72,8 @@
     void send(RetainPtr<dispatch_data_t>&&, CompletionHandler<void()>&& = nullptr) const;
     void receiveBytes(CompletionHandler<void(Vector<uint8_t>&&)>&&) const;
     void receiveHTTPRequest(CompletionHandler<void(Vector<char>&&)>&&, Vector<char>&& buffer = { }) const;
-    void terminate() const;
+    void terminate();
+    void cancel();
 
 private:
     friend class HTTPServer;

Modified: trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm (264686 => 264687)


--- trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm	2020-07-22 01:10:01 UTC (rev 264686)
+++ trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm	2020-07-22 01:11:14 UTC (rev 264687)
@@ -49,6 +49,7 @@
     
     size_t requestCount { 0 };
     const HashMap<String, HTTPResponse> requestMap;
+    Vector<Connection> connections;
 };
 
 RetainPtr<nw_parameters_t> HTTPServer::listenerParameters(Protocol protocol, CertificateVerifier&& verifier)
@@ -88,13 +89,29 @@
     Util::run(&ready);
 }
 
+void HTTPServer::cancel()
+{
+    __block bool cancelled = false;
+    nw_listener_set_state_changed_handler(m_listener.get(), ^(nw_listener_state_t state, nw_error_t error) {
+        ASSERT_UNUSED(error, !error);
+        if (state == nw_listener_state_cancelled)
+            cancelled = true;
+    });
+    nw_listener_cancel(m_listener.get());
+    Util::run(&cancelled);
+    m_listener = nullptr;
+    for (auto& connection : std::exchange(m_requestData->connections, { }))
+        connection.cancel();
+}
+
 HTTPServer::HTTPServer(std::initializer_list<std::pair<String, HTTPResponse>> responses, Protocol protocol, CertificateVerifier&& verifier)
-    : m_requestData(adoptRef(new RequestData(responses)))
+    : m_requestData(adoptRef(*new RequestData(responses)))
     , m_listener(adoptNS(nw_listener_create(listenerParameters(protocol, WTFMove(verifier)).get())))
     , m_protocol(protocol)
 {
     nw_listener_set_queue(m_listener.get(), dispatch_get_main_queue());
     nw_listener_set_new_connection_handler(m_listener.get(), makeBlockPtr([requestData = m_requestData](nw_connection_t connection) {
+        requestData->connections.append(Connection(connection));
         nw_connection_set_queue(connection, dispatch_get_main_queue());
         nw_connection_start(connection);
         respondToRequests(Connection(connection), requestData);
@@ -103,11 +120,13 @@
 }
 
 HTTPServer::HTTPServer(Function<void(Connection)>&& connectionHandler, Protocol protocol)
-    : m_listener(adoptNS(nw_listener_create(listenerParameters(protocol, nullptr).get())))
+    : m_requestData(adoptRef(*new RequestData({ })))
+    , m_listener(adoptNS(nw_listener_create(listenerParameters(protocol, nullptr).get())))
     , m_protocol(protocol)
 {
     nw_listener_set_queue(m_listener.get(), dispatch_get_main_queue());
-    nw_listener_set_new_connection_handler(m_listener.get(), makeBlockPtr([connectionHandler = WTFMove(connectionHandler)] (nw_connection_t connection) {
+    nw_listener_set_new_connection_handler(m_listener.get(), makeBlockPtr([requestData = m_requestData, connectionHandler = WTFMove(connectionHandler)] (nw_connection_t connection) {
+        requestData->connections.append(Connection(connection));
         nw_connection_set_queue(connection, dispatch_get_main_queue());
         nw_connection_start(connection);
         connectionHandler(Connection(connection));
@@ -139,8 +158,6 @@
 
 size_t HTTPServer::totalRequests() const
 {
-    if (!m_requestData)
-        return 0;
     return m_requestData->requestCount;
 }
 
@@ -187,9 +204,9 @@
     return request;
 }
 
-void HTTPServer::respondToRequests(Connection connection, RefPtr<RequestData> requestData)
+void HTTPServer::respondToRequests(Connection connection, Ref<RequestData> requestData)
 {
-    connection.receiveHTTPRequest([connection, requestData] (Vector<char>&& request) {
+    connection.receiveHTTPRequest([connection, requestData] (Vector<char>&& request) mutable {
         if (!request.size())
             return;
         requestData->requestCount++;
@@ -291,11 +308,24 @@
     }).get());
 }
 
-void Connection::terminate() const
+void Connection::terminate()
 {
     nw_connection_cancel(m_connection.get());
 }
 
+void Connection::cancel()
+{
+    __block bool cancelled = false;
+    nw_connection_set_state_changed_handler(m_connection.get(), ^(nw_connection_state_t state, nw_error_t error) {
+        ASSERT_UNUSED(error, !error);
+        if (state == nw_connection_state_cancelled)
+            cancelled = true;
+    });
+    nw_connection_cancel(m_connection.get());
+    Util::run(&cancelled);
+    m_connection = nullptr;
+}
+
 void H2::Connection::send(Frame&& frame, CompletionHandler<void()>&& completionHandler) const
 {
     auto frameType = frame.type();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to