[Content Filtering] Determine navigation and content policy before continuing to...
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKit2Cocoa / Download.mm
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import <WebKit/WKFoundation.h>
28
29 #if WK_API_ENABLED
30 #if PLATFORM(MAC) // No downloading on iOS
31
32 #import "PlatformUtilities.h"
33 #import "Test.h"
34 #import <WebCore/FileSystem.h>
35 #import <WebKit/_WKDownload.h>
36 #import <WebKit/_WKDownloadDelegate.h>
37 #import <WebKit/WKNavigationDelegatePrivate.h>
38 #import <WebKit/WKProcessPoolPrivate.h>
39 #import <WebKit/WKWebView.h>
40 #import <WebKit/WKWebViewConfiguration.h>
41 #import <wtf/RetainPtr.h>
42 #import <wtf/text/WTFString.h>
43
44 static bool isDone;
45 static NSURL *sourceURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
46
47 @interface DownloadDelegate : NSObject <_WKDownloadDelegate>
48 @end
49
50 @implementation DownloadDelegate {
51     RetainPtr<_WKDownload> _download;
52     String _destinationPath;
53     long long _expectedContentLength;
54     uint64_t _receivedContentLength;
55 }
56
57 - (void)_downloadDidStart:(_WKDownload *)download
58 {
59     EXPECT_NULL(_download);
60     EXPECT_NOT_NULL(download);
61     EXPECT_TRUE([[[[download request] URL] path] isEqualToString:[sourceURL path]]);
62     _download = download;
63 }
64
65 - (void)_download:(_WKDownload *)download didReceiveResponse:(NSURLResponse *)response
66 {
67     EXPECT_EQ(_download, download);
68     EXPECT_TRUE(_expectedContentLength == 0);
69     EXPECT_TRUE(_receivedContentLength == 0);
70     EXPECT_TRUE([[[response URL] path] isEqualToString:[sourceURL path]]);
71     _expectedContentLength = [response expectedContentLength];
72 }
73
74 - (void)_download:(_WKDownload *)download didReceiveData:(uint64_t)length
75 {
76     EXPECT_EQ(_download, download);
77     _receivedContentLength += length;
78 }
79
80 - (NSString *)_download:(_WKDownload *)download decideDestinationWithSuggestedFilename:(NSString *)filename allowOverwrite:(BOOL *)allowOverwrite
81 {
82     EXPECT_EQ(_download, download);
83
84     WebCore::PlatformFileHandle fileHandle;
85     _destinationPath = WebCore::openTemporaryFile("TestWebKitAPI", fileHandle);
86     EXPECT_TRUE(fileHandle != WebCore::invalidPlatformFileHandle);
87     WebCore::closeFile(fileHandle);
88
89     *allowOverwrite = YES;
90     return _destinationPath;
91 }
92
93 - (void)_downloadDidFinish:(_WKDownload *)download
94 {
95     EXPECT_EQ(_download, download);
96     EXPECT_TRUE(_expectedContentLength == NSURLResponseUnknownLength || static_cast<uint64_t>(_expectedContentLength) == _receivedContentLength);
97     EXPECT_TRUE([[NSFileManager defaultManager] contentsEqualAtPath:_destinationPath andPath:[sourceURL path]]);
98     WebCore::deleteFile(_destinationPath);
99     isDone = true;
100 }
101
102 @end
103
104 TEST(_WKDownload, DownloadDelegate)
105 {
106     RetainPtr<WKProcessPool> processPool = adoptNS([[WKProcessPool alloc] init]);
107     DownloadDelegate *downloadDelegate = [[DownloadDelegate alloc] init];
108     [processPool _setDownloadDelegate:downloadDelegate];
109
110     @autoreleasepool {
111         EXPECT_EQ(downloadDelegate, [processPool _downloadDelegate]);
112     }
113
114     [downloadDelegate release];
115     EXPECT_NULL([processPool _downloadDelegate]);
116 }
117
118 static void runTest(id <WKNavigationDelegate> navigationDelegate, id <_WKDownloadDelegate> downloadDelegate, NSURL *url)
119 {
120     RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
121     [webView setNavigationDelegate:navigationDelegate];
122     [[[webView configuration] processPool] _setDownloadDelegate:downloadDelegate];
123
124     isDone = false;
125     [webView loadRequest:[NSURLRequest requestWithURL:url]];
126     TestWebKitAPI::Util::run(&isDone);
127 }
128
129 @interface DownloadNavigationDelegate : NSObject <WKNavigationDelegate>
130 @end
131
132 @implementation DownloadNavigationDelegate
133 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
134 {
135     decisionHandler(_WKNavigationActionPolicyDownload);
136 }
137 @end
138
139 TEST(_WKDownload, DownloadRequest)
140 {
141     runTest(adoptNS([[DownloadNavigationDelegate alloc] init]).get(), adoptNS([[DownloadDelegate alloc] init]).get(), sourceURL);
142 }
143
144 @interface ConvertResponseToDownloadNavigationDelegate : NSObject <WKNavigationDelegate>
145 @end
146
147 @implementation ConvertResponseToDownloadNavigationDelegate
148 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
149 {
150     decisionHandler(_WKNavigationResponsePolicyBecomeDownload);
151 }
152 @end
153
154 TEST(_WKDownload, ConvertResponseToDownload)
155 {
156     runTest(adoptNS([[ConvertResponseToDownloadNavigationDelegate alloc] init]).get(), adoptNS([[DownloadDelegate alloc] init]).get(), sourceURL);
157 }
158
159 @interface FailingDownloadDelegate : NSObject <_WKDownloadDelegate>
160 @end
161
162 @implementation FailingDownloadDelegate
163
164 - (void)_downloadDidFinish:(_WKDownload *)download
165 {
166     EXPECT_TRUE(false);
167     isDone = true;
168 }
169
170 - (void)_download:(_WKDownload *)download didFailWithError:(NSError *)error
171 {
172     isDone = true;
173 }
174
175 - (void)_downloadDidCancel:(_WKDownload *)download
176 {
177     EXPECT_TRUE(false);
178     isDone = true;
179 }
180
181 @end
182
183 TEST(_WKDownload, DownloadMissingResource)
184 {
185     runTest(adoptNS([[DownloadNavigationDelegate alloc] init]).get(), adoptNS([[FailingDownloadDelegate alloc] init]).get(), [NSURL URLWithString:@"non-existant-scheme://"]);
186 }
187
188 @interface CancelledDownloadDelegate : NSObject <_WKDownloadDelegate>
189 @end
190
191 @implementation CancelledDownloadDelegate
192
193 - (void)_downloadDidStart:(_WKDownload *)download
194 {
195     [download cancel];
196 }
197
198 - (void)_downloadDidFinish:(_WKDownload *)download
199 {
200     EXPECT_TRUE(false);
201     isDone = true;
202 }
203
204 - (void)_download:(_WKDownload *)download didFailWithError:(NSError *)error
205 {
206     EXPECT_TRUE(false);
207     isDone = true;
208 }
209
210 - (void)_downloadDidCancel:(_WKDownload *)download
211 {
212     isDone = true;
213 }
214
215 @end
216
217 TEST(_WKDownload, CancelDownload)
218 {
219     runTest(adoptNS([[DownloadNavigationDelegate alloc] init]).get(), adoptNS([[CancelledDownloadDelegate alloc] init]).get(), sourceURL);
220 }
221
222 @interface OriginatingWebViewDownloadDelegate : NSObject <_WKDownloadDelegate>
223 - (instancetype)initWithWebView:(WKWebView *)webView;
224 @end
225
226 @implementation OriginatingWebViewDownloadDelegate {
227     RetainPtr<WKWebView> _webView;
228 }
229
230 - (instancetype)initWithWebView:(WKWebView *)webView
231 {
232     if (!(self = [super init]))
233         return nil;
234
235     _webView = webView;
236     return self;
237 }
238
239 - (void)_downloadDidStart:(_WKDownload *)download
240 {
241     @autoreleasepool {
242         EXPECT_EQ([download originatingWebView], _webView);
243     }
244
245     _webView = nullptr;
246     EXPECT_NULL([download originatingWebView]);
247     isDone = true;
248 }
249
250 @end
251
252 TEST(_WKDownload, OriginatingWebView)
253 {
254     RetainPtr<DownloadNavigationDelegate> navigationDelegate = adoptNS([[DownloadNavigationDelegate alloc] init]);                 
255     RetainPtr<OriginatingWebViewDownloadDelegate> downloadDelegate;
256     {
257         RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
258         [webView setNavigationDelegate:navigationDelegate.get()];
259         downloadDelegate = adoptNS([[OriginatingWebViewDownloadDelegate alloc] initWithWebView:webView.get()]);
260         [[[webView configuration] processPool] _setDownloadDelegate:downloadDelegate.get()];
261         [webView loadRequest:[NSURLRequest requestWithURL:sourceURL]];
262     }
263
264     isDone = false;
265     TestWebKitAPI::Util::run(&isDone);
266 }
267
268 #endif
269 #endif