blob: b4b1e897f6ad6c5eb222472d2bf7a13bc34370ae [file] [log] [blame] [edit]
/*
* Copyright (C) 2017-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "config.h"
#import "HTTPServer.h"
#import "PlatformUtilities.h"
#import "TestCocoa.h"
#import "TestNavigationDelegate.h"
#import "TestWKWebView.h"
#import <WebKit/WKProcessPoolPrivate.h>
#import <WebKit/WKWebViewPrivate.h>
#import <WebKit/WKWebViewPrivateForTesting.h>
#import <WebKit/WKWebpagePreferencesPrivate.h>
#import <WebKit/_WKProcessPoolConfiguration.h>
#import <wtf/Vector.h>
namespace TestWebKitAPI {
#if !PLATFORM(IOS)
static bool isEnhancedSecurityEnabled(WKWebView *webView)
{
__block bool gotResponse = false;
__block bool isEnhancedSecurityEnabledResult = false;
[webView _isEnhancedSecurityEnabled:^(BOOL isEnhancedSecurityEnabled) {
isEnhancedSecurityEnabledResult = isEnhancedSecurityEnabled;
gotResponse = true;
}];
TestWebKitAPI::Util::run(&gotResponse);
EXPECT_NE([webView _webProcessIdentifier], 0);
return isEnhancedSecurityEnabledResult;
}
static bool isJITEnabled(WKWebView *webView)
{
__block bool gotResponse = false;
__block bool isJITEnabledResult = false;
[webView _isJITEnabled:^(BOOL isJITEnabled) {
isJITEnabledResult = isJITEnabled;
gotResponse = true;
}];
TestWebKitAPI::Util::run(&gotResponse);
EXPECT_NE([webView _webProcessIdentifier], 0);
return isJITEnabledResult;
}
TEST(EnhancedSecurity, EnhancedSecurityEnablesTrue)
{
auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
webViewConfiguration.get().defaultWebpagePreferences.securityRestrictionMode = WKSecurityRestrictionModeMaximizeCompatibility;
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
NSURL *url = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
[webView _test_waitForDidFinishNavigation];
EXPECT_EQ(true, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
NSString *processVariant = [webView _webContentProcessVariantForFrame:nil];
EXPECT_STREQ("security", processVariant.UTF8String);
#endif
}
TEST(EnhancedSecurity, EnhancedSecurityEnableFalse)
{
auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
webViewConfiguration.get().defaultWebpagePreferences.securityRestrictionMode = WKSecurityRestrictionModeNone;
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
NSURL *url = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
[webView _test_waitForDidFinishNavigation];
EXPECT_EQ(false, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
NSString *processVariant = [webView _webContentProcessVariantForFrame:nil];
EXPECT_STREQ("standard", processVariant.UTF8String);
#endif
}
TEST(EnhancedSecurity, EnhancedSecurityDisablesJIT)
{
auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
webViewConfiguration.get().defaultWebpagePreferences.securityRestrictionMode = WKSecurityRestrictionModeMaximizeCompatibility;
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
NSURL *url = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
[webView _test_waitForDidFinishNavigation];
EXPECT_EQ(false, isJITEnabled(webView.get()));
}
TEST(EnhancedSecurity, EnhancedSecurityNavigationStaysEnabledAfterNavigation)
{
auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
webViewConfiguration.get().defaultWebpagePreferences.securityRestrictionMode = WKSecurityRestrictionModeMaximizeCompatibility;
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
auto delegate = adoptNS([TestNavigationDelegate new]);
[webView setNavigationDelegate:delegate.get()];
__block bool finishedNavigation = false;
delegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
finishedNavigation = true;
};
NSURL *url = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(true, isEnhancedSecurityEnabled(webView.get()));
finishedNavigation = false;
NSURL *url2 = [NSBundle.test_resourcesBundle URLForResource:@"simple2" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url2]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(true, isEnhancedSecurityEnabled(webView.get()));
}
TEST(EnhancedSecurity, PSONToEnhancedSecurity)
{
auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
webViewConfiguration.get().defaultWebpagePreferences.securityRestrictionMode = WKSecurityRestrictionModeNone;
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
auto delegate = adoptNS([TestNavigationDelegate new]);
[webView setNavigationDelegate:delegate.get()];
__block bool finishedNavigation = false;
delegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
finishedNavigation = true;
};
NSURL *url = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(false, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("standard", [webView _webContentProcessVariantForFrame:nil].UTF8String);
#endif
pid_t pid1 = [webView _webProcessIdentifier];
EXPECT_NE(pid1, 0);
finishedNavigation = false;
delegate.get().decidePolicyForNavigationActionWithPreferences = ^(WKNavigationAction *action, WKWebpagePreferences *preferences, void (^completionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
EXPECT_EQ(preferences.securityRestrictionMode, WKSecurityRestrictionModeNone);
preferences.securityRestrictionMode = WKSecurityRestrictionModeMaximizeCompatibility;
completionHandler(WKNavigationActionPolicyAllow, preferences);
};
NSURL *url2 = [NSBundle.test_resourcesBundle URLForResource:@"simple2" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url2]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(true, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("security", [webView _webContentProcessVariantForFrame:nil].UTF8String);
#endif
EXPECT_NE(pid1, [webView _webProcessIdentifier]);
}
TEST(EnhancedSecurity, PSONToEnhancedSecuritySamePage)
{
auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
webViewConfiguration.get().defaultWebpagePreferences.securityRestrictionMode = WKSecurityRestrictionModeNone;
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
auto delegate = adoptNS([TestNavigationDelegate new]);
[webView setNavigationDelegate:delegate.get()];
__block bool finishedNavigation = false;
delegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
finishedNavigation = true;
};
NSURL *url = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(false, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("standard", [webView _webContentProcessVariantForFrame:nil].UTF8String);
#endif
pid_t pid1 = [webView _webProcessIdentifier];
EXPECT_NE(pid1, 0);
finishedNavigation = false;
delegate.get().decidePolicyForNavigationActionWithPreferences = ^(WKNavigationAction *action, WKWebpagePreferences *preferences, void (^completionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
EXPECT_EQ(preferences.securityRestrictionMode, WKSecurityRestrictionModeNone);
preferences.securityRestrictionMode = WKSecurityRestrictionModeMaximizeCompatibility;
completionHandler(WKNavigationActionPolicyAllow, preferences);
};
NSURL *url2 = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url2]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(true, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("security", [webView _webContentProcessVariantForFrame:nil].UTF8String);
#endif
EXPECT_NE(pid1, [webView _webProcessIdentifier]);
}
static RetainPtr<_WKProcessPoolConfiguration> psonProcessPoolConfiguration()
{
auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
processPoolConfiguration.get().processSwapsOnNavigation = YES;
processPoolConfiguration.get().usesWebProcessCache = YES;
processPoolConfiguration.get().prewarmsProcessesAutomatically = YES;
processPoolConfiguration.get().processSwapsOnNavigationWithinSameNonHTTPFamilyProtocol = YES;
return processPoolConfiguration;
}
TEST(EnhancedSecurity, PSONToEnhancedSecuritySharedProcessPool)
{
auto processPoolConfiguration = psonProcessPoolConfiguration();
auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
[webViewConfiguration setProcessPool:processPool.get()];
webViewConfiguration.get().defaultWebpagePreferences.securityRestrictionMode = WKSecurityRestrictionModeNone;
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
auto delegate = adoptNS([TestNavigationDelegate new]);
[webView setNavigationDelegate:delegate.get()];
__block bool finishedNavigation = false;
delegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
finishedNavigation = true;
};
NSURL *url = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(false, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("standard", [webView _webContentProcessVariantForFrame:nil].UTF8String);
#endif
pid_t pid1 = [webView _webProcessIdentifier];
EXPECT_NE(pid1, 0);
finishedNavigation = false;
auto webView2 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
[webView2 setNavigationDelegate:delegate.get()];
delegate.get().decidePolicyForNavigationActionWithPreferences = ^(WKNavigationAction *action, WKWebpagePreferences *preferences, void (^completionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
EXPECT_EQ(preferences.securityRestrictionMode, WKSecurityRestrictionModeNone);
preferences.securityRestrictionMode = WKSecurityRestrictionModeMaximizeCompatibility;
completionHandler(WKNavigationActionPolicyAllow, preferences);
};
NSURL *url2 = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView2 loadRequest:[NSURLRequest requestWithURL:url2]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(true, isEnhancedSecurityEnabled(webView2.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("security", [webView2 _webContentProcessVariantForFrame:nil].UTF8String);
#endif
EXPECT_NE(pid1, [webView2 _webProcessIdentifier]);
}
TEST(EnhancedSecurity, PSONToEnhancedSecuritySharedProcessPoolReverse)
{
auto processPoolConfiguration = psonProcessPoolConfiguration();
auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
[webViewConfiguration setProcessPool:processPool.get()];
webViewConfiguration.get().defaultWebpagePreferences.securityRestrictionMode = WKSecurityRestrictionModeMaximizeCompatibility;
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
auto delegate = adoptNS([TestNavigationDelegate new]);
[webView setNavigationDelegate:delegate.get()];
__block bool finishedNavigation = false;
delegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
finishedNavigation = true;
};
NSURL *url = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(true, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("security", [webView _webContentProcessVariantForFrame:nil].UTF8String);
#endif
pid_t pid1 = [webView _webProcessIdentifier];
EXPECT_NE(pid1, 0);
finishedNavigation = false;
auto webView2 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
[webView2 setNavigationDelegate:delegate.get()];
delegate.get().decidePolicyForNavigationActionWithPreferences = ^(WKNavigationAction *action, WKWebpagePreferences *preferences, void (^completionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
EXPECT_EQ(preferences.securityRestrictionMode, WKSecurityRestrictionModeMaximizeCompatibility);
preferences.securityRestrictionMode = WKSecurityRestrictionModeNone;
completionHandler(WKNavigationActionPolicyAllow, preferences);
};
NSURL *url2 = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView2 loadRequest:[NSURLRequest requestWithURL:url2]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(false, isEnhancedSecurityEnabled(webView2.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("standard", [webView2 _webContentProcessVariantForFrame:nil].UTF8String);
#endif
EXPECT_NE(pid1, [webView2 _webProcessIdentifier]);
}
#if USE(APPLE_INTERNAL_SDK)
TEST(EnhancedSecurity, ProcessVariantMatchesConfiguration)
{
auto webViewConfiguration1 = adoptNS([WKWebViewConfiguration new]);
webViewConfiguration1.get().defaultWebpagePreferences.securityRestrictionMode = WKSecurityRestrictionModeMaximizeCompatibility;
auto webView1 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration1.get()]);
auto webViewConfiguration2 = adoptNS([WKWebViewConfiguration new]);
webViewConfiguration2.get().defaultWebpagePreferences.securityRestrictionMode = WKSecurityRestrictionModeNone;
auto webView2 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration2.get()]);
NSURL *url = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView1 loadRequest:[NSURLRequest requestWithURL:url]];
[webView1 _test_waitForDidFinishNavigation];
EXPECT_EQ(true, isEnhancedSecurityEnabled(webView1.get()));
EXPECT_STREQ("security", [webView1 _webContentProcessVariantForFrame:nil].UTF8String);
[webView2 loadRequest:[NSURLRequest requestWithURL:url]];
[webView2 _test_waitForDidFinishNavigation];
EXPECT_EQ(false, isEnhancedSecurityEnabled(webView2.get()));
EXPECT_STREQ("standard", [webView2 _webContentProcessVariantForFrame:nil].UTF8String);
}
#endif
TEST(EnhancedSecurity, ProcessCanLaunch)
{
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
configuration.get().websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
configuration.get().processPool = adoptNS([[WKProcessPool alloc] init]).get();
configuration.get().defaultWebpagePreferences.securityRestrictionMode = WKSecurityRestrictionModeMaximizeCompatibility;
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
[webView loadHTMLString:@"<html><body>test</body></html>" baseURL:nil];
// Wait with explicit timeout instead of _test_waitForDidFinishNavigation
__block bool navigationFinished = false;
auto delegate = adoptNS([TestNavigationDelegate new]);
delegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
navigationFinished = true;
};
[webView setNavigationDelegate:delegate.get()];
// Wait up to 10 seconds for navigation to complete
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:10.0];
while (!navigationFinished && [timeout timeIntervalSinceNow] > 0)
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
if (navigationFinished)
NSLog(@"EnhancedSecurity ProcessCanLaunch: Navigation finished");
else
NSLog(@"EnhancedSecurity ProcessCanLaunch: Navigation TIMED OUT after 10 seconds");
auto processID = [webView _webProcessIdentifier];
NSLog(@"EnhancedSecurity ProcessCanLaunch: Process ID: %d", processID);
EXPECT_NE(processID, 0);
}
TEST(EnhancedSecurity, CaptivePortalProcessCanLaunch)
{
[WKProcessPool _setCaptivePortalModeEnabledGloballyForTesting:YES];
// Create configuration AFTER setting global mode
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
configuration.get().websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
configuration.get().processPool = adoptNS([[WKProcessPool alloc] init]).get();
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
[webView loadHTMLString:@"<html><body>test</body></html>" baseURL:nil];
// Wait with explicit timeout instead of _test_waitForDidFinishNavigation
__block bool navigationFinished = false;
auto delegate = adoptNS([TestNavigationDelegate new]);
delegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
navigationFinished = true;
};
[webView setNavigationDelegate:delegate.get()];
// Wait up to 10 seconds for navigation to complete
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:10.0];
while (!navigationFinished && [timeout timeIntervalSinceNow] > 0)
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
if (navigationFinished)
NSLog(@"CaptivePortal ProcessCanLaunch: Navigation finished");
else
NSLog(@"CaptivePortal ProcessCanLaunch: Navigation TIMED OUT after 10 seconds");
auto processID = [webView _webProcessIdentifier];
EXPECT_NE(processID, 0);
[WKProcessPool _clearCaptivePortalModeEnabledGloballyForTesting];
}
TEST(EnhancedSecurity, EnhancedSecurityNavigationStaysEnabledAfterSubFrameNavigationRequestDisables)
{
HTTPServer server({
{ "/example"_s, { "<iframe id='webkit_frame' src='https://example.com/webkit'></iframe>"_s } },
{ "/example_subframe"_s, { "<script>alert('done')</script>"_s } },
{ "/webkit"_s, { "<html></html>"_s } }
}, HTTPServer::Protocol::HttpsProxy);
auto webViewConfiguration = server.httpsProxyConfiguration();
[webViewConfiguration.processPool _setObject:@"WebProcessPlugInWithInternals" forBundleParameter:TestWebKitAPI::Util::TestPlugInClassNameParameter];
webViewConfiguration.defaultWebpagePreferences._enhancedSecurityEnabled = YES;
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration]);
auto delegate = adoptNS([TestNavigationDelegate new]);
[delegate allowAnyTLSCertificate];
[webView setNavigationDelegate:delegate.get()];
__block bool finishedNavigation = false;
delegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
finishedNavigation = true;
};
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://example.com/example"]]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(true, isEnhancedSecurityEnabled(webView.get()));
finishedNavigation = false;
delegate.get().decidePolicyForNavigationActionWithPreferences = ^(WKNavigationAction *action, WKWebpagePreferences *preferences, void (^completionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
EXPECT_TRUE(preferences._enhancedSecurityEnabled);
EXPECT_FALSE(action.sourceFrame.isMainFrame);
preferences._enhancedSecurityEnabled = NO;
completionHandler(WKNavigationActionPolicyAllow, preferences);
};
[webView evaluateJavaScript:@"location.href = 'https://example.com/example_subframe'" inFrame:[webView firstChildFrame] completionHandler:nil];
EXPECT_WK_STREQ([webView _test_waitForAlert], "done");
EXPECT_EQ(true, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("security", [webView _webContentProcessVariantForFrame:nil].UTF8String);
EXPECT_STREQ("security", [webView _webContentProcessVariantForFrame:[webView firstChildFrame]._handle].UTF8String);
#endif
}
TEST(EnhancedSecurity, EnhancedSecurityNavigationStaysEnabledAfterSubFrameNavigationRequestDisablesCrossOrigin)
{
HTTPServer server({
{ "/example"_s, { "<iframe id='webkit_frame' src='https://example.com/webkit'></iframe>"_s } },
{ "/example_subframe"_s, { "<script>alert('done')</script>"_s } },
{ "/webkit"_s, { "<html></html>"_s } }
}, HTTPServer::Protocol::HttpsProxy);
auto webViewConfiguration = server.httpsProxyConfiguration();
[webViewConfiguration.processPool _setObject:@"WebProcessPlugInWithInternals" forBundleParameter:TestWebKitAPI::Util::TestPlugInClassNameParameter];
webViewConfiguration.defaultWebpagePreferences._enhancedSecurityEnabled = YES;
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration]);
auto delegate = adoptNS([TestNavigationDelegate new]);
[delegate allowAnyTLSCertificate];
[webView setNavigationDelegate:delegate.get()];
__block bool finishedNavigation = false;
delegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
finishedNavigation = true;
};
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://example.com/example"]]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(true, isEnhancedSecurityEnabled(webView.get()));
finishedNavigation = false;
delegate.get().decidePolicyForNavigationActionWithPreferences = ^(WKNavigationAction *action, WKWebpagePreferences *preferences, void (^completionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
EXPECT_TRUE(preferences._enhancedSecurityEnabled);
EXPECT_FALSE(action.sourceFrame.isMainFrame);
preferences._enhancedSecurityEnabled = NO;
completionHandler(WKNavigationActionPolicyAllow, preferences);
};
[webView evaluateJavaScript:@"location.href = 'https://webkit.org/example_subframe'" inFrame:[webView firstChildFrame] completionHandler:nil];
EXPECT_WK_STREQ([webView _test_waitForAlert], "done");
EXPECT_EQ(true, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("security", [webView _webContentProcessVariantForFrame:nil].UTF8String);
EXPECT_STREQ("security", [webView _webContentProcessVariantForFrame:[webView firstChildFrame]._handle].UTF8String);
#endif
}
TEST(EnhancedSecurity, EnhancedSecurityNavigationStaysDisabledAfterSubFrameNavigationRequestEnabled)
{
HTTPServer server({
{ "/example"_s, { "<iframe id='webkit_frame' src='https://example.com/webkit'></iframe>"_s } },
{ "/example_subframe"_s, { "<script>alert('done')</script>"_s } },
{ "/webkit"_s, { "<html></html>"_s } }
}, HTTPServer::Protocol::HttpsProxy);
auto webViewConfiguration = server.httpsProxyConfiguration();
[webViewConfiguration.processPool _setObject:@"WebProcessPlugInWithInternals" forBundleParameter:TestWebKitAPI::Util::TestPlugInClassNameParameter];
webViewConfiguration.defaultWebpagePreferences._enhancedSecurityEnabled = NO;
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration]);
auto delegate = adoptNS([TestNavigationDelegate new]);
[delegate allowAnyTLSCertificate];
[webView setNavigationDelegate:delegate.get()];
__block bool finishedNavigation = false;
delegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
finishedNavigation = true;
};
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://example.com/example"]]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(false, isEnhancedSecurityEnabled(webView.get()));
finishedNavigation = false;
delegate.get().decidePolicyForNavigationActionWithPreferences = ^(WKNavigationAction *action, WKWebpagePreferences *preferences, void (^completionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
EXPECT_FALSE(preferences._enhancedSecurityEnabled);
EXPECT_FALSE(action.sourceFrame.isMainFrame);
preferences._enhancedSecurityEnabled = YES;
completionHandler(WKNavigationActionPolicyAllow, preferences);
};
[webView evaluateJavaScript:@"location.href = 'https://example.com/example_subframe'" inFrame:[webView firstChildFrame] completionHandler:nil];
EXPECT_WK_STREQ([webView _test_waitForAlert], "done");
EXPECT_EQ(false, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("standard", [webView _webContentProcessVariantForFrame:nil].UTF8String);
EXPECT_STREQ("standard", [webView _webContentProcessVariantForFrame:[webView firstChildFrame]._handle].UTF8String);
#endif
}
TEST(EnhancedSecurity, EnhancedSecurityNavigationStaysDisabledAfterSubFrameNavigationRequestEnabledCrossOrigin)
{
HTTPServer server({
{ "/example"_s, { "<iframe id='webkit_frame' src='https://example.com/webkit'></iframe>"_s } },
{ "/example_subframe"_s, { "<script>alert('done')</script>"_s } },
{ "/webkit"_s, { "<html></html>"_s } }
}, HTTPServer::Protocol::HttpsProxy);
auto webViewConfiguration = server.httpsProxyConfiguration();
[webViewConfiguration.processPool _setObject:@"WebProcessPlugInWithInternals" forBundleParameter:TestWebKitAPI::Util::TestPlugInClassNameParameter];
webViewConfiguration.defaultWebpagePreferences._enhancedSecurityEnabled = NO;
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration]);
auto delegate = adoptNS([TestNavigationDelegate new]);
[delegate allowAnyTLSCertificate];
[webView setNavigationDelegate:delegate.get()];
__block bool finishedNavigation = false;
delegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
finishedNavigation = true;
};
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://example.com/example"]]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(false, isEnhancedSecurityEnabled(webView.get()));
finishedNavigation = false;
delegate.get().decidePolicyForNavigationActionWithPreferences = ^(WKNavigationAction *action, WKWebpagePreferences *preferences, void (^completionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
EXPECT_FALSE(preferences._enhancedSecurityEnabled);
EXPECT_FALSE(action.sourceFrame.isMainFrame);
preferences._enhancedSecurityEnabled = YES;
completionHandler(WKNavigationActionPolicyAllow, preferences);
};
[webView evaluateJavaScript:@"location.href = 'https://webkit.org/example_subframe'" inFrame:[webView firstChildFrame] completionHandler:nil];
EXPECT_WK_STREQ([webView _test_waitForAlert], "done");
EXPECT_EQ(false, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("standard", [webView _webContentProcessVariantForFrame:nil].UTF8String);
EXPECT_STREQ("standard", [webView _webContentProcessVariantForFrame:[webView firstChildFrame]._handle].UTF8String);
#endif
}
TEST(EnhancedSecurity, WindowOpenWithNoopenerFromEnhancedSecurityPage)
{
HTTPServer server({
{ "/example"_s, { "<script>w = window.open('https://webkit.org/webkit', '_blank', 'noopener')</script>"_s } },
{ "/webkit"_s, { "hi"_s } },
}, HTTPServer::Protocol::HttpsProxy);
auto webViewConfiguration = server.httpsProxyConfiguration();
webViewConfiguration.defaultWebpagePreferences._enhancedSecurityEnabled = YES;
webViewConfiguration.preferences.javaScriptCanOpenWindowsAutomatically = YES;
auto openerWebView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration]);
auto openerDelegate = adoptNS([TestNavigationDelegate new]);
[openerDelegate allowAnyTLSCertificate];
[openerWebView setNavigationDelegate:openerDelegate.get()];
__block RetainPtr<WKWebView> openedWebView;
auto uiDelegate = adoptNS([TestUIDelegate new]);
uiDelegate.get().createWebViewWithConfiguration = ^(WKWebViewConfiguration *configuration, WKNavigationAction *, WKWindowFeatures *) {
openedWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
auto openedDelegate = adoptNS([TestNavigationDelegate new]);
[openedDelegate allowAnyTLSCertificate];
[openedWebView setNavigationDelegate:openedDelegate.get()];
return openedWebView.get();
};
[openerWebView setUIDelegate:uiDelegate.get()];
[openerWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://example.com/example"]]];
[openerDelegate waitForDidFinishNavigation];
while (!openedWebView)
TestWebKitAPI::Util::spinRunLoop();
EXPECT_EQ(true, isEnhancedSecurityEnabled(openedWebView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("security", [openedWebView _webContentProcessVariantForFrame:nil].UTF8String);
#endif
bool hasOpener = [[openedWebView objectByEvaluatingJavaScript:@"!!window.opener"] boolValue];
EXPECT_FALSE(hasOpener);
}
TEST(EnhancedSecurity, WindowOpenWithOpenerFromEnhancedSecurityPage)
{
HTTPServer server({
{ "/example"_s, { "<script>w = window.open('https://webkit.org/webkit')</script>"_s } },
{ "/webkit"_s, { "hi"_s } },
}, HTTPServer::Protocol::HttpsProxy);
auto webViewConfiguration = server.httpsProxyConfiguration();
webViewConfiguration.defaultWebpagePreferences._enhancedSecurityEnabled = YES;
webViewConfiguration.preferences.javaScriptCanOpenWindowsAutomatically = YES;
auto openerWebView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration]);
auto openerDelegate = adoptNS([TestNavigationDelegate new]);
[openerDelegate allowAnyTLSCertificate];
[openerWebView setNavigationDelegate:openerDelegate.get()];
__block RetainPtr<WKWebView> openedWebView;
auto uiDelegate = adoptNS([TestUIDelegate new]);
uiDelegate.get().createWebViewWithConfiguration = ^(WKWebViewConfiguration *configuration, WKNavigationAction *, WKWindowFeatures *) {
openedWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
auto openedDelegate = adoptNS([TestNavigationDelegate new]);
[openedDelegate allowAnyTLSCertificate];
[openedWebView setNavigationDelegate:openedDelegate.get()];
return openedWebView.get();
};
[openerWebView setUIDelegate:uiDelegate.get()];
[openerWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://example.com/example"]]];
[openerDelegate waitForDidFinishNavigation];
while (!openedWebView)
TestWebKitAPI::Util::spinRunLoop();
EXPECT_EQ(true, isEnhancedSecurityEnabled(openedWebView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("security", [openedWebView _webContentProcessVariantForFrame:nil].UTF8String);
EXPECT_EQ([openerWebView _webProcessIdentifier], [openedWebView _webProcessIdentifier]);
#endif
}
TEST(EnhancedSecurity, WindowOpenNoopenerFromEnhancedSecurityInheritsEnhancedSecurity)
{
HTTPServer server({
{ "/target"_s, { "target page"_s } },
{ "/opener"_s, { "<script>function openwithnoopener() {w = window.open('https://google.com/', '_blank', 'noopener')}</script>"_s } },
}, HTTPServer::Protocol::HttpsProxy);
auto processPoolConfiguration = psonProcessPoolConfiguration();
auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
auto standardConfig = server.httpsProxyConfiguration();
[standardConfig setProcessPool:processPool.get()];
standardConfig.defaultWebpagePreferences._enhancedSecurityEnabled = NO;
standardConfig.preferences.javaScriptCanOpenWindowsAutomatically = YES;
auto standardWebView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:standardConfig]);
auto standardDelegate = adoptNS([TestNavigationDelegate new]);
[standardDelegate allowAnyTLSCertificate];
[standardWebView setNavigationDelegate:standardDelegate.get()];
[standardWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://webkit.org/target"]]];
[standardDelegate waitForDidFinishNavigation];
EXPECT_EQ(false, isEnhancedSecurityEnabled(standardWebView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("standard", [standardWebView _webContentProcessVariantForFrame:nil].UTF8String);
#endif
pid_t standardPid = [standardWebView _webProcessIdentifier];
EXPECT_NE(standardPid, 0);
auto enhancedConfig = server.httpsProxyConfiguration();
[enhancedConfig setProcessPool:processPool.get()];
enhancedConfig.defaultWebpagePreferences._enhancedSecurityEnabled = YES;
enhancedConfig.preferences.javaScriptCanOpenWindowsAutomatically = YES;
auto openerWebView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 1, 1) configuration:enhancedConfig]);
auto openerDelegate = adoptNS([TestNavigationDelegate new]);
[openerDelegate allowAnyTLSCertificate];
[openerWebView setNavigationDelegate:openerDelegate.get()];
__block RetainPtr<WKWebView> openedWebView;
auto uiDelegate = adoptNS([TestUIDelegate new]);
uiDelegate.get().createWebViewWithConfiguration = ^(WKWebViewConfiguration *configuration, WKNavigationAction *, WKWindowFeatures *) {
openedWebView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 1, 1) configuration:configuration]);
auto openedDelegate = adoptNS([TestNavigationDelegate new]);
[openedDelegate allowAnyTLSCertificate];
[openedWebView setNavigationDelegate:openedDelegate.get()];
return openedWebView.get();
};
[openerWebView setUIDelegate:uiDelegate.get()];
[openerWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://example.com/opener"]]];
[openerDelegate waitForDidFinishNavigation];
[openerWebView evaluateJavaScript:@"openwithnoopener();" completionHandler:nil];
while (!openedWebView)
TestWebKitAPI::Util::spinRunLoop();
EXPECT_EQ(true, isEnhancedSecurityEnabled(openedWebView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("security", [openedWebView _webContentProcessVariantForFrame:nil].UTF8String);
EXPECT_NE(standardPid, [openedWebView _webProcessIdentifier]);
#endif
bool hasOpener = [[openedWebView objectByEvaluatingJavaScript:@"!!window.opener"] boolValue];
EXPECT_FALSE(hasOpener);
}
TEST(EnhancedSecurity, WindowOpenNoopenerFromStandardWithEnhancedSecurityViaDelegate)
{
HTTPServer server({
{ "/opener"_s, { "<script>function openwithnoopener() {w = window.open('https://webkit.org/opened', '_blank', 'noopener')}</script>"_s } },
{ "/opened"_s, { "opened page"_s } },
}, HTTPServer::Protocol::HttpsProxy);
auto processPoolConfiguration = psonProcessPoolConfiguration();
auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
auto standardConfig = server.httpsProxyConfiguration();
[standardConfig setProcessPool:processPool.get()];
standardConfig.defaultWebpagePreferences._enhancedSecurityEnabled = NO;
standardConfig.preferences.javaScriptCanOpenWindowsAutomatically = YES;
auto openerWebView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:standardConfig]);
auto openerDelegate = adoptNS([TestNavigationDelegate new]);
[openerDelegate allowAnyTLSCertificate];
[openerWebView setNavigationDelegate:openerDelegate.get()];
__block RetainPtr<WKWebView> openedWebView;
__block RetainPtr<TestNavigationDelegate> openedDelegate;
auto uiDelegate = adoptNS([TestUIDelegate new]);
uiDelegate.get().createWebViewWithConfiguration = ^(WKWebViewConfiguration *configuration, WKNavigationAction *, WKWindowFeatures *) {
openedWebView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
openedDelegate = adoptNS([TestNavigationDelegate new]);
[openedDelegate allowAnyTLSCertificate];
openedDelegate.get().decidePolicyForNavigationActionWithPreferences = ^(WKNavigationAction *action, WKWebpagePreferences *preferences, void (^completionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
preferences._enhancedSecurityEnabled = YES;
completionHandler(WKNavigationActionPolicyAllow, preferences);
};
[openedWebView setNavigationDelegate:openedDelegate.get()];
return openedWebView.get();
};
[openerWebView setUIDelegate:uiDelegate.get()];
[openerWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://example.com/opener"]]];
[openerDelegate waitForDidFinishNavigation];
EXPECT_EQ(false, isEnhancedSecurityEnabled(openerWebView.get()));
[openerWebView evaluateJavaScript:@"openwithnoopener();" completionHandler:nil];
while (!openedWebView)
TestWebKitAPI::Util::spinRunLoop();
[openedDelegate waitForDidFinishNavigation];
EXPECT_EQ(false, isEnhancedSecurityEnabled(openerWebView.get()));
EXPECT_EQ(true, isEnhancedSecurityEnabled(openedWebView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
pid_t openerPID = [openerWebView _webProcessIdentifier];
pid_t openedPID = [openedWebView _webProcessIdentifier];
bool isEnhanced = isEnhancedSecurityEnabled(openedWebView.get());
if (isEnhanced) {
EXPECT_STREQ("security", [openedWebView _webContentProcessVariantForFrame:nil].UTF8String);
EXPECT_NE(openerPID, openedPID);
} else
EXPECT_STREQ("standard", [openedWebView _webContentProcessVariantForFrame:nil].UTF8String);
#endif
bool hasOpener = [[openedWebView objectByEvaluatingJavaScript:@"!!window.opener"] boolValue];
EXPECT_FALSE(hasOpener);
}
TEST(EnhancedSecurity, WindowOpenNoopenerFromEnhancedSecurityWithStandardViaDelegate)
{
HTTPServer server({
{ "/opener"_s, { "<script>function openwithnoopener() {w = window.open('https://webkit.org/opened', '_blank', 'noopener')}</script>"_s } },
{ "/opened"_s, { "opened page"_s } },
}, HTTPServer::Protocol::HttpsProxy);
auto processPoolConfiguration = psonProcessPoolConfiguration();
auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
auto enhancedConfig = server.httpsProxyConfiguration();
[enhancedConfig setProcessPool:processPool.get()];
enhancedConfig.defaultWebpagePreferences._enhancedSecurityEnabled = YES;
enhancedConfig.preferences.javaScriptCanOpenWindowsAutomatically = YES;
auto openerWebView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:enhancedConfig]);
auto openerDelegate = adoptNS([TestNavigationDelegate new]);
[openerDelegate allowAnyTLSCertificate];
[openerWebView setNavigationDelegate:openerDelegate.get()];
__block RetainPtr<WKWebView> openedWebView;
__block RetainPtr<TestNavigationDelegate> openedDelegate;
auto uiDelegate = adoptNS([TestUIDelegate new]);
uiDelegate.get().createWebViewWithConfiguration = ^(WKWebViewConfiguration *configuration, WKNavigationAction *, WKWindowFeatures *) {
openedWebView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
openedDelegate = adoptNS([TestNavigationDelegate new]);
[openedDelegate allowAnyTLSCertificate];
openedDelegate.get().decidePolicyForNavigationActionWithPreferences = ^(WKNavigationAction *action, WKWebpagePreferences *preferences, void (^completionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
preferences._enhancedSecurityEnabled = NO;
completionHandler(WKNavigationActionPolicyAllow, preferences);
};
[openedWebView setNavigationDelegate:openedDelegate.get()];
return openedWebView.get();
};
[openerWebView setUIDelegate:uiDelegate.get()];
[openerWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://example.com/opener"]]];
[openerDelegate waitForDidFinishNavigation];
EXPECT_EQ(true, isEnhancedSecurityEnabled(openerWebView.get()));
[openerWebView evaluateJavaScript:@"openwithnoopener();" completionHandler:nil];
while (!openedWebView)
TestWebKitAPI::Util::spinRunLoop();
[openedDelegate waitForDidFinishNavigation];
EXPECT_EQ(true, isEnhancedSecurityEnabled(openerWebView.get()));
EXPECT_EQ(false, isEnhancedSecurityEnabled(openedWebView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
pid_t openerPID = [openerWebView _webProcessIdentifier];
EXPECT_STREQ("standard", [openedWebView _webContentProcessVariantForFrame:nil].UTF8String);
EXPECT_NE(openerPID, [openedWebView _webProcessIdentifier]);
#endif
bool hasOpener = [[openedWebView objectByEvaluatingJavaScript:@"!!window.opener"] boolValue];
EXPECT_FALSE(hasOpener);
}
TEST(EnhancedSecurity, LockdownModeTakesPrecedenceOverEnhancedSecurity)
{
auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
webViewConfiguration.get().defaultWebpagePreferences._enhancedSecurityEnabled = YES;
webViewConfiguration.get().defaultWebpagePreferences.lockdownModeEnabled = YES;
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 1, 1) configuration:webViewConfiguration.get()]);
NSURL *url = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
[webView _test_waitForDidFinishNavigation];
EXPECT_EQ(false, isJITEnabled(webView.get()));
EXPECT_EQ(false, isEnhancedSecurityEnabled(webView.get()));
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("lockdown", [webView _webContentProcessVariantForFrame:nil].UTF8String);
#endif
}
TEST(EnhancedSecurity, EnhancedSecurityRequestedWhenLockdownModeActive)
{
auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
webViewConfiguration.get().defaultWebpagePreferences.lockdownModeEnabled = YES;
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
auto delegate = adoptNS([TestNavigationDelegate new]);
[webView setNavigationDelegate:delegate.get()];
__block bool finishedNavigation = false;
delegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
finishedNavigation = true;
};
NSURL *url = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(false, isJITEnabled(webView.get()));
finishedNavigation = false;
delegate.get().decidePolicyForNavigationActionWithPreferences = ^(WKNavigationAction *action, WKWebpagePreferences *preferences, void (^completionHandler)(WKNavigationActionPolicy, WKWebpagePreferences *)) {
preferences._enhancedSecurityEnabled = YES;
completionHandler(WKNavigationActionPolicyAllow, preferences);
};
NSURL *url2 = [NSBundle.test_resourcesBundle URLForResource:@"simple2" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url2]];
TestWebKitAPI::Util::run(&finishedNavigation);
EXPECT_EQ(false, isJITEnabled(webView.get()));
EXPECT_EQ(false, isEnhancedSecurityEnabled(webView.get()));
EXPECT_EQ(true, webViewConfiguration.get().defaultWebpagePreferences.isLockdownModeEnabled);
// _webContentProcessVariantForFrame relies on private entitlements not available on public builds
#if USE(APPLE_INTERNAL_SDK)
EXPECT_STREQ("lockdown", [webView _webContentProcessVariantForFrame:nil].UTF8String);
#endif
}
#if HAVE(ENHANCED_SECURITY_WEB_CONTENT_PROCESS)
TEST(EnhancedSecurity, SystemLockdownModeEnablesEnhancedSecurityWhenAPIOptsOut)
{
[WKProcessPool _setCaptivePortalModeEnabledGloballyForTesting:YES];
auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
webViewConfiguration.get().defaultWebpagePreferences.securityRestrictionMode = WKSecurityRestrictionModeNone;
webViewConfiguration.get().defaultWebpagePreferences.lockdownModeEnabled = NO;
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
NSURL *url = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
[webView loadRequest:[NSURLRequest requestWithURL:url]];
[webView _test_waitForDidFinishNavigation];
EXPECT_EQ(false, isJITEnabled(webView.get()));
#if USE(APPLE_INTERNAL_SDK)
NSString *processVariant = [webView _webContentProcessVariantForFrame:nil];
EXPECT_STREQ("security", processVariant.UTF8String);
#endif
[WKProcessPool _clearCaptivePortalModeEnabledGloballyForTesting];
}
#endif
#endif
} // namespace TestWebKitAPI