blob: 9670058cadda7b8982062368480cadd74a887587 [file] [log] [blame] [edit]
/*
* Copyright (C) 2014 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 <WebKit/WKFoundation.h>
#if WK_API_ENABLED
#if PLATFORM(MAC) // No downloading on iOS
#import "PlatformUtilities.h"
#import "Test.h"
#import <WebCore/FileSystem.h>
#import <WebKit/_WKDownload.h>
#import <WebKit/_WKDownloadDelegate.h>
#import <WebKit/WKNavigationDelegatePrivate.h>
#import <WebKit/WKProcessPoolPrivate.h>
#import <WebKit/WKWebView.h>
#import <WebKit/WKWebViewConfiguration.h>
#import <wtf/RetainPtr.h>
#import <wtf/text/WTFString.h>
static bool isDone;
static bool hasReceivedResponse;
static NSURL *sourceURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
@interface DownloadDelegate : NSObject <_WKDownloadDelegate>
@end
@implementation DownloadDelegate {
RetainPtr<_WKDownload> _download;
String _destinationPath;
long long _expectedContentLength;
uint64_t _receivedContentLength;
}
- (void)_downloadDidStart:(_WKDownload *)download
{
EXPECT_NULL(_download);
EXPECT_NOT_NULL(download);
EXPECT_TRUE([[[[download request] URL] path] isEqualToString:[sourceURL path]]);
_download = download;
}
- (void)_download:(_WKDownload *)download didReceiveResponse:(NSURLResponse *)response
{
hasReceivedResponse = true;
EXPECT_EQ(_download, download);
EXPECT_TRUE(_expectedContentLength == 0);
EXPECT_TRUE(_receivedContentLength == 0);
EXPECT_TRUE([[[response URL] path] isEqualToString:[sourceURL path]]);
_expectedContentLength = [response expectedContentLength];
}
- (void)_download:(_WKDownload *)download didReceiveData:(uint64_t)length
{
EXPECT_EQ(_download, download);
_receivedContentLength += length;
}
- (NSString *)_download:(_WKDownload *)download decideDestinationWithSuggestedFilename:(NSString *)filename allowOverwrite:(BOOL *)allowOverwrite
{
EXPECT_TRUE(hasReceivedResponse);
EXPECT_EQ(_download, download);
WebCore::PlatformFileHandle fileHandle;
_destinationPath = WebCore::openTemporaryFile("TestWebKitAPI", fileHandle);
EXPECT_TRUE(fileHandle != WebCore::invalidPlatformFileHandle);
WebCore::closeFile(fileHandle);
*allowOverwrite = YES;
return _destinationPath;
}
- (void)_downloadDidFinish:(_WKDownload *)download
{
EXPECT_EQ(_download, download);
EXPECT_TRUE(_expectedContentLength == NSURLResponseUnknownLength || static_cast<uint64_t>(_expectedContentLength) == _receivedContentLength);
EXPECT_TRUE([[NSFileManager defaultManager] contentsEqualAtPath:_destinationPath andPath:[sourceURL path]]);
WebCore::deleteFile(_destinationPath);
isDone = true;
}
@end
TEST(_WKDownload, DownloadDelegate)
{
RetainPtr<WKProcessPool> processPool = adoptNS([[WKProcessPool alloc] init]);
DownloadDelegate *downloadDelegate = [[DownloadDelegate alloc] init];
[processPool _setDownloadDelegate:downloadDelegate];
@autoreleasepool {
EXPECT_EQ(downloadDelegate, [processPool _downloadDelegate]);
}
[downloadDelegate release];
EXPECT_NULL([processPool _downloadDelegate]);
}
static void runTest(id <WKNavigationDelegate> navigationDelegate, id <_WKDownloadDelegate> downloadDelegate, NSURL *url)
{
RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
[webView setNavigationDelegate:navigationDelegate];
[[[webView configuration] processPool] _setDownloadDelegate:downloadDelegate];
isDone = false;
hasReceivedResponse = false;
[webView loadRequest:[NSURLRequest requestWithURL:url]];
TestWebKitAPI::Util::run(&isDone);
}
@interface DownloadNavigationDelegate : NSObject <WKNavigationDelegate>
@end
@implementation DownloadNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
decisionHandler(_WKNavigationActionPolicyDownload);
}
@end
TEST(_WKDownload, DownloadRequest)
{
runTest(adoptNS([[DownloadNavigationDelegate alloc] init]).get(), adoptNS([[DownloadDelegate alloc] init]).get(), sourceURL);
}
@interface ConvertResponseToDownloadNavigationDelegate : NSObject <WKNavigationDelegate>
@end
@implementation ConvertResponseToDownloadNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
decisionHandler(_WKNavigationResponsePolicyBecomeDownload);
}
@end
TEST(_WKDownload, ConvertResponseToDownload)
{
runTest(adoptNS([[ConvertResponseToDownloadNavigationDelegate alloc] init]).get(), adoptNS([[DownloadDelegate alloc] init]).get(), sourceURL);
}
@interface FailingDownloadDelegate : NSObject <_WKDownloadDelegate>
@end
@implementation FailingDownloadDelegate
- (void)_downloadDidFinish:(_WKDownload *)download
{
EXPECT_TRUE(false);
isDone = true;
}
- (void)_download:(_WKDownload *)download didFailWithError:(NSError *)error
{
isDone = true;
}
- (void)_downloadDidCancel:(_WKDownload *)download
{
EXPECT_TRUE(false);
isDone = true;
}
@end
TEST(_WKDownload, DownloadMissingResource)
{
runTest(adoptNS([[DownloadNavigationDelegate alloc] init]).get(), adoptNS([[FailingDownloadDelegate alloc] init]).get(), [NSURL URLWithString:@"non-existant-scheme://"]);
}
@interface CancelledDownloadDelegate : NSObject <_WKDownloadDelegate>
@end
@implementation CancelledDownloadDelegate
- (void)_downloadDidStart:(_WKDownload *)download
{
[download cancel];
}
- (void)_downloadDidFinish:(_WKDownload *)download
{
EXPECT_TRUE(false);
isDone = true;
}
- (void)_download:(_WKDownload *)download didFailWithError:(NSError *)error
{
EXPECT_TRUE(false);
isDone = true;
}
- (void)_downloadDidCancel:(_WKDownload *)download
{
isDone = true;
}
@end
TEST(_WKDownload, CancelDownload)
{
runTest(adoptNS([[DownloadNavigationDelegate alloc] init]).get(), adoptNS([[CancelledDownloadDelegate alloc] init]).get(), sourceURL);
}
@interface OriginatingWebViewDownloadDelegate : NSObject <_WKDownloadDelegate>
- (instancetype)initWithWebView:(WKWebView *)webView;
@end
@implementation OriginatingWebViewDownloadDelegate {
RetainPtr<WKWebView> _webView;
}
- (instancetype)initWithWebView:(WKWebView *)webView
{
if (!(self = [super init]))
return nil;
_webView = webView;
return self;
}
- (void)_downloadDidStart:(_WKDownload *)download
{
@autoreleasepool {
EXPECT_EQ([download originatingWebView], _webView);
}
_webView = nullptr;
EXPECT_NULL([download originatingWebView]);
isDone = true;
}
@end
TEST(_WKDownload, OriginatingWebView)
{
RetainPtr<DownloadNavigationDelegate> navigationDelegate = adoptNS([[DownloadNavigationDelegate alloc] init]);
RetainPtr<OriginatingWebViewDownloadDelegate> downloadDelegate;
{
RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
[webView setNavigationDelegate:navigationDelegate.get()];
downloadDelegate = adoptNS([[OriginatingWebViewDownloadDelegate alloc] initWithWebView:webView.get()]);
[[[webView configuration] processPool] _setDownloadDelegate:downloadDelegate.get()];
[webView loadRequest:[NSURLRequest requestWithURL:sourceURL]];
}
isDone = false;
TestWebKitAPI::Util::run(&isDone);
}
@interface DownloadRequestOriginalURLDelegate : NSObject <_WKDownloadDelegate>
- (instancetype)initWithExpectedOriginalURL:(NSURL *)expectOriginalURL;
@end
@implementation DownloadRequestOriginalURLDelegate {
NSURL *_expectedOriginalURL;
}
- (instancetype)initWithExpectedOriginalURL:(NSURL *)expectedOriginalURL
{
if (!(self = [super init]))
return nil;
_expectedOriginalURL = expectedOriginalURL;
return self;
}
- (void)_downloadDidStart:(_WKDownload *)download
{
if ([_expectedOriginalURL isEqual:sourceURL])
EXPECT_TRUE(!download.request.mainDocumentURL);
else
EXPECT_TRUE([_expectedOriginalURL isEqual:download.request.mainDocumentURL]);
isDone = true;
}
@end
@interface DownloadRequestOriginalURLNavigationDelegate : NSObject <WKNavigationDelegate>
@end
@implementation DownloadRequestOriginalURLNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
if ([navigationAction.request.URL isEqual:sourceURL])
decisionHandler(_WKNavigationActionPolicyDownload);
else
decisionHandler(WKNavigationActionPolicyAllow);
}
@end
TEST(_WKDownload, DownloadRequestOriginalURL)
{
NSURL *originalURL = [[NSBundle mainBundle] URLForResource:@"DownloadRequestOriginalURL" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
runTest(adoptNS([[DownloadRequestOriginalURLNavigationDelegate alloc] init]).get(), adoptNS([[DownloadRequestOriginalURLDelegate alloc] initWithExpectedOriginalURL:originalURL]).get(), originalURL);
}
TEST(_WKDownload, DownloadRequestOriginalURLFrame)
{
NSURL *originalURL = [[NSBundle mainBundle] URLForResource:@"DownloadRequestOriginalURL2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
runTest(adoptNS([[DownloadRequestOriginalURLNavigationDelegate alloc] init]).get(), adoptNS([[DownloadRequestOriginalURLDelegate alloc] initWithExpectedOriginalURL:originalURL]).get(), originalURL);
}
TEST(_WKDownload, DownloadRequestOriginalURLDirectDownload)
{
runTest(adoptNS([[DownloadRequestOriginalURLNavigationDelegate alloc] init]).get(), adoptNS([[DownloadRequestOriginalURLDelegate alloc] initWithExpectedOriginalURL:sourceURL]).get(), sourceURL);
}
TEST(_WKDownload, DownloadRequestOriginalURLDirectDownloadWithLoadedContent)
{
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
[webView setNavigationDelegate:[[DownloadRequestOriginalURLNavigationDelegate alloc] init]];
[[[webView configuration] processPool] _setDownloadDelegate:[[DownloadRequestOriginalURLDelegate alloc] initWithExpectedOriginalURL:sourceURL]];
NSURL *contentURL = [[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
// Here is to test if the original URL can be set correctly when the current document
// is completely unrelated to the download.
[webView loadRequest:[NSURLRequest requestWithURL:contentURL]];
[webView loadRequest:[NSURLRequest requestWithURL:sourceURL]];
isDone = false;
TestWebKitAPI::Util::run(&isDone);
}
@interface BlobDownloadDelegate : NSObject <_WKDownloadDelegate>
@end
@implementation BlobDownloadDelegate {
RetainPtr<_WKDownload> _download;
String _destinationPath;
long long _expectedContentLength;
uint64_t _receivedContentLength;
}
- (void)_downloadDidStart:(_WKDownload *)download
{
EXPECT_NULL(_download);
EXPECT_NOT_NULL(download);
EXPECT_TRUE([[[[download request] URL] scheme] isEqualToString:@"blob"]);
_download = download;
}
- (void)_download:(_WKDownload *)download didReceiveResponse:(NSURLResponse *)response
{
hasReceivedResponse = true;
EXPECT_EQ(_download, download);
EXPECT_EQ(_expectedContentLength, 0U);
EXPECT_EQ(_receivedContentLength, 0U);
EXPECT_TRUE([[[response URL] scheme] isEqualToString:@"blob"]);
_expectedContentLength = [response expectedContentLength];
}
- (void)_download:(_WKDownload *)download didReceiveData:(uint64_t)length
{
EXPECT_EQ(_download, download);
_receivedContentLength += length;
}
- (NSString *)_download:(_WKDownload *)download decideDestinationWithSuggestedFilename:(NSString *)filename allowOverwrite:(BOOL *)allowOverwrite
{
EXPECT_TRUE(hasReceivedResponse);
EXPECT_EQ(_download, download);
WebCore::PlatformFileHandle fileHandle;
_destinationPath = WebCore::openTemporaryFile("TestWebKitAPI", fileHandle);
EXPECT_TRUE(fileHandle != WebCore::invalidPlatformFileHandle);
WebCore::closeFile(fileHandle);
*allowOverwrite = YES;
return _destinationPath;
}
- (void)_downloadDidFinish:(_WKDownload *)download
{
EXPECT_EQ(_download, download);
EXPECT_TRUE(_expectedContentLength == NSURLResponseUnknownLength || static_cast<uint64_t>(_expectedContentLength) == _receivedContentLength);
NSString* expectedContent = @"{\"x\":42,\"s\":\"hello, world\"}";
NSData* expectedData = [expectedContent dataUsingEncoding:NSUTF8StringEncoding];
EXPECT_TRUE([[[NSFileManager defaultManager] contentsAtPath:_destinationPath] isEqualToData:expectedData]);
WebCore::deleteFile(_destinationPath);
isDone = true;
}
@end
@interface DownloadBlobURLNavigationDelegate : NSObject <WKNavigationDelegate>
@end
@implementation DownloadBlobURLNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
if ([navigationAction.request.URL.scheme isEqualToString:@"blob"])
decisionHandler(_WKNavigationActionPolicyDownload);
else
decisionHandler(WKNavigationActionPolicyAllow);
}
@end
TEST(_WKDownload, DownloadRequestBlobURL)
{
NSURL *originalURL = [[NSBundle mainBundle] URLForResource:@"DownloadRequestBlobURL" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
runTest(adoptNS([[DownloadBlobURLNavigationDelegate alloc] init]).get(), adoptNS([[BlobDownloadDelegate alloc] init]).get(), originalURL);
}
#endif
#endif