blob: 44f6024b8abfeceac4d1d114b41eeec2b4d4e438 [file] [log] [blame]
/*
* Copyright (C) 2019 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"
#if PLATFORM(MAC)
#import "PlatformUtilities.h"
#import "Test.h"
#import "TestNavigationDelegate.h"
#import "TestURLSchemeHandler.h"
#import "TestWKWebView.h"
#import <WebKit/WKUIDelegatePrivate.h>
#import <WebKit/WKURLSchemeHandler.h>
#import <WebKit/WKURLSchemeTaskPrivate.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WebKit.h>
#import <wtf/BlockPtr.h>
#import <wtf/HashMap.h>
#import <wtf/RetainPtr.h>
#import <wtf/RunLoop.h>
#import <wtf/Threading.h>
#import <wtf/Vector.h>
#import <wtf/text/StringHash.h>
#import <wtf/text/WTFString.h>
static RetainPtr<WKWebView> createdWebView;
static RetainPtr<TestNavigationDelegate> navDelegate;
@interface JavascriptURLNavigationDelegate : NSObject <WKUIDelegatePrivate>
@end
@implementation JavascriptURLNavigationDelegate
- (void)_webViewRunModal:(WKWebView *)webView
{
EXPECT_EQ(webView, createdWebView.get());
}
- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
createdWebView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
[createdWebView setUIDelegate:self];
navDelegate = adoptNS([[TestNavigationDelegate alloc] init]);
[navDelegate setDecidePolicyForNavigationAction:[&] (WKNavigationAction *action, void (^decisionHandler)(WKNavigationActionPolicy)) {
decisionHandler(WKNavigationActionPolicyAllow);
}];
[createdWebView setNavigationDelegate:navDelegate.get()];
return createdWebView.get();
}
- (void)_webViewClose:(WKWebView *)webView
{
EXPECT_EQ(webView, createdWebView.get());
[webView _close];
}
@end
static const char* mainResource = R"JSURLRESOURCE(
<body>
The initial frame should have "Hello there" in it.<br>
The second frame should not.<br>
<script>
function createURL(data, type = 'text/html') {
return URL.createObjectURL(new Blob([data], {type: type}));
}
function waitForLoad() {
showModalDialog(createURL(`
<script>
var dataURLDelay = 400;
var earlyReturn = false;
function tryIt() {
if (earlyReturn)
return;
try {
opener.frame.contentDocument.x;
} catch (e) {
earlyReturn = true;
setTimeout(window.close, dataURLDelay * 1.5);
}
};
setTimeout(tryIt, dataURLDelay);
setTimeout(tryIt, dataURLDelay * 1.5);
setTimeout(tryIt, dataURLDelay * 2);
setTimeout(tryIt, dataURLDelay * 2.5);
setTimeout(window.close, dataURLDelay * 3);
</scrip` + 't>'
));
}
function runTest() {
window.onmessage = null;
frame = document.createElement('iframe');
frame.src = location;
document.body.appendChild(frame);
frame.contentDocument.open();
frame.contentWindow.addEventListener('readystatechange', () => {
a = frame.contentDocument.createElement('a');
a.href = targetURL;
a.click();
waitForLoad();
}, {capture: true, once: true});
var javascriptSource = `
<script>
alert(document.documentElement.outerHTML);
function checkIt() {
if (document.documentElement.outerHTML.includes('Hello worl' + 'd')) {
console.log('Failed');
if (window.webkit.messageHandlers && window.webkit.messageHandlers.testHandler)
window.webkit.messageHandlers.testHandler.postMessage('Failed');
} else {
console.log('Passed');
if (window.webkit.messageHandlers && window.webkit.messageHandlers.testHandler)
window.webkit.messageHandlers.testHandler.postMessage('Passed');
}
}
setTimeout(checkIt, 0);
</scrip` + 't>';
frame.src = 'javascript:"' + javascriptSource + '"';
}
window.onmessage = runTest;
var targetSource = `
<script>
function writeIt() {
document.write('Hello world');
parent.postMessage('go', '` + window.location.origin + `');
}
setTimeout(writeIt, 400);
</scrip` + 't>';
targetURL = 'data:text/html,' + targetSource;
loadedOnce = document.body.appendChild(document.createElement('iframe'));
loadedOnce.src = targetURL;
</script>
</body>
)JSURLRESOURCE";
TEST(WKWebView, JavascriptURLNavigation)
{
static bool done;
auto delegate = adoptNS([[JavascriptURLNavigationDelegate alloc] init]);
auto handler = adoptNS([[TestURLSchemeHandler alloc] init]);
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
[configuration setURLSchemeHandler:handler.get() forURLScheme:@"jsurl"];
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
[webView setUIDelegate:delegate.get()];
[webView performAfterReceivingMessage:@"Passed" action:^() {
done = true;
}];
[webView performAfterReceivingMessage:@"Failed" action:^() {
done = true;
FAIL();
}];
[handler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
if (![task.request.URL.absoluteString isEqualToString:@"jsurl://host1/main.html"]) {
// We only expect the URL above.
FAIL();
}
auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
[task didReceiveResponse:response.get()];
[task didReceiveData:[NSData dataWithBytes:mainResource length:strlen(mainResource)]];
[task didFinish];
}];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"jsurl://host1/main.html"]]];
TestWebKitAPI::Util::run(&done);
}
#endif // PLATFORM(MAC)