Add SPI to restrict loading to main resources or non-network loads
https://bugs.webkit.org/show_bug.cgi?id=209893
Patch by Alex Christensen <achristensen@webkit.org> on 2020-04-02
Reviewed by Tim Horton.
Source/WebCore:
This will allow two projects that currently use the injected bundle SPI to use these instead.
Covered by API tests.
* Modules/websockets/ThreadableWebSocketChannel.cpp:
(WebCore::ThreadableWebSocketChannel::validateURL):
* loader/ResourceLoadNotifier.cpp:
(WebCore::ResourceLoadNotifier::assignIdentifierToInitialRequest):
(WebCore::ResourceLoadNotifier::dispatchWillSendRequest):
* loader/ResourceLoadNotifier.h:
* page/Page.cpp:
(WebCore::m_loadsFromNetwork):
(WebCore::m_deviceOrientationUpdateProvider): Deleted.
* page/Page.h:
(WebCore::Page::loadsSubresources const):
(WebCore::Page::loadsFromNetwork const):
* page/PageConfiguration.h:
Source/WebKit:
* Shared/WebPageCreationParameters.cpp:
(WebKit::WebPageCreationParameters::encode const):
(WebKit::WebPageCreationParameters::decode):
* Shared/WebPageCreationParameters.h:
* UIProcess/API/APIPageConfiguration.cpp:
(API::PageConfiguration::copy const):
* UIProcess/API/APIPageConfiguration.h:
(API::PageConfiguration::loadsSubresources const):
(API::PageConfiguration::setLoadsSubresources):
(API::PageConfiguration::loadsFromNetwork const):
(API::PageConfiguration::setLoadsFromNetwork):
* UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
(-[WKWebViewConfiguration _setLoadsFromNetwork:]):
(-[WKWebViewConfiguration _loadsFromNetwork]):
(-[WKWebViewConfiguration _setLoadsSubresources:]):
(-[WKWebViewConfiguration _loadsSubresources]):
* UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
* UIProcess/WebPageProxy.cpp:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::m_processDisplayName):
Tools:
* TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm:
* TestWebKitAPI/cocoa/HTTPServer.h:
(TestWebKitAPI::HTTPServer::totalRequests const):
* TestWebKitAPI/cocoa/HTTPServer.mm:
(TestWebKitAPI::HTTPServer::respondToRequests):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@259392 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 2e860dc..e24cff7 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,27 @@
+2020-04-02 Alex Christensen <achristensen@webkit.org>
+
+ Add SPI to restrict loading to main resources or non-network loads
+ https://bugs.webkit.org/show_bug.cgi?id=209893
+
+ Reviewed by Tim Horton.
+
+ This will allow two projects that currently use the injected bundle SPI to use these instead.
+ Covered by API tests.
+
+ * Modules/websockets/ThreadableWebSocketChannel.cpp:
+ (WebCore::ThreadableWebSocketChannel::validateURL):
+ * loader/ResourceLoadNotifier.cpp:
+ (WebCore::ResourceLoadNotifier::assignIdentifierToInitialRequest):
+ (WebCore::ResourceLoadNotifier::dispatchWillSendRequest):
+ * loader/ResourceLoadNotifier.h:
+ * page/Page.cpp:
+ (WebCore::m_loadsFromNetwork):
+ (WebCore::m_deviceOrientationUpdateProvider): Deleted.
+ * page/Page.h:
+ (WebCore::Page::loadsSubresources const):
+ (WebCore::Page::loadsFromNetwork const):
+ * page/PageConfiguration.h:
+
2020-04-02 Eric Carlson <eric.carlson@apple.com>
[iOS] Allow WebKit to use camera in multi-tasking mode
diff --git a/Source/WebCore/Modules/websockets/ThreadableWebSocketChannel.cpp b/Source/WebCore/Modules/websockets/ThreadableWebSocketChannel.cpp
index fb6d885..62bfe17 100644
--- a/Source/WebCore/Modules/websockets/ThreadableWebSocketChannel.cpp
+++ b/Source/WebCore/Modules/websockets/ThreadableWebSocketChannel.cpp
@@ -82,8 +82,10 @@
Optional<ThreadableWebSocketChannel::ValidatedURL> ThreadableWebSocketChannel::validateURL(Document& document, const URL& requestedURL)
{
ValidatedURL validatedURL { requestedURL, true };
-#if ENABLE(CONTENT_EXTENSIONS)
if (auto* page = document.page()) {
+ if (!page->loadsFromNetwork())
+ return { };
+#if ENABLE(CONTENT_EXTENSIONS)
if (auto* documentLoader = document.loader()) {
auto results = page->userContentProvider().processContentRuleListsForLoad(validatedURL.url, ContentExtensions::ResourceType::Raw, *documentLoader);
if (results.summary.blockedLoad)
@@ -94,10 +96,10 @@
}
validatedURL.areCookiesAllowed = !results.summary.blockedCookies;
}
- }
#else
- UNUSED_PARAM(document);
+ UNUSED_PARAM(document);
#endif
+ }
return validatedURL;
}
diff --git a/Source/WebCore/loader/ResourceLoadNotifier.cpp b/Source/WebCore/loader/ResourceLoadNotifier.cpp
index 812e2744a..0b6f788 100644
--- a/Source/WebCore/loader/ResourceLoadNotifier.cpp
+++ b/Source/WebCore/loader/ResourceLoadNotifier.cpp
@@ -109,6 +109,13 @@
void ResourceLoadNotifier::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
{
+ bool pageIsProvisionallyLoading = false;
+ if (auto* frameLoader = loader ? loader->frameLoader() : nullptr)
+ pageIsProvisionallyLoading = frameLoader->provisionalDocumentLoader() == loader;
+
+ if (pageIsProvisionallyLoading)
+ m_initialRequestIdentifier = identifier;
+
m_frame.loader().client().assignIdentifierToInitialRequest(identifier, loader, request);
}
@@ -126,6 +133,14 @@
if (m_frame.loader().documentLoader())
m_frame.loader().documentLoader()->didTellClientAboutLoad(request.url());
+ if (auto* page = m_frame.page()) {
+ if (!page->loadsSubresources()) {
+ if (!m_frame.isMainFrame() || (m_initialRequestIdentifier && *m_initialRequestIdentifier != identifier))
+ request = { };
+ } else if (!page->loadsFromNetwork() && request.url().protocolIsInHTTPFamily())
+ request = { };
+ }
+
// Notifying the FrameLoaderClient may cause the frame to be destroyed.
Ref<Frame> protect(m_frame);
m_frame.loader().client().dispatchWillSendRequest(loader, identifier, request, redirectResponse);
diff --git a/Source/WebCore/loader/ResourceLoadNotifier.h b/Source/WebCore/loader/ResourceLoadNotifier.h
index e0e6a48..6b17d25 100644
--- a/Source/WebCore/loader/ResourceLoadNotifier.h
+++ b/Source/WebCore/loader/ResourceLoadNotifier.h
@@ -67,6 +67,7 @@
private:
Frame& m_frame;
+ Optional<unsigned long> m_initialRequestIdentifier;
};
} // namespace WebCore
diff --git a/Source/WebCore/page/Page.cpp b/Source/WebCore/page/Page.cpp
index 9f0a406..90e75d5 100644
--- a/Source/WebCore/page/Page.cpp
+++ b/Source/WebCore/page/Page.cpp
@@ -290,6 +290,8 @@
#if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY)
, m_deviceOrientationUpdateProvider(WTFMove(pageConfiguration.deviceOrientationUpdateProvider))
#endif
+ , m_loadsSubresources(pageConfiguration.loadsSubresources)
+ , m_loadsFromNetwork(pageConfiguration.loadsFromNetwork)
{
updateTimerThrottlingState();
diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h
index e2484f6..b34455d 100644
--- a/Source/WebCore/page/Page.h
+++ b/Source/WebCore/page/Page.h
@@ -702,6 +702,9 @@
bool isOnlyNonUtilityPage() const;
bool isUtilityPage() const { return m_isUtilityPage; }
+ bool loadsSubresources() const { return m_loadsSubresources; }
+ bool loadsFromNetwork() const { return m_loadsFromNetwork; }
+
bool isLowPowerModeEnabled() const;
WEBCORE_EXPORT void setLowPowerModeEnabledOverrideForTesting(Optional<bool>);
@@ -1010,6 +1013,8 @@
Vector<UserContentURLPattern> m_corsDisablingPatterns;
Vector<UserStyleSheet> m_userStyleSheetsPendingInjection;
bool m_shouldFireResizeEvents { true };
+ bool m_loadsSubresources { true };
+ bool m_loadsFromNetwork { true };
};
inline PageGroup& Page::group()
diff --git a/Source/WebCore/page/PageConfiguration.h b/Source/WebCore/page/PageConfiguration.h
index 369f063..ee7457c 100644
--- a/Source/WebCore/page/PageConfiguration.h
+++ b/Source/WebCore/page/PageConfiguration.h
@@ -127,6 +127,8 @@
#endif
Vector<String> corsDisablingPatterns;
UniqueRef<MediaRecorderProvider> mediaRecorderProvider;
+ bool loadsSubresources { true };
+ bool loadsFromNetwork { true };
};
}
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 012895a..80d21b6 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,31 @@
+2020-04-02 Alex Christensen <achristensen@webkit.org>
+
+ Add SPI to restrict loading to main resources or non-network loads
+ https://bugs.webkit.org/show_bug.cgi?id=209893
+
+ Reviewed by Tim Horton.
+
+ * Shared/WebPageCreationParameters.cpp:
+ (WebKit::WebPageCreationParameters::encode const):
+ (WebKit::WebPageCreationParameters::decode):
+ * Shared/WebPageCreationParameters.h:
+ * UIProcess/API/APIPageConfiguration.cpp:
+ (API::PageConfiguration::copy const):
+ * UIProcess/API/APIPageConfiguration.h:
+ (API::PageConfiguration::loadsSubresources const):
+ (API::PageConfiguration::setLoadsSubresources):
+ (API::PageConfiguration::loadsFromNetwork const):
+ (API::PageConfiguration::setLoadsFromNetwork):
+ * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
+ (-[WKWebViewConfiguration _setLoadsFromNetwork:]):
+ (-[WKWebViewConfiguration _loadsFromNetwork]):
+ (-[WKWebViewConfiguration _setLoadsSubresources:]):
+ (-[WKWebViewConfiguration _loadsSubresources]):
+ * UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
+ * UIProcess/WebPageProxy.cpp:
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::m_processDisplayName):
+
2020-04-02 youenn fablet <youenn@apple.com>
Debug crash: ASSERTION FAILED: m_ongoingFetches.contains(task.fetchIdentifier())
diff --git a/Source/WebKit/Shared/WebPageCreationParameters.cpp b/Source/WebKit/Shared/WebPageCreationParameters.cpp
index 8937b26..87725f1 100644
--- a/Source/WebKit/Shared/WebPageCreationParameters.cpp
+++ b/Source/WebKit/Shared/WebPageCreationParameters.cpp
@@ -133,6 +133,8 @@
encoder << oldPageID;
encoder << overriddenMediaType;
encoder << corsDisablingPatterns;
+ encoder << loadsSubresources;
+ encoder << loadsFromNetwork;
encoder << crossOriginAccessControlCheckEnabled;
encoder << processDisplayName;
@@ -416,6 +418,18 @@
return WTF::nullopt;
parameters.corsDisablingPatterns = WTFMove(*corsDisablingPatterns);
+ Optional<bool> loadsSubresources;
+ decoder >> loadsSubresources;
+ if (!loadsSubresources)
+ return WTF::nullopt;
+ parameters.loadsSubresources = *loadsSubresources;
+
+ Optional<bool> loadsFromNetwork;
+ decoder >> loadsFromNetwork;
+ if (!loadsFromNetwork)
+ return WTF::nullopt;
+ parameters.loadsFromNetwork = *loadsFromNetwork;
+
Optional<bool> crossOriginAccessControlCheckEnabled;
decoder >> crossOriginAccessControlCheckEnabled;
if (!crossOriginAccessControlCheckEnabled)
diff --git a/Source/WebKit/Shared/WebPageCreationParameters.h b/Source/WebKit/Shared/WebPageCreationParameters.h
index b47560e..736cba3 100644
--- a/Source/WebKit/Shared/WebPageCreationParameters.h
+++ b/Source/WebKit/Shared/WebPageCreationParameters.h
@@ -202,6 +202,9 @@
String overriddenMediaType;
Vector<String> corsDisablingPatterns;
+ bool loadsSubresources { true };
+ bool loadsFromNetwork { true };
+
bool crossOriginAccessControlCheckEnabled { true };
String processDisplayName;
diff --git a/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp b/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp
index d091765..c8d10b7 100644
--- a/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp
+++ b/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp
@@ -95,6 +95,8 @@
copy->m_processDisplayName = this->m_processDisplayName;
copy->m_ignoresAppBoundDomains = this->m_ignoresAppBoundDomains;
+ copy->m_loadsSubresources = this->m_loadsSubresources;
+ copy->m_loadsFromNetwork = this->m_loadsFromNetwork;
return copy;
}
diff --git a/Source/WebKit/UIProcess/API/APIPageConfiguration.h b/Source/WebKit/UIProcess/API/APIPageConfiguration.h
index eec7f19..ff58c91 100644
--- a/Source/WebKit/UIProcess/API/APIPageConfiguration.h
+++ b/Source/WebKit/UIProcess/API/APIPageConfiguration.h
@@ -149,7 +149,13 @@
bool ignoresAppBoundDomains() const { return m_ignoresAppBoundDomains; }
void setIgnoresAppBoundDomains(bool shouldIgnore) { m_ignoresAppBoundDomains = shouldIgnore; }
-
+
+ bool loadsSubresources() const { return m_loadsSubresources; }
+ void setLoadsSubresources(bool loads) { m_loadsSubresources = loads; }
+
+ bool loadsFromNetwork() const { return m_loadsFromNetwork; }
+ void setLoadsFromNetwork(bool loads) { m_loadsFromNetwork = loads; }
+
private:
RefPtr<WebKit::WebProcessPool> m_processPool;
@@ -191,6 +197,8 @@
WTF::String m_processDisplayName;
WebKit::WebViewCategory m_webViewCategory { WebKit::WebViewCategory::AppBoundDomain };
bool m_ignoresAppBoundDomains { false };
+ bool m_loadsSubresources { true };
+ bool m_loadsFromNetwork { true };
};
} // namespace API
diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm b/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm
index 8539a2a..d44ed2b 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm
@@ -913,6 +913,26 @@
_pageConfiguration->setCORSDisablingPatterns(WTFMove(vector));
}
+- (void)_setLoadsFromNetwork:(BOOL)loads
+{
+ _pageConfiguration->setLoadsFromNetwork(loads);
+}
+
+- (BOOL)_loadsFromNetwork
+{
+ return _pageConfiguration->loadsFromNetwork();
+}
+
+- (void)_setLoadsSubresources:(BOOL)loads
+{
+ _pageConfiguration->setLoadsSubresources(loads);
+}
+
+- (BOOL)_loadsSubresources
+{
+ return _pageConfiguration->loadsSubresources();
+}
+
- (void)_setCrossOriginAccessControlCheckEnabled:(BOOL)enabled
{
_pageConfiguration->setCrossOriginAccessControlCheckEnabled(enabled);
diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h b/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h
index 68b6eb6..12a7c2d 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h
+++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h
@@ -86,6 +86,9 @@
@property (nonatomic, copy, setter=_setCORSDisablingPatterns:) NSArray<NSString *> *_corsDisablingPatterns WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
@property (nonatomic, setter=_setCrossOriginAccessControlCheckEnabled:) BOOL _crossOriginAccessControlCheckEnabled WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+@property (nonatomic, setter=_setLoadsFromNetwork:) BOOL _loadsFromNetwork WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+@property (nonatomic, setter=_setLoadsSubresources:) BOOL _loadsSubresources WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
#if TARGET_OS_IPHONE
@property (nonatomic, setter=_setClientNavigationsRunAtForegroundPriority:) BOOL _clientNavigationsRunAtForegroundPriority WK_API_AVAILABLE(ios(WK_IOS_TBA));
@property (nonatomic, setter=_setAlwaysRunsAtForegroundPriority:) BOOL _alwaysRunsAtForegroundPriority WK_API_AVAILABLE(ios(9_0));
diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp
index 0208a87..efa2ba4 100644
--- a/Source/WebKit/UIProcess/WebPageProxy.cpp
+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp
@@ -7781,6 +7781,8 @@
parameters.overriddenMediaType = m_overriddenMediaType;
parameters.corsDisablingPatterns = m_configuration->corsDisablingPatterns();
+ parameters.loadsFromNetwork = m_configuration->loadsFromNetwork();
+ parameters.loadsSubresources = m_configuration->loadsSubresources();
parameters.crossOriginAccessControlCheckEnabled = m_configuration->crossOriginAccessControlCheckEnabled();
parameters.hasResourceLoadClient = !!m_resourceLoadClient;
diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp
index 224384a..b7889d8 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp
@@ -529,6 +529,9 @@
#endif
pageConfiguration.corsDisablingPatterns = WTFMove(parameters.corsDisablingPatterns);
+ pageConfiguration.loadsSubresources = parameters.loadsSubresources;
+ pageConfiguration.loadsFromNetwork = parameters.loadsFromNetwork;
+
if (!parameters.crossOriginAccessControlCheckEnabled)
CrossOriginAccessControlCheckDisabler::singleton().setCrossOriginAccessControlCheckEnabled(false);
diff --git a/Tools/ChangeLog b/Tools/ChangeLog
index a2ac238..a5386d6 100644
--- a/Tools/ChangeLog
+++ b/Tools/ChangeLog
@@ -1,3 +1,16 @@
+2020-04-02 Alex Christensen <achristensen@webkit.org>
+
+ Add SPI to restrict loading to main resources or non-network loads
+ https://bugs.webkit.org/show_bug.cgi?id=209893
+
+ Reviewed by Tim Horton.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm:
+ * TestWebKitAPI/cocoa/HTTPServer.h:
+ (TestWebKitAPI::HTTPServer::totalRequests const):
+ * TestWebKitAPI/cocoa/HTTPServer.mm:
+ (TestWebKitAPI::HTTPServer::respondToRequests):
+
2020-04-02 Kate Cheney <katherine_cheney@apple.com>
Add additional WKAppBoundDomains to TestWebKitAPI's expectations after initializing eTLD+1 by default
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm
index da9217e..e4e807a 100644
--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm
+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm
@@ -1004,6 +1004,118 @@
EXPECT_FALSE(loadFail);
}
+TEST(URLSchemeHandler, LoadsFromNetwork)
+{
+ TestWebKitAPI::HTTPServer server({
+ { "/", { {{ "Access-Control-Allow-Origin", "*" }}, "test content" } }
+ });
+
+ bool loadSuccess = false;
+ bool loadFail = false;
+ bool done = false;
+
+ auto handler = adoptNS([TestURLSchemeHandler new]);
+
+ WKWebViewConfiguration *configuration = [[[WKWebViewConfiguration alloc] init] autorelease];
+ [configuration setURLSchemeHandler:handler.get() forURLScheme:@"test"];
+
+ [handler setStartURLSchemeTaskHandler:[&](WKWebView *, id<WKURLSchemeTask> task) {
+ if ([task.request.URL.path isEqualToString:@"/main.html"]) {
+ NSData *data = [[NSString stringWithFormat:@"<script>"
+ "fetch('http://127.0.0.1:%d/').then(()=>{"
+ "fetch('/loadSuccess')"
+ "}).catch(()=>{"
+ "var ws = new WebSocket('ws://127.0.0.1:%d');"
+ "ws.onerror = function() { fetch('/loadFail') };"
+ "})"
+ "</script>", server.port(), server.port()] dataUsingEncoding:NSUTF8StringEncoding];
+ [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:data.length textEncodingName:nil] autorelease]];
+ [task didReceiveData:data];
+ [task didFinish];
+ } else if ([task.request.URL.path isEqualToString:@"/loadSuccess"]) {
+ loadSuccess = true;
+ done = true;
+ } else if ([task.request.URL.path isEqualToString:@"/loadFail"]) {
+ loadFail = true;
+ done = true;
+ } else
+ ASSERT_NOT_REACHED();
+ }];
+
+ {
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration]);
+ [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test://host1/main.html"]]];
+ TestWebKitAPI::Util::run(&done);
+ }
+ EXPECT_TRUE(loadSuccess);
+ EXPECT_FALSE(loadFail);
+ EXPECT_EQ(server.totalRequests(), 1u);
+
+ loadSuccess = false;
+ loadFail = false;
+ done = false;
+
+ configuration._loadsFromNetwork = NO;
+ {
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration]);
+ [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test://host1/main.html"]]];
+ TestWebKitAPI::Util::run(&done);
+ }
+ EXPECT_FALSE(loadSuccess);
+ EXPECT_TRUE(loadFail);
+ EXPECT_EQ(server.totalRequests(), 1u);
+}
+
+TEST(URLSchemeHandler, LoadsSubresources)
+{
+ bool loadedImage = false;
+ bool loadedIFrame = false;
+
+ auto handler = adoptNS([TestURLSchemeHandler new]);
+
+ WKWebViewConfiguration *configuration = [[[WKWebViewConfiguration alloc] init] autorelease];
+ [configuration setURLSchemeHandler:handler.get() forURLScheme:@"test"];
+
+ [handler setStartURLSchemeTaskHandler:[&](WKWebView *, id<WKURLSchemeTask> task) {
+ NSString *response = nil;
+ if ([task.request.URL.path isEqualToString:@"/main.html"])
+ response = @"<img src='/imgsrc'></img><iframe src='/iframesrc'></iframe>";
+ else if ([task.request.URL.path isEqualToString:@"/imgsrc"]) {
+ response = @"image content";
+ loadedImage = true;
+ } else if ([task.request.URL.path isEqualToString:@"/iframesrc"]) {
+ response = @"iframe content";
+ loadedIFrame = true;
+ } else
+ ASSERT_NOT_REACHED();
+ [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:response.length textEncodingName:nil] autorelease]];
+ [task didReceiveData:[response dataUsingEncoding:NSUTF8StringEncoding]];
+ [task didFinish];
+ }];
+
+ {
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration]);
+ [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test://host1/main.html"]]];
+ TestWebKitAPI::Util::run(&loadedImage);
+ TestWebKitAPI::Util::run(&loadedIFrame);
+ }
+
+ loadedImage = false;
+ loadedIFrame = false;
+
+ configuration._loadsSubresources = NO;
+ {
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration]);
+ auto delegate = adoptNS([TestNavigationDelegate new]);
+ webView.get().navigationDelegate = delegate.get();
+ [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test://host1/main.html"]]];
+ [delegate waitForDidFinishNavigation];
+ TestWebKitAPI::Util::spinRunLoop(100);
+ EXPECT_FALSE(loadedIFrame);
+ EXPECT_FALSE(loadedImage);
+ }
+}
+
#endif // HAVE(NETWORK_FRAMEWORK)
@interface FrameSchemeHandler : NSObject <WKURLSchemeHandler>
diff --git a/Tools/TestWebKitAPI/cocoa/HTTPServer.h b/Tools/TestWebKitAPI/cocoa/HTTPServer.h
index 1a1c074..89f173d 100644
--- a/Tools/TestWebKitAPI/cocoa/HTTPServer.h
+++ b/Tools/TestWebKitAPI/cocoa/HTTPServer.h
@@ -43,6 +43,7 @@
HTTPServer(std::initializer_list<std::pair<String, HTTPResponse>>, Protocol = Protocol::Http);
uint16_t port() const;
NSURLRequest *request() const;
+ size_t totalRequests() const { return m_totalRequests; }
private:
void respondToRequests(nw_connection_t);
@@ -50,6 +51,7 @@
RetainPtr<nw_listener_t> m_listener;
const Protocol m_protocol;
const HashMap<String, HTTPResponse> m_requestResponseMap;
+ size_t m_totalRequests { 0 };
};
struct HTTPServer::HTTPResponse {
diff --git a/Tools/TestWebKitAPI/cocoa/HTTPServer.mm b/Tools/TestWebKitAPI/cocoa/HTTPServer.mm
index 0cc950b..c62cfda 100644
--- a/Tools/TestWebKitAPI/cocoa/HTTPServer.mm
+++ b/Tools/TestWebKitAPI/cocoa/HTTPServer.mm
@@ -100,6 +100,8 @@
});
request.append('\0');
+ m_totalRequests++;
+
const char* getPathPrefix = "GET ";
const char* postPathPrefix = "POST ";
const char* pathSuffix = " HTTP/1.1\r\n";