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();