/* * 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 #if WK_API_ENABLED #if PLATFORM(MAC) // No downloading on iOS #import "PlatformUtilities.h" #import "Test.h" #import #import #import #import #import #import #import #import #import static bool isDone; 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 { 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_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(_expectedContentLength) == _receivedContentLength); EXPECT_TRUE([[NSFileManager defaultManager] contentsEqualAtPath:_destinationPath andPath:[sourceURL path]]); WebCore::deleteFile(_destinationPath); isDone = true; } @end TEST(_WKDownload, DownloadDelegate) { RetainPtr 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 navigationDelegate, id <_WKDownloadDelegate> downloadDelegate, NSURL *url) { RetainPtr webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]); [webView setNavigationDelegate:navigationDelegate]; [[[webView configuration] processPool] _setDownloadDelegate:downloadDelegate]; isDone = false; [webView loadRequest:[NSURLRequest requestWithURL:url]]; TestWebKitAPI::Util::run(&isDone); } @interface DownloadNavigationDelegate : NSObject @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 @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 _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 navigationDelegate = adoptNS([[DownloadNavigationDelegate alloc] init]); RetainPtr downloadDelegate; { RetainPtr 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 @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); } #endif #endif