blob: bd8596a7ebbe019c65479e19b9ea4922c51531ac [file] [log] [blame] [edit]
/*
* 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"
#import "DragAndDropSimulator.h"
#import "HTTPServer.h"
#import "PlatformUtilities.h"
#import "Test.h"
#import "TestNavigationDelegate.h"
#import "TestProtocol.h"
#import "TestUIDelegate.h"
#import "TestWKWebView.h"
#import <WebKit/WKDragDestinationAction.h>
#import <WebKit/WKNavigationPrivate.h>
#import <WebKit/WKPreferencesPrivate.h>
#import <WebKit/WKWebView.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WKWebViewPrivate.h>
#import <WebKit/WKWebsiteDataStorePrivate.h>
#import <WebKit/_WKFeature.h>
#import <WebKit/_WKWebsiteDataStoreConfiguration.h>
#import <wtf/RetainPtr.h>
#import <wtf/text/WTFString.h>
static bool navigationComplete = false;
static bool navigationFail = false;
static String finalURL;
static id<WKNavigationDelegate> gDelegate;
static RetainPtr<WKWebView> newWebView;
@interface TestLoadWebArchiveNavigationDelegate : NSObject <WKNavigationDelegate, WKUIDelegate>
@end
@implementation TestLoadWebArchiveNavigationDelegate
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
navigationComplete = true;
finalURL = navigation._request.URL.lastPathComponent;
}
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
navigationFail = true;
finalURL = navigation._request.URL.lastPathComponent;
}
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
newWebView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration]);
[newWebView setNavigationDelegate:gDelegate];
return newWebView.get();
}
@end
namespace TestWebKitAPI {
TEST(LoadWebArchive, FailNavigation1)
{
// Using `document.location.href = 'helloworld.webarchive';`.
RetainPtr<NSURL> testURL = [NSBundle.test_resourcesBundle URLForResource:@"load-web-archive-1" withExtension:@"html"];
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
for (_WKFeature *feature in WKPreferences._features) {
NSString *key = feature.key;
if ([key isEqualToString:@"LoadWebArchiveWithEphemeralStorageEnabled"])
[[configuration preferences] _setEnabled:YES forFeature:feature];
}
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
auto delegate = adoptNS([[TestLoadWebArchiveNavigationDelegate alloc] init]);
[webView setNavigationDelegate:delegate.get()];
navigationFail = false;
[webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
Util::run(&navigationFail);
EXPECT_WK_STREQ(finalURL, "helloworld.webarchive");
}
TEST(LoadWebArchive, FailNavigation2)
{
// Using `window.open('helloworld.webarchive');`.
RetainPtr<NSURL> testURL = [NSBundle.test_resourcesBundle URLForResource:@"load-web-archive-2" withExtension:@"html"];
auto delegate = adoptNS([[TestLoadWebArchiveNavigationDelegate alloc] init]);
gDelegate = delegate.get();
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
for (_WKFeature *feature in WKPreferences._features) {
NSString *key = feature.key;
if ([key isEqualToString:@"LoadWebArchiveWithEphemeralStorageEnabled"])
[[configuration preferences] _setEnabled:YES forFeature:feature];
}
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
[webView setNavigationDelegate:delegate.get()];
[webView setUIDelegate:delegate.get()];
navigationFail = false;
[webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
Util::run(&navigationFail);
EXPECT_WK_STREQ(finalURL, "helloworld.webarchive");
}
TEST(LoadWebArchive, ClientNavigationSucceed)
{
RetainPtr<NSURL> testURL = [NSBundle.test_resourcesBundle URLForResource:@"helloworld" withExtension:@"webarchive"];
auto webView = adoptNS([[WKWebView alloc] init]);
auto delegate = adoptNS([[TestLoadWebArchiveNavigationDelegate alloc] init]);
[webView setNavigationDelegate:delegate.get()];
navigationComplete = false;
[webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, "helloworld.webarchive");
}
TEST(LoadWebArchive, ClientNavigationSucceedWithCookie)
{
RetainPtr<NSURL> testURL = [NSBundle.test_resourcesBundle URLForResource:@"helloworld" withExtension:@"webarchive"];
RetainPtr<WKWebsiteDataStore> dataStore = WKWebsiteDataStore.nonPersistentDataStore;
auto configuration = adoptNS([WKWebViewConfiguration new]);
[configuration setWebsiteDataStore:dataStore.get()];
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
auto delegate = adoptNS([[TestLoadWebArchiveNavigationDelegate alloc] init]);
[webView setNavigationDelegate:delegate.get()];
__block bool doneSettingCookie { false };
RetainPtr<NSHTTPCookie> cookie1 = [NSHTTPCookie cookieWithProperties:@{
NSHTTPCookiePath: @"/",
NSHTTPCookieName: @"CookieName",
NSHTTPCookieValue: @"CookieValue",
NSHTTPCookieDomain: @".www.webkit.org",
NSHTTPCookieSecure: @"TRUE",
NSHTTPCookieDiscard: @"TRUE",
NSHTTPCookieMaximumAge: @"10000",
}];
[dataStore.get().httpCookieStore setCookie:cookie1.get() completionHandler:^() {
doneSettingCookie = true;
}];
TestWebKitAPI::Util::run(&doneSettingCookie);
navigationComplete = false;
[webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, "helloworld.webarchive");
}
TEST(LoadWebArchive, ClientNavigationReload)
{
RetainPtr<NSURL> testURL = [NSBundle.test_resourcesBundle URLForResource:@"helloworld" withExtension:@"webarchive"];
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
for (_WKFeature *feature in WKPreferences._features) {
NSString *key = feature.key;
if ([key isEqualToString:@"LoadWebArchiveWithEphemeralStorageEnabled"])
[[configuration preferences] _setEnabled:YES forFeature:feature];
}
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
auto delegate = adoptNS([[TestLoadWebArchiveNavigationDelegate alloc] init]);
[webView setNavigationDelegate:delegate.get()];
navigationComplete = false;
[webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, "helloworld.webarchive");
navigationComplete = false;
[webView reload];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, "");
}
TEST(LoadWebArchive, ClientNavigationWithStorageReload)
{
RetainPtr<NSURL> testURL = [NSBundle.test_resourcesBundle URLForResource:@"helloworld" withExtension:@"webarchive"];
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
for (_WKFeature *feature in WKPreferences._features) {
NSString *key = feature.key;
if ([key isEqualToString:@"LoadWebArchiveWithEphemeralStorageEnabled"])
[[configuration preferences] _setEnabled:YES forFeature:feature];
}
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
auto delegate = adoptNS([[TestLoadWebArchiveNavigationDelegate alloc] init]);
[webView setNavigationDelegate:delegate.get()];
navigationComplete = false;
[webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, "helloworld.webarchive");
__block bool doneEvaluatingJavaScript { false };
[webView evaluateJavaScript:@"localStorage.setItem(\"key\", \"value\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
[webView evaluateJavaScript:@"localStorage.getItem(\"key\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSString class]]);
EXPECT_WK_STREQ(@"value", value);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
navigationComplete = false;
[webView reload];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, "");
[webView evaluateJavaScript:@"localStorage.getItem(\"key\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSString class]]);
EXPECT_WK_STREQ(@"value", value);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
}
TEST(LoadWebArchive, DragNavigationSucceed)
{
RetainPtr<NSURL> webArchiveURL = [NSBundle.test_resourcesBundle URLForResource:@"helloworld" withExtension:@"webarchive"];
RetainPtr<NSURL> simpleURL = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
[pasteboard clearContents];
[pasteboard declareTypes:@[NSFilenamesPboardType] owner:nil];
[pasteboard setPropertyList:@[webArchiveURL.get().path] forType:NSFilenamesPboardType];
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
for (_WKFeature *feature in WKPreferences._features) {
NSString *key = feature.key;
if ([key isEqualToString:@"LoadWebArchiveWithEphemeralStorageEnabled"])
[[configuration preferences] _setEnabled:YES forFeature:feature];
}
auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get()]);
[simulator setExternalDragPasteboard:pasteboard];
[simulator setDragDestinationAction:WKDragDestinationActionAny];
auto webView = [simulator webView];
auto delegate = adoptNS([[TestLoadWebArchiveNavigationDelegate alloc] init]);
[webView setNavigationDelegate:delegate.get()];
navigationComplete = false;
[webView loadRequest:[NSURLRequest requestWithURL:simpleURL.get()]];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, "simple.html");
navigationComplete = false;
[simulator runFrom:CGPointMake(0, 0) to:CGPointMake(50, 50)];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, "helloworld.webarchive");
}
TEST(LoadWebArchive, DragNavigationReload)
{
RetainPtr<NSURL> webArchiveURL = [NSBundle.test_resourcesBundle URLForResource:@"helloworld" withExtension:@"webarchive"];
RetainPtr<NSURL> simpleURL = [NSBundle.test_resourcesBundle URLForResource:@"simple" withExtension:@"html"];
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
[pasteboard clearContents];
[pasteboard declareTypes:@[NSFilenamesPboardType] owner:nil];
[pasteboard setPropertyList:@[webArchiveURL.get().path] forType:NSFilenamesPboardType];
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
for (_WKFeature *feature in WKPreferences._features) {
NSString *key = feature.key;
if ([key isEqualToString:@"LoadWebArchiveWithEphemeralStorageEnabled"])
[[configuration preferences] _setEnabled:YES forFeature:feature];
}
auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get()]);
[simulator setExternalDragPasteboard:pasteboard];
[simulator setDragDestinationAction:WKDragDestinationActionAny];
auto webView = [simulator webView];
auto delegate = adoptNS([[TestLoadWebArchiveNavigationDelegate alloc] init]);
[webView setNavigationDelegate:delegate.get()];
navigationComplete = false;
[webView loadRequest:[NSURLRequest requestWithURL:simpleURL.get()]];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, "simple.html");
navigationComplete = false;
[simulator runFrom:CGPointMake(0, 0) to:CGPointMake(50, 50)];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, "helloworld.webarchive");
navigationComplete = false;
[webView reload];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, "");
}
static NSData* constructArchive()
{
NSString *js = @"alert('loaded http subresource successfully')";
auto response = adoptNS([[NSURLResponse alloc] initWithURL:[NSURL URLWithString:@"http://download.example/script.js"] MIMEType:@"application/javascript" expectedContentLength:js.length textEncodingName:@"utf-8"]);
auto responseArchiver = adoptNS([[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]);
[responseArchiver encodeObject:response.get() forKey:@"WebResourceResponse"];
NSDictionary *archive = @{
@"WebMainResource": @{
@"WebResourceData": [@"<script src='script.js'></script>" dataUsingEncoding:NSUTF8StringEncoding],
@"WebResourceFrameName": @"",
@"WebResourceMIMEType": @"text/html",
@"WebResourceTextEncodingName": @"UTF-8",
@"WebResourceURL": @"http://download.example/",
},
@"WebSubresources": @[@{
@"WebResourceData": [js dataUsingEncoding:NSUTF8StringEncoding],
@"WebResourceMIMEType": @"application/javascript",
@"WebResourceResponse": responseArchiver.get().encodedData,
@"WebResourceTextEncodingName": @"utf-8",
@"WebResourceURL": @"http://download.example/script.js",
}]
};
return [NSPropertyListSerialization dataFromPropertyList:archive format:NSPropertyListBinaryFormat_v1_0 errorDescription:nil];
}
TEST(LoadWebArchive, HTTPSUpgrade)
{
NSData *data = constructArchive();
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
for (_WKFeature *feature in WKPreferences._features) {
NSString *key = feature.key;
if ([key isEqualToString:@"LoadWebArchiveWithEphemeralStorageEnabled"])
[[configuration preferences] _setEnabled:YES forFeature:feature];
}
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
[webView loadData:data MIMEType:@"application/x-webarchive" characterEncodingName:@"utf-8" baseURL:[NSURL URLWithString:@"http://download.example/"]];
EXPECT_WK_STREQ([webView _test_waitForAlert], "loaded http subresource successfully");
}
TEST(LoadWebArchive, DisallowedNetworkHosts)
{
NSData *data = constructArchive();
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
configuration.get()._allowedNetworkHosts = [NSSet set];
for (_WKFeature *feature in WKPreferences._features) {
NSString *key = feature.key;
if ([key isEqualToString:@"LoadWebArchiveWithEphemeralStorageEnabled"])
[[configuration preferences] _setEnabled:YES forFeature:feature];
}
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
[webView loadData:data MIMEType:@"application/x-webarchive" characterEncodingName:@"utf-8" baseURL:[NSURL URLWithString:@"http://download.example/"]];
EXPECT_WK_STREQ([webView _test_waitForAlert], "loaded http subresource successfully");
}
TEST(LoadWebArchive, SiteToWebArchiveAndBack)
{
using namespace TestWebKitAPI;
HTTPServer server({
{ "http://download.example/"_s, { "<body>/</body>"_s } },
{ "http://download.example/page1.html"_s, { "<body>page1</body>"_s } },
}, HTTPServer::Protocol::Http);
auto storeConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] initNonPersistentConfiguration]);
[storeConfiguration setProxyConfiguration:@{
(NSString *)kCFStreamPropertyHTTPProxyHost: @"127.0.0.1",
(NSString *)kCFStreamPropertyHTTPProxyPort: @(server.port())
}];
auto dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:storeConfiguration.get()]);
auto configuration = adoptNS([WKWebViewConfiguration new]);
[configuration setWebsiteDataStore:dataStore.get()];
for (_WKFeature *feature in WKPreferences._features) {
NSString *key = feature.key;
if ([key isEqualToString:@"LoadWebArchiveWithEphemeralStorageEnabled"])
[[configuration preferences] _setEnabled:YES forFeature:feature];
}
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
auto delegate = adoptNS([[TestLoadWebArchiveNavigationDelegate alloc] init]);
[webView setNavigationDelegate:delegate.get()];
navigationComplete = false;
RetainPtr<NSURL> webArchiveURL = [NSBundle.test_resourcesBundle URLForResource:@"download.example" withExtension:@"webarchive"];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://download.example/page1.html"]]];
Util::run(&navigationComplete);
EXPECT_WK_STREQ([webView URL].absoluteString, @"http://download.example/page1.html");
navigationComplete = false;
__block bool doneEvaluatingJavaScript { false };
[webView evaluateJavaScript:@"localStorage.setItem(\"key\", \"value\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
[webView evaluateJavaScript:@"localStorage.getItem(\"key\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSString class]]);
EXPECT_WK_STREQ(@"value", value);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
[webView loadFileURL:webArchiveURL.get() allowingReadAccessToURL:webArchiveURL.get()];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, @"download.example.webarchive");
navigationComplete = false;
[webView evaluateJavaScript:@"location.href" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSString class]]);
EXPECT_WK_STREQ(@"http://download.example/", value);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
EXPECT_TRUE([webView canGoBack]);
[webView evaluateJavaScript:@"localStorage.getItem(\"key\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSNull class]]);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://download.example/page1.html"]]];
Util::run(&navigationComplete);
EXPECT_WK_STREQ([webView URL].absoluteString, @"http://download.example/page1.html");
navigationComplete = false;
[webView evaluateJavaScript:@"localStorage.getItem(\"key\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_FALSE([value isKindOfClass:[NSNull class]]);
EXPECT_TRUE([value isKindOfClass:[NSString class]]);
EXPECT_WK_STREQ(@"value", value);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
}
TEST(LoadWebArchive, WebArchiveToSiteAndBack)
{
using namespace TestWebKitAPI;
HTTPServer server({
{ "http://download.example/"_s, { "<body>/</body>"_s } },
{ "http://download.example/page1.html"_s, { "<body>page1</body>"_s } },
}, HTTPServer::Protocol::Http);
auto storeConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] initNonPersistentConfiguration]);
[storeConfiguration setProxyConfiguration:@{
(NSString *)kCFStreamPropertyHTTPProxyHost: @"127.0.0.1",
(NSString *)kCFStreamPropertyHTTPProxyPort: @(server.port())
}];
auto dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:storeConfiguration.get()]);
auto configuration = adoptNS([WKWebViewConfiguration new]);
[configuration setWebsiteDataStore:dataStore.get()];
for (_WKFeature *feature in WKPreferences._features) {
NSString *key = feature.key;
if ([key isEqualToString:@"LoadWebArchiveWithEphemeralStorageEnabled"])
[[configuration preferences] _setEnabled:YES forFeature:feature];
}
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
auto delegate = adoptNS([[TestLoadWebArchiveNavigationDelegate alloc] init]);
[webView setNavigationDelegate:delegate.get()];
navigationComplete = false;
RetainPtr<NSURL> webArchiveURL = [NSBundle.test_resourcesBundle URLForResource:@"download.example" withExtension:@"webarchive"];
[webView loadFileURL:webArchiveURL.get() allowingReadAccessToURL:webArchiveURL.get()];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, @"download.example.webarchive");
navigationComplete = false;
__block bool doneEvaluatingJavaScript { false };
[webView evaluateJavaScript:@"location.href" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSString class]]);
EXPECT_WK_STREQ(@"http://download.example/", value);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
[webView evaluateJavaScript:@"localStorage.setItem(\"key\", \"value\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
[webView evaluateJavaScript:@"localStorage.getItem(\"key\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSString class]]);
EXPECT_WK_STREQ(@"value", value);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
[webView evaluateJavaScript:@"let anchor = document.createElement('a'); anchor.href = \"http://download.example/page1.html\"; anchor.click();" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
Util::run(&navigationComplete);
EXPECT_WK_STREQ([webView URL].absoluteString, @"http://download.example/page1.html");
navigationComplete = false;
[webView evaluateJavaScript:@"localStorage.getItem(\"key\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSNull class]]);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
WKBackForwardList *list = [webView backForwardList];
EXPECT_WK_STREQ(@"http://download.example/page1.html", [list.currentItem.URL absoluteString]);
EXPECT_EQ((NSUInteger)1, list.backList.count);
EXPECT_EQ((NSUInteger)0, list.forwardList.count);
EXPECT_TRUE([webView canGoBack]);
[webView goBack];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, @"download.example.webarchive");
navigationComplete = false;
[webView evaluateJavaScript:@"location.href" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSString class]]);
EXPECT_WK_STREQ(@"http://download.example/", value);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
[webView evaluateJavaScript:@"localStorage.getItem(\"key\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_FALSE([value isKindOfClass:[NSNull class]]);
EXPECT_TRUE([value isKindOfClass:[NSString class]]);
EXPECT_WK_STREQ(@"value", value);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
}
TEST(LoadWebArchive, FileWebArchiveToDataWebArchiveAndBack)
{
auto configuration = adoptNS([WKWebViewConfiguration new]);
for (_WKFeature *feature in WKPreferences._features) {
NSString *key = feature.key;
if ([key isEqualToString:@"LoadWebArchiveWithEphemeralStorageEnabled"])
[[configuration preferences] _setEnabled:YES forFeature:feature];
}
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
auto delegate = adoptNS([[TestLoadWebArchiveNavigationDelegate alloc] init]);
[webView setNavigationDelegate:delegate.get()];
navigationComplete = false;
RetainPtr<NSURL> webArchiveURL = [NSBundle.test_resourcesBundle URLForResource:@"download.example" withExtension:@"webarchive"];
[webView loadFileURL:webArchiveURL.get() allowingReadAccessToURL:webArchiveURL.get()];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, @"download.example.webarchive");
navigationComplete = false;
__block bool doneEvaluatingJavaScript { false };
[webView evaluateJavaScript:@"location.href" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSString class]]);
EXPECT_WK_STREQ(@"http://download.example/", value);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
[webView evaluateJavaScript:@"localStorage.setItem(\"key\", \"value\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
[webView evaluateJavaScript:@"localStorage.getItem(\"key\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSString class]]);
EXPECT_WK_STREQ(@"value", value);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
NSData *data = constructArchive();
[webView loadData:data MIMEType:@"application/x-webarchive" characterEncodingName:@"utf-8" baseURL:[NSURL URLWithString:@"http://download.example/"]];
Util::run(&navigationComplete);
EXPECT_WK_STREQ([webView URL].absoluteString, @"http://download.example/");
navigationComplete = false;
[webView evaluateJavaScript:@"localStorage.getItem(\"key\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSNull class]]);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
[webView loadFileURL:webArchiveURL.get() allowingReadAccessToURL:webArchiveURL.get()];
Util::run(&navigationComplete);
EXPECT_WK_STREQ(finalURL, @"download.example.webarchive");
navigationComplete = false;
[webView evaluateJavaScript:@"location.href" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSString class]]);
EXPECT_WK_STREQ(@"http://download.example/", value);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
[webView evaluateJavaScript:@"localStorage.getItem(\"key\");" completionHandler:^(id value, NSError *error) {
EXPECT_NULL(error);
EXPECT_TRUE([value isKindOfClass:[NSNull class]]);
doneEvaluatingJavaScript = true;
}];
TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
doneEvaluatingJavaScript = false;
}
TEST(LoadWebArchive, PreferCachedImageSourceOverBrokenImage)
{
[TestProtocol registerWithScheme:@"http"];
RetainPtr archiveData = [] {
RetainPtr sourceView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600)]);
[sourceView _setOverrideDeviceScaleFactor:1];
[sourceView synchronouslyLoadHTMLString:@"<!DOCTYPE html>"
"<html>"
" <meta name='viewport' content='width=device-width, initial-scale=1'>"
" <body>"
" <picture>"
" <img src='http://bundle-file/400x400-green.png'"
" srcset='http://bundle-file/400x400-green.png 1x,http://bundle-file/large-red-square.png 2x' />"
" </picture>"
" </body>"
"</html>"];
RetainPtr result = [sourceView contentsAsWebArchive];
[sourceView _killWebContentProcessAndResetState];
return result;
}();
[TestProtocol unregister];
RetainPtr configuration = adoptNS([WKWebViewConfiguration new]);
[configuration setWebsiteDataStore:WKWebsiteDataStore.nonPersistentDataStore];
[configuration _setAllowedNetworkHosts:NSSet.set];
RetainPtr delegate = adoptNS([TestNavigationDelegate new]);
RetainPtr webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
[webView setNavigationDelegate:delegate.get()];
[webView _setOverrideDeviceScaleFactor:2];
[webView loadData:archiveData.get() MIMEType:@"application/x-webarchive" characterEncodingName:@"" baseURL:[NSURL URLWithString:@""]];
[delegate waitForDidFinishNavigation];
NSArray<NSNumber *> *dimensions = [webView objectByEvaluatingJavaScript:@"const image = document.images[0]; [image.naturalWidth, image.naturalHeight];"];
auto naturalWidth = dimensions.firstObject.intValue;
auto naturalHeight = dimensions.lastObject.intValue;
EXPECT_EQ(naturalWidth, 400);
EXPECT_EQ(naturalHeight, 400);
}
TEST(LoadWebArchive, FailNavigationFromNonClientOrUserInitiatedWindowOpen)
{
RetainPtr configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
[[configuration preferences] setJavaScriptCanOpenWindowsAutomatically:YES];
for (_WKFeature *feature in WKPreferences._features) {
NSString *key = feature.key;
if ([key isEqualToString:@"LoadWebArchiveWithEphemeralStorageEnabled"])
[[configuration preferences] _setEnabled:YES forFeature:feature];
}
RetainPtr navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]);
__block bool failed = false;
__block bool finished = false;
navigationDelegate.get().didFailProvisionalNavigation = ^(WKWebView *, WKNavigation *, NSError *error) {
failed = true;
finished = true;
};
navigationDelegate.get().didFinishNavigation = ^(WKWebView *, WKNavigation *) {
finished = true;
};
RetainPtr uiDelegate = adoptNS([[TestUIDelegate alloc] init]);
__block RetainPtr<WKWebView> openedWebView;
uiDelegate.get().createWebViewWithConfiguration = ^(WKWebViewConfiguration *configuration, WKNavigationAction *action, WKWindowFeatures *windowFeatures) {
openedWebView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectZero configuration:configuration]);
openedWebView.get().navigationDelegate = navigationDelegate.get();
openedWebView.get().UIDelegate = uiDelegate.get();
return openedWebView.get();
};
RetainPtr webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
[webView setNavigationDelegate:navigationDelegate.get()];
[webView setUIDelegate:uiDelegate.get()];
[webView evaluateJavaScript:@"window.open('file:///usr/local/lib/WebKitAdditions.resources/iframe.webarchive', '_blank', 'noopener');" completionHandler:^(id, NSError *error) {
EXPECT_NULL(error);
}];
Util::run(&finished);
EXPECT_TRUE(failed);
}
} // namespace TestWebKitAPI