Web Inspector: provide a way to edit page settings on a remote target
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKitCocoa / WebsitePolicies.mm
1 /*
2  * Copyright (C) 2016 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 #include "config.h"
27
28 #import "PlatformUtilities.h"
29 #import "TestWKWebView.h"
30 #import <WebKit/WKNavigationDelegatePrivate.h>
31 #import <WebKit/WKPagePrivate.h>
32 #import <WebKit/WKPreferencesRefPrivate.h>
33 #import <WebKit/WKUIDelegatePrivate.h>
34 #import <WebKit/WKURLSchemeTaskPrivate.h>
35 #import <WebKit/WKUserContentControllerPrivate.h>
36 #import <WebKit/WKWebViewPrivate.h>
37 #import <WebKit/WKWebsiteDataStorePrivate.h>
38 #import <WebKit/_WKUserContentExtensionStorePrivate.h>
39 #import <WebKit/_WKWebsiteDataStoreConfiguration.h>
40 #import <WebKit/_WKWebsitePolicies.h>
41 #import <wtf/Function.h>
42 #import <wtf/HashMap.h>
43 #import <wtf/MainThread.h>
44 #import <wtf/RetainPtr.h>
45 #import <wtf/text/StringHash.h>
46 #import <wtf/text/WTFString.h>
47
48 #if PLATFORM(IOS_FAMILY)
49 #import <WebKit/WKWebViewConfigurationPrivate.h>
50 #endif
51
52 #if WK_API_ENABLED
53
54 @interface WKWebView ()
55 - (WKPageRef)_pageForTesting;
56 @end
57
58 static bool doneCompiling;
59 static bool receivedAlert;
60 static bool finishedNavigation;
61
62 #if PLATFORM(MAC)
63 static Optional<_WKAutoplayEvent> receivedAutoplayEvent;
64 static Optional<_WKAutoplayEventFlags> receivedAutoplayEventFlags;
65 #endif
66
67 static size_t alertCount;
68
69 @interface ContentBlockingWebsitePoliciesDelegate : NSObject <WKNavigationDelegate, WKUIDelegate>
70 @end
71
72 @implementation ContentBlockingWebsitePoliciesDelegate
73
74 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
75 {
76     // _webView:decidePolicyForNavigationAction:decisionHandler: should be called instead if it is implemented.
77     EXPECT_TRUE(false);
78     decisionHandler(WKNavigationActionPolicyAllow);
79 }
80
81 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
82 {
83     switch (alertCount++) {
84     case 0:
85         // Default behavior.
86         EXPECT_STREQ("content blockers enabled", message.UTF8String);
87         break;
88     case 1:
89         // After having set websitePolicies.contentBlockersEnabled to false.
90         EXPECT_STREQ("content blockers disabled", message.UTF8String);
91         break;
92     case 2:
93         // After having reloaded without content blockers.
94         EXPECT_STREQ("content blockers disabled", message.UTF8String);
95         break;
96     default:
97         EXPECT_TRUE(false);
98     }
99     receivedAlert = true;
100     completionHandler();
101 }
102
103 - (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
104 {
105     _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
106     switch (alertCount) {
107     case 0:
108         // Verify the content blockers behave correctly with the default behavior.
109         break;
110     case 1:
111         {
112             // Verify disabling content blockers works correctly.
113             websitePolicies.contentBlockersEnabled = false;
114             
115             // Verify calling the decisionHandler asynchronously works correctly.
116             auto decisionHandlerCopy = Block_copy(decisionHandler);
117             callOnMainThread([decisionHandlerCopy, websitePolicies = RetainPtr<_WKWebsitePolicies>(websitePolicies)] {
118                 decisionHandlerCopy(WKNavigationActionPolicyAllow, websitePolicies.get());
119                 Block_release(decisionHandlerCopy);
120             });
121         }
122         return;
123     case 2:
124         // Verify enabling content blockers has no effect when reloading without content blockers.
125         websitePolicies.contentBlockersEnabled = true;
126         break;
127     default:
128         EXPECT_TRUE(false);
129     }
130     decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
131 }
132
133 @end
134
135 TEST(WebKit, WebsitePoliciesContentBlockersEnabled)
136 {
137     [[_WKUserContentExtensionStore defaultStore] _removeAllContentExtensions];
138
139     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
140
141     doneCompiling = false;
142     NSString* contentBlocker = @"[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]";
143     [[_WKUserContentExtensionStore defaultStore] compileContentExtensionForIdentifier:@"WebsitePoliciesTest" encodedContentExtension:contentBlocker completionHandler:^(_WKUserContentFilter *filter, NSError *error) {
144         EXPECT_TRUE(error == nil);
145         [[configuration userContentController] _addUserContentFilter:filter];
146         doneCompiling = true;
147     }];
148     TestWebKitAPI::Util::run(&doneCompiling);
149
150     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
151
152     auto delegate = adoptNS([[ContentBlockingWebsitePoliciesDelegate alloc] init]);
153     [webView setNavigationDelegate:delegate.get()];
154     [webView setUIDelegate:delegate.get()];
155
156     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"contentBlockerCheck" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
157     alertCount = 0;
158     receivedAlert = false;
159     [webView loadRequest:request];
160     TestWebKitAPI::Util::run(&receivedAlert);
161
162     receivedAlert = false;
163     [webView reload];
164     TestWebKitAPI::Util::run(&receivedAlert);
165
166     receivedAlert = false;
167     [webView _reloadWithoutContentBlockers];
168     TestWebKitAPI::Util::run(&receivedAlert);
169
170     [[_WKUserContentExtensionStore defaultStore] _removeAllContentExtensions];
171 }
172
173 @interface AutoplayPoliciesDelegate : NSObject <WKNavigationDelegate, WKUIDelegatePrivate>
174 @property (nonatomic, copy) _WKWebsiteAutoplayPolicy(^autoplayPolicyForURL)(NSURL *);
175 @property (nonatomic, copy) _WKWebsiteAutoplayQuirk(^allowedAutoplayQuirksForURL)(NSURL *);
176 @end
177
178 @implementation AutoplayPoliciesDelegate
179
180 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
181 {
182     // _webView:decidePolicyForNavigationAction:decisionHandler: should be called instead if it is implemented.
183     EXPECT_TRUE(false);
184     decisionHandler(WKNavigationActionPolicyAllow);
185 }
186
187 - (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
188 {
189     _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
190     if (_allowedAutoplayQuirksForURL)
191         websitePolicies.allowedAutoplayQuirks = _allowedAutoplayQuirksForURL(navigationAction.request.URL);
192     if (_autoplayPolicyForURL)
193         websitePolicies.autoplayPolicy = _autoplayPolicyForURL(navigationAction.request.URL);
194     decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
195 }
196
197 #if PLATFORM(MAC)
198 - (void)_webView:(WKWebView *)webView handleAutoplayEvent:(_WKAutoplayEvent)event withFlags:(_WKAutoplayEventFlags)flags
199 {
200     receivedAutoplayEventFlags = flags;
201     receivedAutoplayEvent = event;
202 }
203 #endif
204
205 @end
206
207 @interface AsyncAutoplayPoliciesDelegate : NSObject <WKNavigationDelegate, WKUIDelegatePrivate>
208 @property (nonatomic, copy) _WKWebsiteAutoplayPolicy(^autoplayPolicyForURL)(NSURL *);
209 @property (nonatomic, copy) _WKWebsiteAutoplayQuirk(^allowedAutoplayQuirksForURL)(NSURL *);
210 @end
211
212 @implementation AsyncAutoplayPoliciesDelegate
213
214 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
215 {
216     // _webView:decidePolicyForNavigationAction:decisionHandler: should be called instead if it is implemented.
217     EXPECT_TRUE(false);
218     decisionHandler(WKNavigationActionPolicyAllow);
219 }
220
221 - (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
222 {
223     dispatch_async(dispatch_get_main_queue(), ^{
224         _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
225         if (_allowedAutoplayQuirksForURL)
226             websitePolicies.allowedAutoplayQuirks = _allowedAutoplayQuirksForURL(navigationAction.request.URL);
227         if (_autoplayPolicyForURL)
228             websitePolicies.autoplayPolicy = _autoplayPolicyForURL(navigationAction.request.URL);
229         decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
230     });
231 }
232
233 #if PLATFORM(MAC)
234 - (void)_webView:(WKWebView *)webView handleAutoplayEvent:(_WKAutoplayEvent)event withFlags:(_WKAutoplayEventFlags)flags
235 {
236     receivedAutoplayEventFlags = flags;
237     receivedAutoplayEvent = event;
238 }
239 #endif
240
241 @end
242
243 TEST(WebKit, WebsitePoliciesAutoplayEnabled)
244 {
245     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
246
247 #if PLATFORM(IOS_FAMILY)
248     [configuration setAllowsInlineMediaPlayback:YES];
249 #endif
250
251     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
252
253     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
254     [webView setNavigationDelegate:delegate.get()];
255
256     NSURLRequest *requestWithAudio = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
257     NSURLRequest *requestWithoutAudio = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-no-audio-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
258
259     // iOS does not support volume changes to media elements.
260 #if PLATFORM(MAC)
261     NSURLRequest *requestWithoutVolume = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-zero-volume-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
262 #endif
263
264     [delegate setAutoplayPolicyForURL:^(NSURL *) {
265         return _WKWebsiteAutoplayPolicyAllowWithoutSound;
266     }];
267     [webView loadRequest:requestWithAudio];
268     [webView waitForMessage:@"did-not-play"];
269
270     [webView loadRequest:requestWithoutAudio];
271     [webView waitForMessage:@"autoplayed"];
272
273 #if PLATFORM(MAC)
274     [webView loadRequest:requestWithoutVolume];
275     [webView waitForMessage:@"autoplayed"];
276 #endif
277
278     [delegate setAutoplayPolicyForURL:^(NSURL *) {
279         return _WKWebsiteAutoplayPolicyDeny;
280     }];
281
282 #if PLATFORM(MAC)
283     [webView loadRequest:requestWithoutVolume];
284     [webView waitForMessage:@"did-not-play"];
285 #endif
286
287     [webView loadRequest:requestWithAudio];
288     [webView waitForMessage:@"did-not-play"];
289
290     // Test updating website policies.
291     _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
292     websitePolicies.autoplayPolicy = _WKWebsiteAutoplayPolicyAllow;
293     [webView _updateWebsitePolicies:websitePolicies];
294     [webView stringByEvaluatingJavaScript:@"playVideo()"];
295     [webView waitForMessage:@"autoplayed"];
296
297     [webView loadRequest:requestWithoutAudio];
298     [webView waitForMessage:@"did-not-play"];
299
300     [delegate setAutoplayPolicyForURL:^(NSURL *) {
301         return _WKWebsiteAutoplayPolicyAllow;
302     }];
303     [webView loadRequest:requestWithAudio];
304     [webView waitForMessage:@"autoplayed"];
305
306     [webView loadRequest:requestWithoutAudio];
307     [webView waitForMessage:@"autoplayed"];
308
309 #if PLATFORM(MAC)
310     [webView loadRequest:requestWithoutVolume];
311     [webView waitForMessage:@"autoplayed"];
312 #endif
313
314     NSURLRequest *requestWithAudioInIFrame = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check-in-iframe" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
315
316     // If the top-level document allows autoplay, any iframes should also autoplay.
317     [delegate setAutoplayPolicyForURL:^(NSURL *url) {
318         if ([url.lastPathComponent isEqualToString:@"autoplay-check-in-iframe.html"])
319             return _WKWebsiteAutoplayPolicyAllow;
320         return _WKWebsiteAutoplayPolicyDeny;
321     }];
322
323     [webView loadRequest:requestWithAudioInIFrame];
324     [webView waitForMessage:@"autoplayed"];
325
326     // If the top-level document disallows autoplay, any iframes should also not autoplay.
327     [delegate setAutoplayPolicyForURL:^(NSURL *url) {
328         if ([url.lastPathComponent isEqualToString:@"autoplay-check-in-iframe.html"])
329             return _WKWebsiteAutoplayPolicyDeny;
330         return _WKWebsiteAutoplayPolicyAllow;
331     }];
332
333     [webView loadRequest:requestWithAudioInIFrame];
334     [webView waitForMessage:@"did-not-play"];
335 }
336
337 #if PLATFORM(MAC)
338 static void runUntilReceivesAutoplayEvent(WKAutoplayEvent event)
339 {
340     while (!receivedAutoplayEvent || *receivedAutoplayEvent != event)
341         CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, true);
342 }
343
344 TEST(WebKit, WebsitePoliciesPlayAfterPreventedAutoplay)
345 {
346     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
347     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 336, 276) configuration:configuration.get()]);
348
349     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
350     [delegate setAutoplayPolicyForURL:^(NSURL *) {
351         return _WKWebsiteAutoplayPolicyDeny;
352     }];
353     [webView setNavigationDelegate:delegate.get()];
354     [webView setUIDelegate:delegate.get()];
355
356     NSPoint playButtonClickPoint = NSMakePoint(20, 256);
357
358     receivedAutoplayEvent = WTF::nullopt;
359     NSURLRequest *jsPlayRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"js-play-with-controls" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
360     [webView loadRequest:jsPlayRequest];
361     [webView waitForMessage:@"loaded"];
362     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPreventFromAutoplaying);
363
364     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
365     [webView mouseUpAtPoint:playButtonClickPoint];
366     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPlayMediaWithUserGesture);
367     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsHasAudio);
368     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsPlaybackWasPrevented);
369
370     receivedAutoplayEvent = WTF::nullopt;
371     [webView loadHTMLString:@"" baseURL:nil];
372
373     NSURLRequest *autoplayRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-with-controls" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
374     [webView loadRequest:autoplayRequest];
375     [webView waitForMessage:@"loaded"];
376     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPreventFromAutoplaying);
377     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsHasAudio);
378
379     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
380     [webView mouseUpAtPoint:playButtonClickPoint];
381     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPlayMediaWithUserGesture);
382     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsHasAudio);
383     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsPlaybackWasPrevented);
384
385     receivedAutoplayEvent = WTF::nullopt;
386     [webView loadHTMLString:@"" baseURL:nil];
387
388     NSURLRequest *noAutoplayRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"no-autoplay-with-controls" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
389     [webView loadRequest:noAutoplayRequest];
390     [webView waitForMessage:@"loaded"];
391     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
392     [webView mouseUpAtPoint:playButtonClickPoint];
393     [webView waitForMessage:@"played"];
394     ASSERT_TRUE(receivedAutoplayEvent == WTF::nullopt);
395
396     receivedAutoplayEvent = WTF::nullopt;
397     [webView loadHTMLString:@"" baseURL:nil];
398
399     [delegate setAutoplayPolicyForURL:^(NSURL *) {
400         return _WKWebsiteAutoplayPolicyAllowWithoutSound;
401     }];
402
403     NSURLRequest *autoplayMutedRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-muted-with-controls" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
404     [webView loadRequest:autoplayMutedRequest];
405     [webView waitForMessage:@"loaded"];
406     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPreventFromAutoplaying);
407
408     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
409     [webView mouseUpAtPoint:playButtonClickPoint];
410     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPlayMediaWithUserGesture);
411     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsHasAudio);
412     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsPlaybackWasPrevented);
413 }
414
415 TEST(WebKit, WebsitePoliciesPlayingWithUserGesture)
416 {
417     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
418     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
419
420     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
421     [delegate setAutoplayPolicyForURL:^(NSURL *) {
422         return _WKWebsiteAutoplayPolicyAllow;
423     }];
424     [webView setNavigationDelegate:delegate.get()];
425     [webView setUIDelegate:delegate.get()];
426
427     receivedAutoplayEvent = WTF::nullopt;
428
429     NSPoint playButtonClickPoint = NSMakePoint(20, 580);
430
431     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"audio-with-play-button" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
432     [webView loadRequest:request];
433     [webView waitForMessage:@"loaded"];
434     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
435     [webView mouseUpAtPoint:playButtonClickPoint];
436
437     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPlayMediaWithUserGesture);
438     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsHasAudio);
439     ASSERT_FALSE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsMediaIsMainContent);
440
441     receivedAutoplayEvent = WTF::nullopt;
442
443     request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"video-with-play-button" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
444     [webView loadRequest:request];
445     [webView waitForMessage:@"loaded"];
446     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
447     [webView mouseUpAtPoint:playButtonClickPoint];
448
449     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPlayMediaWithUserGesture);
450     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsHasAudio);
451     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsMediaIsMainContent);
452 }
453
454 TEST(WebKit, WebsitePoliciesPlayingWithoutInterference)
455 {
456     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
457     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 336, 276) configuration:configuration.get()]);
458
459     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
460     [delegate setAutoplayPolicyForURL:^(NSURL *) {
461         return _WKWebsiteAutoplayPolicyAllow;
462     }];
463     [webView setNavigationDelegate:delegate.get()];
464     [webView setUIDelegate:delegate.get()];
465
466     receivedAutoplayEvent = WTF::nullopt;
467     NSURLRequest *jsPlayRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"js-autoplay-audio" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
468     [webView loadRequest:jsPlayRequest];
469     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidAutoplayMediaPastThresholdWithoutUserInterference);
470     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsHasAudio);
471 }
472
473 TEST(WebKit, WebsitePoliciesUserInterferenceWithPlaying)
474 {
475     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
476     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 336, 276) configuration:configuration.get()]);
477
478     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
479     [delegate setAutoplayPolicyForURL:^(NSURL *) {
480         return _WKWebsiteAutoplayPolicyAllow;
481     }];
482     [webView setNavigationDelegate:delegate.get()];
483     [webView setUIDelegate:delegate.get()];
484
485     receivedAutoplayEvent = WTF::nullopt;
486     NSURLRequest *jsPlayRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"js-play-with-controls" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
487     [webView loadRequest:jsPlayRequest];
488     [webView waitForMessage:@"playing"];
489     ASSERT_TRUE(receivedAutoplayEvent == WTF::nullopt);
490
491     WKPageSetMuted([webView _pageForTesting], kWKMediaAudioMuted);
492     runUntilReceivesAutoplayEvent(kWKAutoplayEventUserDidInterfereWithPlayback);
493     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsHasAudio);
494
495     receivedAutoplayEvent = WTF::nullopt;
496     [webView loadRequest:jsPlayRequest];
497     [webView waitForMessage:@"playing"];
498     ASSERT_TRUE(receivedAutoplayEvent == WTF::nullopt);
499
500     const NSPoint muteButtonClickPoint = NSMakePoint(80, 256);
501     [webView mouseDownAtPoint:muteButtonClickPoint simulatePressure:NO];
502     [webView mouseUpAtPoint:muteButtonClickPoint];
503     runUntilReceivesAutoplayEvent(kWKAutoplayEventUserDidInterfereWithPlayback);
504     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsHasAudio);
505
506     receivedAutoplayEvent = WTF::nullopt;
507     [webView loadRequest:jsPlayRequest];
508     [webView waitForMessage:@"playing"];
509     ASSERT_TRUE(receivedAutoplayEvent == WTF::nullopt);
510
511     const NSPoint playButtonClickPoint = NSMakePoint(20, 256);
512     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
513     [webView mouseUpAtPoint:playButtonClickPoint];
514     runUntilReceivesAutoplayEvent(kWKAutoplayEventUserDidInterfereWithPlayback);
515     ASSERT_TRUE(*receivedAutoplayEventFlags & kWKAutoplayEventFlagsHasAudio);
516 }
517
518 struct ParsedRange {
519     ParsedRange(String string)
520     {
521         // This is a strict and unsafe Range header parser adequate only for tests.
522         bool parsingMin = true;
523         size_t min = 0;
524         size_t max = 0;
525         ASSERT(string.length() > 6);
526         ASSERT(string.startsWith("bytes="));
527         for (size_t i = 6; i < string.length(); ++i) {
528             if (isASCIIDigit(string[i])) {
529                 if (parsingMin)
530                     min = min * 10 + string[i] - '0';
531                 else
532                     max = max * 10 + string[i] - '0';
533             } else if (string[i] == '-') {
534                 if (parsingMin)
535                     parsingMin = false;
536                 else
537                     return;
538             } else
539                 return;
540         }
541         if (min <= max)
542             range = std::make_pair(min, max);
543     }
544     Optional<std::pair<size_t, size_t>> range;
545 };
546
547 @interface TestSchemeHandler : NSObject <WKURLSchemeHandler>
548 - (instancetype)initWithVideoData:(RetainPtr<NSData>&&)data;
549 @end
550
551 @implementation TestSchemeHandler {
552     RetainPtr<NSData> videoData;
553 }
554
555 - (instancetype)initWithVideoData:(RetainPtr<NSData>&&)data
556 {
557     self = [super init];
558     if (!self)
559         return nil;
560     
561     videoData = WTFMove(data);
562     
563     return self;
564 }
565
566 - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
567 {
568     if ([task.request.URL.path isEqualToString:@"/should-redirect"]) {
569         [(id<WKURLSchemeTaskPrivate>)task _didPerformRedirection:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:nil expectedContentLength:0 textEncodingName:nil] autorelease] newRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///autoplay-check.html"]]];
570         
571         NSData *data = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
572         [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:data.length textEncodingName:nil] autorelease]];
573         [task didReceiveData:data];
574         [task didFinish];
575         return;
576     }
577     
578     ASSERT_TRUE([task.request.URL.path isEqualToString:@"/test.mp4"]);
579     ParsedRange parsedRange([task.request valueForHTTPHeaderField:@"Range"]);
580     ASSERT_TRUE(!!parsedRange.range);
581     auto& range = *parsedRange.range;
582     
583     NSDictionary *headerFields = @{ @"Content-Length": [@(range.second - range.first) stringValue], @"Content-Range": [NSString stringWithFormat:@"bytes %lu-%lu/%lu", range.first, range.second, [videoData length]] };
584     NSURLResponse *response = [[[NSHTTPURLResponse alloc] initWithURL:task.request.URL statusCode:200 HTTPVersion:(NSString *)kCFHTTPVersion1_1 headerFields:headerFields] autorelease];
585     [task didReceiveResponse:response];
586     [task didReceiveData:[videoData subdataWithRange:NSMakeRange(range.first, range.second - range.first)]];
587     [task didFinish];
588     
589 }
590
591 - (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)task
592 {
593 }
594
595 @end
596
597 TEST(WebKit, WebsitePoliciesDuringRedirect)
598 {
599     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
600     auto videoData = adoptNS([[NSData alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"test" withExtension:@"mp4" subdirectory:@"TestWebKitAPI.resources"]]);
601     [configuration setURLSchemeHandler:[[[TestSchemeHandler alloc] initWithVideoData:WTFMove(videoData)] autorelease] forURLScheme:@"test"];
602     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
603     
604     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
605     [delegate setAutoplayPolicyForURL:^(NSURL *url) {
606         if ([url.path isEqualToString:@"/should-redirect"])
607             return _WKWebsiteAutoplayPolicyDeny;
608         return _WKWebsiteAutoplayPolicyAllow;
609     }];
610     [webView setNavigationDelegate:delegate.get()];
611     [webView setUIDelegate:delegate.get()];
612     
613     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///should-redirect"]]];
614     [webView waitForMessage:@"autoplayed"];
615 }
616
617 TEST(WebKit, WebsitePoliciesUpdates)
618 {
619     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
620     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
621     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
622     [webView setNavigationDelegate:delegate.get()];
623     [webView setUIDelegate:delegate.get()];
624
625     NSURLRequest *requestWithAudio = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
626
627     [delegate setAutoplayPolicyForURL:^(NSURL *) {
628         return _WKWebsiteAutoplayPolicyDeny;
629     }];
630     [webView loadRequest:requestWithAudio];
631     [webView waitForMessage:@"did-not-play"];
632
633     _WKWebsitePolicies *policies = [[[_WKWebsitePolicies alloc] init] autorelease];
634     policies.autoplayPolicy = _WKWebsiteAutoplayPolicyAllow;
635     [webView _updateWebsitePolicies:policies];
636
637     // Now that we updated our policies, a script should be able to autoplay media.
638     [webView stringByEvaluatingJavaScript:@"playVideo()"];
639     [webView waitForMessage:@"autoplayed"];
640
641     [webView stringByEvaluatingJavaScript:@"pauseVideo()"];
642
643     policies = [[[_WKWebsitePolicies alloc] init] autorelease];
644     policies.autoplayPolicy = _WKWebsiteAutoplayPolicyDeny;
645     [webView _updateWebsitePolicies:policies];
646
647     // A script should no longer be able to autoplay media.
648     receivedAutoplayEvent = WTF::nullopt;
649     [webView stringByEvaluatingJavaScript:@"playVideo()"];
650     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPreventFromAutoplaying);
651 }
652
653 TEST(WebKit, WebsitePoliciesArbitraryUserGestureQuirk)
654 {
655     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
656     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
657
658     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
659     [webView setNavigationDelegate:delegate.get()];
660
661     WKRetainPtr<WKPreferencesRef> preferences(AdoptWK, WKPreferencesCreate());
662     WKPreferencesSetNeedsSiteSpecificQuirks(preferences.get(), true);
663     WKPageGroupSetPreferences(WKPageGetPageGroup([webView _pageForTesting]), preferences.get());
664
665     [delegate setAllowedAutoplayQuirksForURL:^_WKWebsiteAutoplayQuirk(NSURL *url)
666     {
667         return _WKWebsiteAutoplayQuirkArbitraryUserGestures;
668     }];
669     [delegate setAutoplayPolicyForURL:^(NSURL *)
670     {
671         return _WKWebsiteAutoplayPolicyDeny;
672     }];
673
674     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
675     [webView loadRequest:request];
676     [webView waitForMessage:@"did-not-play"];
677
678     const NSPoint clickPoint = NSMakePoint(760, 560);
679     [webView mouseDownAtPoint:clickPoint simulatePressure:NO];
680     [webView mouseUpAtPoint:clickPoint];
681
682     [webView stringByEvaluatingJavaScript:@"playVideo()"];
683     [webView waitForMessage:@"autoplayed"];
684 }
685
686 TEST(WebKit, WebsitePoliciesAutoplayQuirks)
687 {
688     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
689     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
690
691     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
692     [webView setNavigationDelegate:delegate.get()];
693
694     WKRetainPtr<WKPreferencesRef> preferences(AdoptWK, WKPreferencesCreate());
695     WKPreferencesSetNeedsSiteSpecificQuirks(preferences.get(), true);
696     WKPageGroupSetPreferences(WKPageGetPageGroup([webView _pageForTesting]), preferences.get());
697
698     NSURLRequest *requestWithAudio = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
699
700     [delegate setAllowedAutoplayQuirksForURL:^_WKWebsiteAutoplayQuirk(NSURL *url) {
701         return _WKWebsiteAutoplayQuirkSynthesizedPauseEvents;
702     }];
703     [delegate setAutoplayPolicyForURL:^(NSURL *) {
704         return _WKWebsiteAutoplayPolicyDeny;
705     }];
706     [webView loadRequest:requestWithAudio];
707     [webView waitForMessage:@"did-not-play"];
708     [webView waitForMessage:@"on-pause"];
709
710     receivedAutoplayEvent = WTF::nullopt;
711     [webView loadHTMLString:@"" baseURL:nil];
712
713     NSURLRequest *requestWithAudioInFrame = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check-in-iframe" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
714
715     [delegate setAllowedAutoplayQuirksForURL:^_WKWebsiteAutoplayQuirk(NSURL *url) {
716         if ([url.lastPathComponent isEqualToString:@"autoplay-check-frame.html"])
717             return _WKWebsiteAutoplayQuirkInheritedUserGestures;
718         
719         return _WKWebsiteAutoplayQuirkSynthesizedPauseEvents | _WKWebsiteAutoplayQuirkInheritedUserGestures;
720     }];
721     [delegate setAutoplayPolicyForURL:^(NSURL *) {
722         return _WKWebsiteAutoplayPolicyDeny;
723     }];
724     [webView loadRequest:requestWithAudioInFrame];
725     [webView waitForMessage:@"did-not-play"];
726     [webView waitForMessage:@"on-pause"];
727
728     receivedAutoplayEvent = WTF::nullopt;
729     [webView loadHTMLString:@"" baseURL:nil];
730
731     NSURLRequest *requestThatInheritsGesture = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-inherits-gesture-from-document" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
732     [webView loadRequest:requestThatInheritsGesture];
733     [webView waitForMessage:@"loaded"];
734
735     // Click in the document, but not in the media element.
736     const NSPoint clickPoint = NSMakePoint(760, 560);
737     [webView mouseDownAtPoint:clickPoint simulatePressure:NO];
738     [webView mouseUpAtPoint:clickPoint];
739
740     [webView stringByEvaluatingJavaScript:@"play()"];
741     [webView waitForMessage:@"playing"];
742 }
743
744 TEST(WebKit, WebsitePoliciesPerDocumentAutoplayBehaviorQuirks)
745 {
746     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
747     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
748
749     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
750     [webView setNavigationDelegate:delegate.get()];
751
752     WKRetainPtr<WKPreferencesRef> preferences(AdoptWK, WKPreferencesCreate());
753     WKPreferencesSetNeedsSiteSpecificQuirks(preferences.get(), true);
754     WKPageGroupSetPreferences(WKPageGetPageGroup([webView _pageForTesting]), preferences.get());
755
756     receivedAutoplayEvent = WTF::nullopt;
757
758     NSURLRequest *requestWithMultipleMediaElements = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplaying-multiple-media-elements" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
759
760     [delegate setAllowedAutoplayQuirksForURL:^_WKWebsiteAutoplayQuirk(NSURL *url) {
761         return _WKWebsiteAutoplayQuirkPerDocumentAutoplayBehavior;
762     }];
763     [delegate setAutoplayPolicyForURL:^(NSURL *) {
764         return _WKWebsiteAutoplayPolicyDeny;
765     }];
766     [webView loadRequest:requestWithMultipleMediaElements];
767     [webView waitForMessage:@"loaded"];
768
769     // We should not be allowed to play without a user gesture.
770     [webView _evaluateJavaScriptWithoutUserGesture:@"playVideo('video1')" completionHandler:nil];
771     [webView waitForMessage:@"did-not-play-video1"];
772
773     // Now try again with a user gesture...
774     const NSPoint playButtonClickPoint = NSMakePoint(20, 580);
775     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
776     [webView mouseUpAtPoint:playButtonClickPoint];
777     [webView waitForMessage:@"did-play-video1"];
778
779     // Now video2 should also be allowed to autoplay without a user gesture because of the quirk.
780     [webView _evaluateJavaScriptWithoutUserGesture:@"playVideo('video2')" completionHandler:nil];
781     [webView waitForMessage:@"did-play-video2"];
782
783     // Now let's test this without the quirk.
784     [webView loadHTMLString:@"" baseURL:nil];
785     receivedAutoplayEvent = WTF::nullopt;
786
787     [delegate setAllowedAutoplayQuirksForURL:^_WKWebsiteAutoplayQuirk(NSURL *url) {
788         return 0;
789     }];
790     [webView loadRequest:requestWithMultipleMediaElements];
791     [webView waitForMessage:@"loaded"];
792
793     // We should not be allowed to play without a user gesture.
794     [webView _evaluateJavaScriptWithoutUserGesture:@"playVideo('video1')" completionHandler:nil];
795     [webView waitForMessage:@"did-not-play-video1"];
796
797     // Now try again with a user gesture...
798     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
799     [webView mouseUpAtPoint:playButtonClickPoint];
800     [webView waitForMessage:@"did-play-video1"];
801
802     // Now video2 should not be allowed to autoplay without a user gesture.
803     [webView _evaluateJavaScriptWithoutUserGesture:@"playVideo('video2')" completionHandler:nil];
804     [webView waitForMessage:@"did-not-play-video2"];
805 }
806
807 TEST(WebKit, WebsitePoliciesAutoplayQuirksAsyncPolicyDelegate)
808 {
809     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
810     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
811
812     auto delegate = adoptNS([[AsyncAutoplayPoliciesDelegate alloc] init]);
813     [webView setNavigationDelegate:delegate.get()];
814
815     WKRetainPtr<WKPreferencesRef> preferences(AdoptWK, WKPreferencesCreate());
816     WKPreferencesSetNeedsSiteSpecificQuirks(preferences.get(), true);
817     WKPageGroupSetPreferences(WKPageGetPageGroup([webView _pageForTesting]), preferences.get());
818
819     NSURLRequest *requestWithAudio = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
820
821     [delegate setAllowedAutoplayQuirksForURL:^_WKWebsiteAutoplayQuirk(NSURL *url) {
822         return _WKWebsiteAutoplayQuirkSynthesizedPauseEvents;
823     }];
824     [delegate setAutoplayPolicyForURL:^(NSURL *) {
825         return _WKWebsiteAutoplayPolicyDeny;
826     }];
827     [webView loadRequest:requestWithAudio];
828     [webView waitForMessage:@"did-not-play"];
829     [webView waitForMessage:@"on-pause"];
830
831     receivedAutoplayEvent = WTF::nullopt;
832     [webView loadHTMLString:@"" baseURL:nil];
833
834     NSURLRequest *requestWithAudioInFrame = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check-in-iframe" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
835
836     [delegate setAllowedAutoplayQuirksForURL:^_WKWebsiteAutoplayQuirk(NSURL *url) {
837         if ([url.lastPathComponent isEqualToString:@"autoplay-check-frame.html"])
838             return _WKWebsiteAutoplayQuirkInheritedUserGestures;
839
840         return _WKWebsiteAutoplayQuirkSynthesizedPauseEvents | _WKWebsiteAutoplayQuirkInheritedUserGestures;
841     }];
842     [delegate setAutoplayPolicyForURL:^(NSURL *) {
843         return _WKWebsiteAutoplayPolicyDeny;
844     }];
845     [webView loadRequest:requestWithAudioInFrame];
846     [webView waitForMessage:@"did-not-play"];
847     [webView waitForMessage:@"on-pause"];
848 }
849 #endif // PLATFORM(MAC)
850
851 TEST(WebKit, InvalidCustomHeaders)
852 {
853     auto websitePolicies = adoptNS([[_WKWebsitePolicies alloc] init]);
854     [websitePolicies setCustomHeaderFields:@{@"invalidheader" : @"", @"noncustom" : @"header", @"    x-Custom ":@"  Needs Canonicalization\t ", @"x-other" : @"other value"}];
855     NSDictionary<NSString *, NSString *> *canonicalized = [websitePolicies customHeaderFields];
856     EXPECT_EQ(canonicalized.count, 2u);
857     EXPECT_STREQ([canonicalized objectForKey:@"x-Custom"].UTF8String, "Needs Canonicalization");
858     EXPECT_STREQ([canonicalized objectForKey:@"x-other"].UTF8String, "other value");
859 }
860
861 static bool firstTestDone;
862 static bool secondTestDone;
863 static bool thirdTestDone;
864 static bool fourthTestDone;
865
866 static void expectHeaders(id <WKURLSchemeTask> task, bool expected)
867 {
868     NSURLRequest *request = task.request;
869     if (expected) {
870         EXPECT_STREQ([[request valueForHTTPHeaderField:@"X-key1"] UTF8String], "value1");
871         EXPECT_STREQ([[request valueForHTTPHeaderField:@"X-key2"] UTF8String], "value2");
872     } else {
873         EXPECT_TRUE([request valueForHTTPHeaderField:@"X-key1"] == nil);
874         EXPECT_TRUE([request valueForHTTPHeaderField:@"X-key2"] == nil);
875     }
876 }
877
878 static void respond(id <WKURLSchemeTask>task, NSString *html = nil)
879 {
880     [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:html.length textEncodingName:nil] autorelease]];
881     [task didReceiveData:[html dataUsingEncoding:NSUTF8StringEncoding]];
882     [task didFinish];
883 }
884
885 @interface CustomHeaderFieldsDelegate : NSObject <WKNavigationDelegatePrivate, WKURLSchemeHandler>
886 @end
887
888 @implementation CustomHeaderFieldsDelegate
889
890 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
891 - (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
892 IGNORE_WARNINGS_END
893 {
894     _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
895     [websitePolicies setCustomHeaderFields:@{@"X-key1": @"value1", @"X-key2": @"value2"}];
896     if ([navigationAction.request.URL.path isEqualToString:@"/mainresource"]) {
897         dispatch_async(dispatch_get_main_queue(), ^{
898             decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
899         });
900     } else
901         decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
902 }
903
904 - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)urlSchemeTask
905 {
906     NSString *path = urlSchemeTask.request.URL.path;
907     if ([path isEqualToString:@"/mainresource"]) {
908         expectHeaders(urlSchemeTask, true);
909         respond(urlSchemeTask, @"<script>fetch('subresource').then(function(response){fetch('test://differentsecurityorigin/crossoriginsubresource',{mode:'no-cors'})})</script>");
910     } else if ([path isEqualToString:@"/subresource"]) {
911         expectHeaders(urlSchemeTask, true);
912         respond(urlSchemeTask);
913     } else if ([path isEqualToString:@"/crossoriginsubresource"]) {
914         expectHeaders(urlSchemeTask, false);
915         respond(urlSchemeTask);
916         firstTestDone = true;
917     } else if ([path isEqualToString:@"/mainresourcewithiframe"]) {
918         expectHeaders(urlSchemeTask, true);
919         respond(urlSchemeTask, @"<iframe src='test://iframeorigin/iframemainresource'></iframe>");
920     } else if ([path isEqualToString:@"/iframemainresource"]) {
921         expectHeaders(urlSchemeTask, false);
922         respond(urlSchemeTask, @"<script>fetch('iframesubresource').then(function(response){fetch('test://mainframeorigin/originaloriginsubresource',{mode:'no-cors'})})</script>");
923     } else if ([path isEqualToString:@"/iframesubresource"]) {
924         expectHeaders(urlSchemeTask, false);
925         respond(urlSchemeTask);
926     } else if ([path isEqualToString:@"/originaloriginsubresource"]) {
927         expectHeaders(urlSchemeTask, false);
928         respond(urlSchemeTask);
929         secondTestDone = true;
930     } else if ([path isEqualToString:@"/nestedtop"]) {
931         expectHeaders(urlSchemeTask, true);
932         respond(urlSchemeTask, @"<iframe src='test://otherorigin/nestedmid'></iframe>");
933     } else if ([path isEqualToString:@"/nestedmid"]) {
934         expectHeaders(urlSchemeTask, false);
935         respond(urlSchemeTask, @"<iframe src='test://toporigin/nestedbottom'></iframe>");
936     } else if ([path isEqualToString:@"/nestedbottom"]) {
937         expectHeaders(urlSchemeTask, true);
938         respond(urlSchemeTask);
939         thirdTestDone = true;
940     } else if ([path isEqualToString:@"/requestfromaboutblank"]) {
941         expectHeaders(urlSchemeTask, true);
942         respond(urlSchemeTask);
943         fourthTestDone = true;
944     } else
945         EXPECT_TRUE(false);
946 }
947
948 - (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)urlSchemeTask
949 {
950 }
951
952 @end
953
954 TEST(WebKit, CustomHeaderFields)
955 {
956     auto delegate = adoptNS([[CustomHeaderFieldsDelegate alloc] init]);
957     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
958     [configuration setURLSchemeHandler:delegate.get() forURLScheme:@"test"];
959     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
960     [webView setNavigationDelegate:delegate.get()];
961     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///mainresource"]]];
962     TestWebKitAPI::Util::run(&firstTestDone);
963     
964     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test://mainframeorigin/mainresourcewithiframe"]]];
965     TestWebKitAPI::Util::run(&secondTestDone);
966
967     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test://toporigin/nestedtop"]]];
968     TestWebKitAPI::Util::run(&thirdTestDone);
969 }
970
971 static unsigned loadCount;
972
973 @interface DataMappingSchemeHandler : NSObject <WKURLSchemeHandler> {
974     HashMap<String, RetainPtr<NSData>> _dataMappings;
975     Function<void(id <WKURLSchemeTask>)> _taskHandler;
976 }
977 - (void)addMappingFromURLString:(NSString *)urlString toData:(const char*)data;
978 - (void)setTaskHandler:(Function<void(id <WKURLSchemeTask>)>&&)handler;
979 @end
980
981 @implementation DataMappingSchemeHandler
982
983 - (void)addMappingFromURLString:(NSString *)urlString toData:(const char*)data
984 {
985     _dataMappings.set(urlString, [NSData dataWithBytesNoCopy:(void*)data length:strlen(data) freeWhenDone:NO]);
986 }
987
988 - (void)setTaskHandler:(Function<void(id <WKURLSchemeTask>)>&&)handler
989 {
990     _taskHandler = WTFMove(handler);
991 }
992
993 - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
994 {
995     NSURL *finalURL = task.request.URL;
996
997     ++loadCount;
998     if (_taskHandler)
999         _taskHandler(task);
1000
1001     auto response = adoptNS([[NSURLResponse alloc] initWithURL:finalURL MIMEType:@"text/html" expectedContentLength:1 textEncodingName:nil]);
1002     [task didReceiveResponse:response.get()];
1003
1004     if (auto data = _dataMappings.get([finalURL absoluteString]))
1005         [task didReceiveData:data.get()];
1006     else
1007         [task didReceiveData:[@"Hello" dataUsingEncoding:NSUTF8StringEncoding]];
1008     [task didFinish];
1009 }
1010
1011 - (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)task
1012 {
1013 }
1014
1015 @end
1016
1017 @interface CustomUserAgentDelegate : NSObject <WKNavigationDelegate> {
1018 }
1019 @end
1020
1021 @implementation CustomUserAgentDelegate
1022
1023 - (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction userInfo:(id <NSSecureCoding>)userInfo decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
1024 {
1025     _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
1026     if (navigationAction.targetFrame.mainFrame)
1027         [websitePolicies setCustomUserAgent:@"Foo Custom UserAgent"];
1028
1029     decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
1030 }
1031
1032 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
1033 {
1034     finishedNavigation = true;
1035 }
1036
1037 @end
1038
1039 static const char* customUserAgentMainFrameTestBytes = R"TESTRESOURCE(
1040 <script src="test://www.webkit.org/script.js"></script>
1041 <img src="test://www.webkit.org/image.png"></img>
1042 <iframe src="test://www.apple.com/subframe.html"></iframe>
1043 <script>
1044 onload = () => {
1045     setTimeout(() => {
1046         fetch("test://www.webkit.org/fetchResource.html");
1047     }, 0);
1048 }
1049 </script>
1050 )TESTRESOURCE";
1051
1052 static const char* customUserAgentSubFrameTestBytes = R"TESTRESOURCE(
1053 <script src="test://www.apple.com/script.js"></script>
1054 <img src="test://www.apple.com/image.png"></img>
1055 <iframe src="test://www.apple.com/subframe2.html"></iframe>
1056 <script>
1057 onload = () => {
1058     setTimeout(() => {
1059         fetch("test://www.apple.com/fetchResource.html");
1060     }, 0);
1061 }
1062 </script>
1063 )TESTRESOURCE";
1064
1065 TEST(WebKit, WebsitePoliciesCustomUserAgent)
1066 {
1067     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
1068
1069     auto schemeHandler = adoptNS([[DataMappingSchemeHandler alloc] init]);
1070     [schemeHandler addMappingFromURLString:@"test://www.webkit.org/main.html" toData:customUserAgentMainFrameTestBytes];
1071     [schemeHandler addMappingFromURLString:@"test://www.apple.com/subframe.html" toData:customUserAgentSubFrameTestBytes];
1072     [schemeHandler setTaskHandler:[](id <WKURLSchemeTask> task) {
1073         EXPECT_STREQ("Foo Custom UserAgent", [[task.request valueForHTTPHeaderField:@"User-Agent"] UTF8String]);
1074     }];
1075     [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"test"];
1076
1077     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
1078
1079     auto delegate = adoptNS([[CustomUserAgentDelegate alloc] init]);
1080     [webView setNavigationDelegate:delegate.get()];
1081
1082     loadCount = 0;
1083     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"test://www.webkit.org/main.html"]];
1084     [webView loadRequest:request];
1085
1086     TestWebKitAPI::Util::run(&finishedNavigation);
1087     finishedNavigation = false;
1088
1089     while (loadCount != 9U)
1090         TestWebKitAPI::Util::spinRunLoop();
1091     loadCount = 0;
1092
1093     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"test://www.google.com/main.html"]];
1094     [webView loadRequest:request];
1095
1096     TestWebKitAPI::Util::run(&finishedNavigation);
1097     finishedNavigation = false;
1098
1099     EXPECT_EQ(1U, loadCount);
1100     loadCount = 0;
1101 }
1102
1103 @interface CustomNavigatorPlatformDelegate : NSObject <WKNavigationDelegate> {
1104 }
1105 @end
1106
1107 @implementation CustomNavigatorPlatformDelegate
1108
1109 - (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction userInfo:(id <NSSecureCoding>)userInfo decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
1110 {
1111     _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
1112     if (navigationAction.targetFrame.mainFrame)
1113         [websitePolicies setCustomNavigatorPlatform:@"Test Custom Platform"];
1114
1115     decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
1116 }
1117
1118 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
1119 {
1120     finishedNavigation = true;
1121 }
1122
1123 @end
1124
1125 TEST(WebKit, WebsitePoliciesCustomNavigatorPlatform)
1126 {
1127     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
1128     
1129     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
1130
1131     auto delegate = adoptNS([[CustomNavigatorPlatformDelegate alloc] init]);
1132     [webView setNavigationDelegate:delegate.get()];
1133     
1134     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"data:text/html,hello"]];
1135     [webView loadRequest:request];
1136     
1137     TestWebKitAPI::Util::run(&finishedNavigation);
1138     finishedNavigation = false;
1139
1140     EXPECT_STREQ("Test Custom Platform", [[webView stringByEvaluatingJavaScript:@"navigator.platform"] UTF8String]);
1141 }
1142
1143 #if PLATFORM(IOS_FAMILY)
1144
1145 static const char* deviceOrientationEventTestBytes = R"TESTRESOURCE(
1146 <script>
1147 addEventListener("deviceorientation", (event) => {
1148     webkit.messageHandlers.testHandler.postMessage("received-device-orientation-event");
1149 });
1150 </script>
1151 )TESTRESOURCE";
1152
1153 @interface WebsitePoliciesDeviceOrientationDelegate : NSObject <WKNavigationDelegate> {
1154     BOOL _deviceOrientationEventEnabled;
1155 }
1156 - (instancetype)initWithDeviceOrientationEventEnabled:(BOOL)enabled;
1157 @end
1158
1159 @implementation WebsitePoliciesDeviceOrientationDelegate
1160
1161 - (instancetype)initWithDeviceOrientationEventEnabled:(BOOL)enabled
1162 {
1163     self = [super init];
1164     _deviceOrientationEventEnabled = enabled;
1165     return self;
1166 }
1167
1168 - (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction userInfo:(id <NSSecureCoding>)userInfo decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
1169 {
1170     _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
1171     [websitePolicies setDeviceOrientationEventEnabled:_deviceOrientationEventEnabled];
1172
1173     decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
1174 }
1175
1176 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
1177 {
1178     finishedNavigation = true;
1179 }
1180
1181 @end
1182
1183 static void runWebsitePoliciesDeviceOrientationEventTest(bool websitePolicyValue)
1184 {
1185     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
1186
1187     auto schemeHandler = adoptNS([[DataMappingSchemeHandler alloc] init]);
1188     [schemeHandler addMappingFromURLString:@"test://localhost/main.html" toData:deviceOrientationEventTestBytes];
1189     [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"test"];
1190
1191     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
1192
1193     auto delegate = adoptNS([[WebsitePoliciesDeviceOrientationDelegate alloc] initWithDeviceOrientationEventEnabled:websitePolicyValue]);
1194     [webView setNavigationDelegate:delegate.get()];
1195
1196     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"test://localhost/main.html"]];
1197     [webView loadRequest:request];
1198     TestWebKitAPI::Util::run(&finishedNavigation);
1199     finishedNavigation = false;
1200
1201     __block bool didReceiveMessage = false;
1202     [webView performAfterReceivingMessage:@"received-device-orientation-event" action:^{
1203         didReceiveMessage = true;
1204     }];
1205
1206     [webView _simulateDeviceOrientationChangeWithAlpha:1.0 beta:2.0 gamma:3.0];
1207
1208     if (websitePolicyValue)
1209         TestWebKitAPI::Util::run(&didReceiveMessage);
1210     else {
1211         TestWebKitAPI::Util::sleep(0.1);
1212         EXPECT_FALSE(didReceiveMessage);
1213     }
1214 }
1215
1216 TEST(WebKit, WebsitePoliciesDeviceOrientationEventEnabled)
1217 {
1218     runWebsitePoliciesDeviceOrientationEventTest(true);
1219 }
1220
1221 TEST(WebKit, WebsitePoliciesDeviceOrientationEventDisabled)
1222 {
1223     runWebsitePoliciesDeviceOrientationEventTest(false);
1224 }
1225
1226 #endif // PLATFORM(IOS_FAMILY)
1227
1228 @interface PopUpPoliciesDelegate : NSObject <WKNavigationDelegate, WKUIDelegatePrivate>
1229 @property (nonatomic, copy) _WKWebsitePopUpPolicy(^popUpPolicyForURL)(NSURL *);
1230 @end
1231
1232 @implementation PopUpPoliciesDelegate
1233
1234 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
1235 {
1236     // _webView:decidePolicyForNavigationAction:decisionHandler: should be called instead if it is implemented.
1237     EXPECT_TRUE(false);
1238     decisionHandler(WKNavigationActionPolicyAllow);
1239 }
1240
1241 - (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
1242 {
1243     _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
1244     if (_popUpPolicyForURL)
1245         websitePolicies.popUpPolicy = _popUpPolicyForURL(navigationAction.request.URL);
1246     decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
1247 }
1248
1249 - (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
1250 {
1251     return [[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration];
1252 }
1253
1254 @end
1255
1256 TEST(WebKit, WebsitePoliciesPopUp)
1257 {
1258     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
1259
1260     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
1261
1262     auto delegate = adoptNS([[PopUpPoliciesDelegate alloc] init]);
1263     [webView setNavigationDelegate:delegate.get()];
1264     [webView setUIDelegate:delegate.get()];
1265
1266     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"pop-up-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
1267
1268     [delegate setPopUpPolicyForURL:^_WKWebsitePopUpPolicy(NSURL *) {
1269         return _WKWebsitePopUpPolicyBlock;
1270     }];
1271
1272     [webView loadRequest:request];
1273     [webView waitForMessage:@"pop-up-blocked"];
1274
1275     [delegate setPopUpPolicyForURL:^_WKWebsitePopUpPolicy(NSURL *) {
1276         return _WKWebsitePopUpPolicyAllow;
1277     }];
1278
1279     [webView loadRequest:request];
1280     [webView waitForMessage:@"pop-up-allowed"];
1281 }
1282
1283 static bool done;
1284
1285 @interface WebsitePoliciesWebsiteDataStoreDelegate : NSObject <WKNavigationDelegatePrivate, WKURLSchemeHandler, WKUIDelegate>
1286 @end
1287
1288 @implementation WebsitePoliciesWebsiteDataStoreDelegate
1289
1290 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
1291 - (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
1292 IGNORE_WARNINGS_END
1293 {
1294     NSURL *url = navigationAction.request.URL;
1295     if ([url.path isEqualToString:@"/invalid"]) {
1296         _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
1297         websitePolicies.websiteDataStore = [[[WKWebsiteDataStore alloc] _initWithConfiguration:[[[_WKWebsiteDataStoreConfiguration alloc] init] autorelease]] autorelease];
1298
1299         bool sawException = false;
1300         @try {
1301             decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
1302         } @catch (NSException *exception) {
1303             sawException = true;
1304         }
1305         EXPECT_TRUE(sawException);
1306
1307         done = true;
1308     }
1309     if ([url.path isEqualToString:@"/checkStorage"]
1310         || [url.path isEqualToString:@"/checkCookies"]
1311         || [url.path isEqualToString:@"/mainFrame"]) {
1312         _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
1313         websitePolicies.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
1314         decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
1315     }
1316     if ([url.path isEqualToString:@"/subFrame"]) {
1317         _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
1318         websitePolicies.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
1319         bool sawException = false;
1320         @try {
1321             decisionHandler(WKNavigationActionPolicyCancel, websitePolicies);
1322         } @catch (NSException *exception) {
1323             sawException = true;
1324         }
1325         EXPECT_TRUE(sawException);
1326         done = true;
1327     }
1328 }
1329
1330 - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
1331 {
1332     NSURL *url = task.request.URL;
1333     if ([url.path isEqualToString:@"/checkStorage"]) {
1334         NSString *html = @"<script>var oldValue = window.sessionStorage['storageKey']; window.sessionStorage['storageKey'] = 'value'; alert('old value: <' + (oldValue ? 'fail' : '') + '>');</script>";
1335         [task didReceiveResponse:[[NSURLResponse alloc] initWithURL:url MIMEType:@"text/html" expectedContentLength:html.length textEncodingName:nil]];
1336         [task didReceiveData:[html dataUsingEncoding:NSUTF8StringEncoding]];
1337         [task didFinish];
1338     }
1339 }
1340
1341 - (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)urlSchemeTask
1342 {
1343 }
1344
1345 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
1346 {
1347     EXPECT_STREQ(message.UTF8String, "old value: <>");
1348     completionHandler();
1349     done = true;
1350 }
1351
1352 @end
1353
1354 RetainPtr<WKWebView> websiteDataStoreTestWebView()
1355 {
1356     auto delegate = adoptNS([[WebsitePoliciesWebsiteDataStoreDelegate alloc] init]);
1357     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
1358     [configuration setURLSchemeHandler:delegate.get() forURLScheme:@"test"];
1359     [configuration setWebsiteDataStore:[WKWebsiteDataStore nonPersistentDataStore]];
1360     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
1361     [webView setNavigationDelegate:delegate.get()];
1362     [webView setUIDelegate:delegate.get()];
1363     return webView;
1364 }
1365
1366 TEST(WebKit, UpdateWebsitePoliciesInvalid)
1367 {
1368     auto webView = websiteDataStoreTestWebView();
1369     auto policies = adoptNS([[_WKWebsitePolicies alloc] init]);
1370     [policies setWebsiteDataStore:[WKWebsiteDataStore nonPersistentDataStore]];
1371     bool sawException = false;
1372     @try {
1373         [webView _updateWebsitePolicies:policies.get()];
1374     } @catch (NSException *exception) {
1375         sawException = true;
1376     }
1377     EXPECT_TRUE(sawException);
1378     
1379     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///invalid"]]];
1380     TestWebKitAPI::Util::run(&done);
1381     
1382     done = false;
1383     [webView loadHTMLString:@"<iframe src='subFrame'></iframe>" baseURL:[NSURL URLWithString:@"http://webkit.org/mainFrame"]];
1384     TestWebKitAPI::Util::run(&done);
1385 }
1386
1387 TEST(WebKit, WebsitePoliciesDataStore)
1388 {
1389     auto cookieWebView = websiteDataStoreTestWebView();
1390     NSString *alertOldCookie = @"<script>var oldCookie = document.cookie; document.cookie = 'key=value'; alert('old value: <' + oldCookie + '>');</script>";
1391     [cookieWebView loadHTMLString:alertOldCookie baseURL:[NSURL URLWithString:@"http://example.com/checkCookies"]];
1392     TestWebKitAPI::Util::run(&done);
1393     done = false;
1394     [cookieWebView loadHTMLString:alertOldCookie baseURL:[NSURL URLWithString:@"http://example.com/checkCookies"]];
1395     TestWebKitAPI::Util::run(&done);
1396 }
1397
1398 #endif // WK_API_ENABLED