2 * Copyright (C) 2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
28 #if WK_API_ENABLED && PLATFORM(MAC)
30 #import "MockContentFilterSettings.h"
31 #import "PlatformUtilities.h"
32 #import "TestProtocol.h"
33 #import "WKWebViewConfigurationExtras.h"
34 #import <WebKit/WKBrowsingContextController.h>
35 #import <WebKit/WKNavigationDelegatePrivate.h>
36 #import <WebKit/WKProcessPoolPrivate.h>
37 #import <WebKit/WKWebView.h>
38 #import <WebKit/_WKDownloadDelegate.h>
39 #import <wtf/RetainPtr.h>
41 using Decision = WebCore::MockContentFilterSettings::Decision;
42 using DecisionPoint = WebCore::MockContentFilterSettings::DecisionPoint;
46 @interface MockContentFilterEnabler : NSObject <NSCopying, NSSecureCoding>
47 - (instancetype)initWithDecision:(Decision)decision decisionPoint:(DecisionPoint)decisionPoint;
50 @implementation MockContentFilterEnabler {
52 DecisionPoint _decisionPoint;
55 + (BOOL)supportsSecureCoding
60 - (id)copyWithZone:(NSZone *)zone
65 - (instancetype)initWithCoder:(NSCoder *)decoder
70 - (instancetype)initWithDecision:(Decision)decision decisionPoint:(DecisionPoint)decisionPoint
72 if (!(self = [super init]))
76 _decisionPoint = decisionPoint;
80 - (void)encodeWithCoder:(NSCoder *)coder
82 [coder encodeInt:static_cast<int>(_decision) forKey:@"Decision"];
83 [coder encodeInt:static_cast<int>(_decisionPoint) forKey:@"DecisionPoint"];
88 static RetainPtr<WKWebViewConfiguration> configurationWithContentFilterSettings(Decision decision, DecisionPoint decisionPoint)
90 auto configuration = retainPtr([WKWebViewConfiguration testwebkitapi_configurationWithTestPlugInClassName:@"ContentFilteringPlugIn"]);
91 auto contentFilterEnabler = adoptNS([[MockContentFilterEnabler alloc] initWithDecision:decision decisionPoint:decisionPoint]);
92 [[configuration processPool] _setObject:contentFilterEnabler.get() forBundleParameter:NSStringFromClass([MockContentFilterEnabler class])];
96 @interface ServerRedirectNavigationDelegate : NSObject <WKNavigationDelegate>
99 @implementation ServerRedirectNavigationDelegate
101 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
103 EXPECT_WK_STREQ(webView.URL.absoluteString, @"http://redirect/?pass");
106 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
108 EXPECT_WK_STREQ(webView.URL.absoluteString, @"http://pass/");
111 - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
118 TEST(ContentFiltering, URLAfterServerRedirect)
121 [NSURLProtocol registerClass:[TestProtocol class]];
122 [WKBrowsingContextController registerSchemeForCustomProtocol:[TestProtocol scheme]];
124 auto configuration = configurationWithContentFilterSettings(Decision::Allow, DecisionPoint::AfterAddData);
125 auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
126 auto navigationDelegate = adoptNS([[ServerRedirectNavigationDelegate alloc] init]);
127 [webView setNavigationDelegate:navigationDelegate.get()];
128 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://redirect?pass"]]];
129 TestWebKitAPI::Util::run(&isDone);
131 [WKBrowsingContextController unregisterSchemeForCustomProtocol:[TestProtocol scheme]];
132 [NSURLProtocol unregisterClass:[TestProtocol class]];
136 @interface BecomeDownloadDelegate : NSObject <WKNavigationDelegate>
139 @implementation BecomeDownloadDelegate
141 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
143 decisionHandler(_WKNavigationResponsePolicyBecomeDownload);
146 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
151 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
158 static bool downloadDidStart;
160 @interface ContentFilteringDownloadDelegate : NSObject <_WKDownloadDelegate>
163 @implementation ContentFilteringDownloadDelegate
165 - (void)_downloadDidStart:(_WKDownload *)download
167 downloadDidStart = true;
172 static void downloadTest(Decision decision, DecisionPoint decisionPoint)
175 [NSURLProtocol registerClass:[TestProtocol class]];
176 [WKBrowsingContextController registerSchemeForCustomProtocol:[TestProtocol scheme]];
178 auto configuration = configurationWithContentFilterSettings(decision, decisionPoint);
179 auto downloadDelegate = adoptNS([[ContentFilteringDownloadDelegate alloc] init]);
180 [[configuration processPool] _setDownloadDelegate:downloadDelegate.get()];
181 auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration.get()]);
182 auto navigationDelegate = adoptNS([[BecomeDownloadDelegate alloc] init]);
183 [webView setNavigationDelegate:navigationDelegate.get()];
184 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://redirect/?download"]]];
187 downloadDidStart = false;
188 TestWebKitAPI::Util::run(&isDone);
190 const bool downloadShouldStart = decision == Decision::Allow || decisionPoint > DecisionPoint::AfterResponse;
191 EXPECT_EQ(downloadShouldStart, downloadDidStart);
193 [WKBrowsingContextController unregisterSchemeForCustomProtocol:[TestProtocol scheme]];
194 [NSURLProtocol unregisterClass:[TestProtocol class]];
198 TEST(ContentFiltering, AllowDownloadAfterWillSendRequest)
200 downloadTest(Decision::Allow, DecisionPoint::AfterWillSendRequest);
203 TEST(ContentFiltering, BlockDownloadAfterWillSendRequest)
205 downloadTest(Decision::Block, DecisionPoint::AfterWillSendRequest);
208 TEST(ContentFiltering, AllowDownloadAfterRedirect)
210 downloadTest(Decision::Allow, DecisionPoint::AfterRedirect);
213 TEST(ContentFiltering, BlockDownloadAfterRedirect)
215 downloadTest(Decision::Block, DecisionPoint::AfterRedirect);
218 TEST(ContentFiltering, AllowDownloadAfterResponse)
220 downloadTest(Decision::Allow, DecisionPoint::AfterResponse);
223 TEST(ContentFiltering, BlockDownloadAfterResponse)
225 downloadTest(Decision::Block, DecisionPoint::AfterResponse);
228 TEST(ContentFiltering, AllowDownloadAfterAddData)
230 downloadTest(Decision::Allow, DecisionPoint::AfterAddData);
233 TEST(ContentFiltering, BlockDownloadAfterAddData)
235 downloadTest(Decision::Block, DecisionPoint::AfterAddData);
238 TEST(ContentFiltering, AllowDownloadAfterFinishedAddingData)
240 downloadTest(Decision::Allow, DecisionPoint::AfterFinishedAddingData);
243 TEST(ContentFiltering, BlockDownloadAfterFinishedAddingData)
245 downloadTest(Decision::Block, DecisionPoint::AfterFinishedAddingData);
248 TEST(ContentFiltering, AllowDownloadNever)
250 downloadTest(Decision::Allow, DecisionPoint::Never);
253 TEST(ContentFiltering, BlockDownloadNever)
255 downloadTest(Decision::Block, DecisionPoint::Never);
258 #endif // WK_API_ENABLED