Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm (292538 => 292539)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm 2022-04-07 16:09:50 UTC (rev 292538)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm 2022-04-07 16:10:36 UTC (rev 292539)
@@ -51,6 +51,7 @@
#import <WebKit/_WKRemoteObjectInterface.h>
#import <WebKit/_WKRemoteObjectRegistry.h>
#import <WebKit/_WKWebsiteDataStoreConfiguration.h>
+#import <WebKit/_WKWebsiteDataStoreDelegate.h>
#import <wtf/Deque.h>
#import <wtf/HashMap.h>
#import <wtf/RetainPtr.h>
@@ -3084,6 +3085,13 @@
" alert(event.data);"
" };"
"}"
+""
+"function openWindowToURL(url) {"
+" worker.postMessage({openWindowToURL: url});"
+" navigator.serviceWorker._onmessage_ = (event) => {"
+" alert(event.data);"
+" };"
+"}"
"</script>"_s;
static constexpr auto ServiceWorkerWindowClientNavigateJS =
@@ -3111,9 +3119,18 @@
" event.source.postMessage(currentClients.length + ' client(s)');"
" return;"
" }"
+" if (event.data && event.data.openWindowToURL) {"
+" await self.clients.openWindow(event.data.openWindowToURL).then((client) => {"
+" event.source.postMessage(client ? 'client' : 'none');"
+" }, (e) => {"
+" event.source.postMessage('failed');"
+" });"
+" return;"
+" }"
"});"_s;
-
+static bool shouldServiceWorkerPSONNavigationDelegateAllowNavigation = true;
+static bool shouldServiceWorkerPSONNavigationDelegateAllowNavigationResponse = true;
@interface ServiceWorkerPSONNavigationDelegate : NSObject <WKNavigationDelegatePrivate> {
@public void (^decidePolicyForNavigationAction)(WKNavigationAction *, void (^)(WKNavigationActionPolicy));
@public void (^didStartProvisionalNavigationHandler)();
@@ -3131,12 +3148,12 @@
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
- decisionHandler(WKNavigationActionPolicyAllow);
+ decisionHandler(shouldServiceWorkerPSONNavigationDelegateAllowNavigation ? WKNavigationActionPolicyAllow : WKNavigationActionPolicyCancel);
}
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
- decisionHandler(WKNavigationResponsePolicyAllow);
+ decisionHandler(shouldServiceWorkerPSONNavigationDelegateAllowNavigationResponse ? WKNavigationResponsePolicyAllow : WKNavigationResponsePolicyCancel);
}
@end
@@ -3166,6 +3183,8 @@
TestWebKitAPI::HTTPServer server({
{ "/"_s, { ServiceWorkerWindowClientNavigateMain } },
{ "/?test"_s, { ServiceWorkerWindowClientNavigateMain } },
+ { "/?fail1"_s, { ServiceWorkerWindowClientNavigateMain } },
+ { "/?fail2"_s, { ServiceWorkerWindowClientNavigateMain } },
{ "/?swap"_s, { {{ "Content-Type"_s, "application/html"_s }, { "Cross-Origin-Opener-Policy"_s, "same-origin"_s } }, ServiceWorkerWindowClientNavigateMain } },
{ "/sw.js"_s, { {{ "Content-Type"_s, "application/_javascript_"_s }}, ServiceWorkerWindowClientNavigateJS } }
}, TestWebKitAPI::HTTPServer::Protocol::Http, nullptr, nullptr, 8091);
@@ -3194,6 +3213,19 @@
[webView1 evaluateJavaScript:@"countServiceWorkerClients()" completionHandler: nil];
EXPECT_WK_STREQ([webView1 _test_waitForAlert], "1 client(s)");
+
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigation = false;
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigationResponse = true;
+ [webView1 evaluateJavaScript:[NSString stringWithFormat:@"navigateOtherClientToURL('%@?fail1')", baseURL] completionHandler: nil];
+ EXPECT_WK_STREQ([webView1 _test_waitForAlert], "none");
+
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigation = true;
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigationResponse = false;
+ [webView1 evaluateJavaScript:[NSString stringWithFormat:@"navigateOtherClientToURL('%@?fail2')", baseURL] completionHandler: nil];
+ EXPECT_WK_STREQ([webView1 _test_waitForAlert], "none");
+
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigation = true;
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigationResponse = true;
}
TEST(ServiceWorker, WindowClientNavigateCrossOrigin)
@@ -3231,3 +3263,121 @@
[webView1 evaluateJavaScript:[NSString stringWithFormat:@"navigateOtherClientToURL('%@')", [[server2.request() URL] absoluteString]] completionHandler: nil];
EXPECT_WK_STREQ([webView1 _test_waitForAlert], "none");
}
+
+@interface ServiceWorkerOpenWindowWebsiteDataStoreDelegate: NSObject <_WKWebsiteDataStoreDelegate> {
+@private
+ WKWebViewConfiguration* _configuration;
+ RetainPtr<ServiceWorkerPSONNavigationDelegate> _navigationDelegate;
+ RetainPtr<TestWKWebView> _webView;
+}
+- (instancetype)initWithConfiguration:(WKWebViewConfiguration*)configuration;
+@end
+
+@implementation ServiceWorkerOpenWindowWebsiteDataStoreDelegate { }
+- (instancetype)initWithConfiguration:(WKWebViewConfiguration*)configuration
+{
+ _configuration = configuration;
+ return self;
+}
+
+- (void)websiteDataStore:(WKWebsiteDataStore *)dataStore openWindow:(NSURL *)url fromServiceWorkerOrigin:(WKSecurityOrigin *)serviceWorkerOrigin completionHandler:(void (^)(WKWebView *newWebView))completionHandler
+{
+ _navigationDelegate = adoptNS([[ServiceWorkerPSONNavigationDelegate alloc] init]);
+ _webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:_configuration addToWindow:YES]);
+ [_webView setNavigationDelegate:_navigationDelegate.get()];
+
+ [_webView loadRequest:[NSURLRequest requestWithURL:url]];
+ completionHandler(_webView.get());
+}
+
+@end
+
+TEST(ServiceWorker, OpenWindowWebsiteDataStoreDelegate)
+{
+ [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins];
+
+ // Start with a clean slate data store
+ [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+
+ auto preferences = [configuration preferences];
+ for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) {
+ if ([feature.key isEqualToString:@"ServiceWorkersUserGestureEnabled"])
+ [preferences _setEnabled:NO forInternalDebugFeature:feature];
+ }
+
+ auto dataStoreDelegate = adoptNS([[ServiceWorkerOpenWindowWebsiteDataStoreDelegate alloc] initWithConfiguration:configuration.get()]);
+ [[configuration websiteDataStore] set_delegate:dataStoreDelegate.get()];
+
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() addToWindow:YES]);
+
+ TestWebKitAPI::HTTPServer server({
+ { "/"_s, { ServiceWorkerWindowClientNavigateMain } },
+ { "/sw.js"_s, { {{ "Content-Type"_s, "application/_javascript_"_s }}, ServiceWorkerWindowClientNavigateJS } }
+ }, TestWebKitAPI::HTTPServer::Protocol::Http, nullptr, nullptr, 8091);
+
+ [webView loadRequest:server.request()];
+ EXPECT_WK_STREQ([webView _test_waitForAlert], "successfully registered");
+
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigation = true;
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigationResponse = true;
+ [webView evaluateJavaScript:[NSString stringWithFormat:@"openWindowToURL('%@')", [[server.request() URL] absoluteString]] completionHandler: nil];
+ EXPECT_WK_STREQ([webView _test_waitForAlert], "client");
+
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigation = false;
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigationResponse = true;
+ [webView evaluateJavaScript:[NSString stringWithFormat:@"openWindowToURL('%@')", [[server.request() URL] absoluteString]] completionHandler: nil];
+ EXPECT_WK_STREQ([webView _test_waitForAlert], "none");
+
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigation = true;
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigationResponse = false;
+ [webView evaluateJavaScript:[NSString stringWithFormat:@"openWindowToURL('%@')", [[server.request() URL] absoluteString]] completionHandler: nil];
+ EXPECT_WK_STREQ([webView _test_waitForAlert], "none");
+
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigation = true;
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigationResponse = true;
+}
+
+TEST(ServiceWorker, OpenWindowCOOP)
+{
+ [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins];
+
+ // Start with a clean slate data store
+ [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+
+ auto preferences = [configuration preferences];
+ for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) {
+ if ([feature.key isEqualToString:@"ServiceWorkersUserGestureEnabled"])
+ [preferences _setEnabled:NO forInternalDebugFeature:feature];
+ }
+
+ auto dataStoreDelegate = adoptNS([[ServiceWorkerOpenWindowWebsiteDataStoreDelegate alloc] initWithConfiguration:configuration.get()]);
+ [[configuration websiteDataStore] set_delegate:dataStoreDelegate.get()];
+
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() addToWindow:YES]);
+
+ TestWebKitAPI::HTTPServer server({
+ { "/"_s, { ServiceWorkerWindowClientNavigateMain } },
+ { "/sw.js"_s, { {{ "Content-Type"_s, "application/_javascript_"_s }}, ServiceWorkerWindowClientNavigateJS } },
+ { "/?swap"_s, { {{ "Content-Type"_s, "application/html"_s }, { "Cross-Origin-Opener-Policy"_s, "same-origin"_s } }, ServiceWorkerWindowClientNavigateMain } }
+ }, TestWebKitAPI::HTTPServer::Protocol::Http, nullptr, nullptr, 8091);
+
+ [webView loadRequest:server.request()];
+ EXPECT_WK_STREQ([webView _test_waitForAlert], "successfully registered");
+
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigation = true;
+ shouldServiceWorkerPSONNavigationDelegateAllowNavigationResponse = true;
+ [webView evaluateJavaScript:[NSString stringWithFormat:@"openWindowToURL('%@?swap')", [[server.request() URL] absoluteString]] completionHandler: nil];
+ EXPECT_WK_STREQ([webView _test_waitForAlert], "client");
+}