Change autoplay state to "prevented" when media is paused due to restrictions.
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKit2Cocoa / 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/WKPagePrivate.h>
31 #import <WebKit/WKPreferencesRefPrivate.h>
32 #import <WebKit/WKUserContentControllerPrivate.h>
33 #import <WebKit/WKWebViewPrivate.h>
34 #import <WebKit/_WKUserContentExtensionStorePrivate.h>
35 #import <WebKit/_WKWebsitePolicies.h>
36 #import <wtf/MainThread.h>
37 #import <wtf/RetainPtr.h>
38
39 #if PLATFORM(IOS)
40 #import <WebKit/WKWebViewConfigurationPrivate.h>
41 #endif
42
43 #if WK_API_ENABLED
44
45 @interface WKWebView ()
46 - (WKPageRef)_pageForTesting;
47 @end
48
49 static bool doneCompiling;
50 static bool receivedAlert;
51
52 #if PLATFORM(MAC)
53 static std::optional<WKAutoplayEvent> receivedAutoplayEvent;
54 #endif
55
56 static size_t alertCount;
57
58 @interface ContentBlockingWebsitePoliciesDelegate : NSObject <WKNavigationDelegate, WKUIDelegate>
59 @end
60
61 @implementation ContentBlockingWebsitePoliciesDelegate
62
63 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
64 {
65     // _webView:decidePolicyForNavigationAction:decisionHandler: should be called instead if it is implemented.
66     EXPECT_TRUE(false);
67     decisionHandler(WKNavigationActionPolicyAllow);
68 }
69
70 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
71 {
72     switch (alertCount++) {
73     case 0:
74         // Default behavior.
75         EXPECT_STREQ("content blockers enabled", message.UTF8String);
76         break;
77     case 1:
78         // After having set websitePolicies.contentBlockersEnabled to false.
79         EXPECT_STREQ("content blockers disabled", message.UTF8String);
80         break;
81     case 2:
82         // After having reloaded without content blockers.
83         EXPECT_STREQ("content blockers disabled", message.UTF8String);
84         break;
85     default:
86         EXPECT_TRUE(false);
87     }
88     receivedAlert = true;
89     completionHandler();
90 }
91
92 - (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
93 {
94     _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
95     switch (alertCount) {
96     case 0:
97         // Verify the content blockers behave correctly with the default behavior.
98         break;
99     case 1:
100         {
101             // Verify disabling content blockers works correctly.
102             websitePolicies.contentBlockersEnabled = false;
103             
104             // Verify calling the decisionHandler asynchronously works correctly.
105             auto decisionHandlerCopy = Block_copy(decisionHandler);
106             callOnMainThread([decisionHandlerCopy, websitePolicies = RetainPtr<_WKWebsitePolicies>(websitePolicies)] {
107                 decisionHandlerCopy(WKNavigationActionPolicyAllow, websitePolicies.get());
108                 Block_release(decisionHandlerCopy);
109             });
110         }
111         return;
112     case 2:
113         // Verify enabling content blockers has no effect when reloading without content blockers.
114         websitePolicies.contentBlockersEnabled = true;
115         break;
116     default:
117         EXPECT_TRUE(false);
118     }
119     decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
120 }
121
122 @end
123
124 TEST(WebKit2, WebsitePoliciesContentBlockersEnabled)
125 {
126     [[_WKUserContentExtensionStore defaultStore] _removeAllContentExtensions];
127
128     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
129
130     doneCompiling = false;
131     NSString* contentBlocker = @"[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]";
132     [[_WKUserContentExtensionStore defaultStore] compileContentExtensionForIdentifier:@"WebsitePoliciesTest" encodedContentExtension:contentBlocker completionHandler:^(_WKUserContentFilter *filter, NSError *error) {
133         EXPECT_TRUE(error == nil);
134         [[configuration userContentController] _addUserContentFilter:filter];
135         doneCompiling = true;
136     }];
137     TestWebKitAPI::Util::run(&doneCompiling);
138
139     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
140
141     auto delegate = adoptNS([[ContentBlockingWebsitePoliciesDelegate alloc] init]);
142     [webView setNavigationDelegate:delegate.get()];
143     [webView setUIDelegate:delegate.get()];
144
145     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"contentBlockerCheck" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
146     alertCount = 0;
147     receivedAlert = false;
148     [webView loadRequest:request];
149     TestWebKitAPI::Util::run(&receivedAlert);
150
151     receivedAlert = false;
152     [webView reload];
153     TestWebKitAPI::Util::run(&receivedAlert);
154
155     receivedAlert = false;
156     [webView _reloadWithoutContentBlockers];
157     TestWebKitAPI::Util::run(&receivedAlert);
158
159     [[_WKUserContentExtensionStore defaultStore] _removeAllContentExtensions];
160 }
161
162 @interface AutoplayPoliciesDelegate : NSObject <WKNavigationDelegate, WKUIDelegate>
163 @property (nonatomic, copy) _WKWebsiteAutoplayPolicy(^autoplayPolicyForURL)(NSURL *);
164 @property (nonatomic) BOOL allowsAutoplayQuirks;
165 @end
166
167 @implementation AutoplayPoliciesDelegate
168
169 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
170 {
171     // _webView:decidePolicyForNavigationAction:decisionHandler: should be called instead if it is implemented.
172     EXPECT_TRUE(false);
173     decisionHandler(WKNavigationActionPolicyAllow);
174 }
175
176 - (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
177 {
178     _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
179     websitePolicies.allowsAutoplayQuirks = _allowsAutoplayQuirks;
180     if (_autoplayPolicyForURL)
181         websitePolicies.autoplayPolicy = _autoplayPolicyForURL(navigationAction.request.URL);
182     decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
183 }
184
185 @end
186
187 TEST(WebKit2, WebsitePoliciesAutoplayEnabled)
188 {
189     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
190
191 #if PLATFORM(IOS)
192     [configuration setAllowsInlineMediaPlayback:YES];
193 #endif
194
195     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
196
197     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
198     [webView setNavigationDelegate:delegate.get()];
199
200     NSURLRequest *requestWithAudio = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
201     NSURLRequest *requestWithoutAudio = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-no-audio-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
202
203     // iOS does not support volume changes to media elements.
204 #if PLATFORM(MAC)
205     NSURLRequest *requestWithoutVolume = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-zero-volume-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
206 #endif
207
208     [delegate setAutoplayPolicyForURL:^(NSURL *) {
209         return _WKWebsiteAutoplayPolicyAllowWithoutSound;
210     }];
211     [webView loadRequest:requestWithAudio];
212     [webView waitForMessage:@"did-not-play"];
213
214     [webView loadRequest:requestWithoutAudio];
215     [webView waitForMessage:@"autoplayed"];
216
217 #if PLATFORM(MAC)
218     [webView loadRequest:requestWithoutVolume];
219     [webView waitForMessage:@"autoplayed"];
220 #endif
221
222     [delegate setAutoplayPolicyForURL:^(NSURL *) {
223         return _WKWebsiteAutoplayPolicyDeny;
224     }];
225
226 #if PLATFORM(MAC)
227     [webView loadRequest:requestWithoutVolume];
228     [webView waitForMessage:@"did-not-play"];
229 #endif
230
231     [webView loadRequest:requestWithAudio];
232     [webView waitForMessage:@"did-not-play"];
233
234     // Test updating website policies.
235     _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
236     websitePolicies.autoplayPolicy = _WKWebsiteAutoplayPolicyAllow;
237     [webView _updateWebsitePolicies:websitePolicies];
238     [webView stringByEvaluatingJavaScript:@"playVideo()"];
239     [webView waitForMessage:@"autoplayed"];
240
241     [webView loadRequest:requestWithoutAudio];
242     [webView waitForMessage:@"did-not-play"];
243
244     [delegate setAutoplayPolicyForURL:^(NSURL *) {
245         return _WKWebsiteAutoplayPolicyAllow;
246     }];
247     [webView loadRequest:requestWithAudio];
248     [webView waitForMessage:@"autoplayed"];
249
250     [webView loadRequest:requestWithoutAudio];
251     [webView waitForMessage:@"autoplayed"];
252
253 #if PLATFORM(MAC)
254     [webView loadRequest:requestWithoutVolume];
255     [webView waitForMessage:@"autoplayed"];
256 #endif
257
258     NSURLRequest *requestWithAudioInIFrame = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check-in-iframe" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
259
260     // If the top-level document allows autoplay, any iframes should also autoplay.
261     [delegate setAutoplayPolicyForURL:^(NSURL *url) {
262         if ([url.lastPathComponent isEqualToString:@"autoplay-check-in-iframe.html"])
263             return _WKWebsiteAutoplayPolicyAllow;
264         return _WKWebsiteAutoplayPolicyDeny;
265     }];
266
267     [webView loadRequest:requestWithAudioInIFrame];
268     [webView waitForMessage:@"autoplayed"];
269
270     // If the top-level document disallows autoplay, any iframes should also not autoplay.
271     [delegate setAutoplayPolicyForURL:^(NSURL *url) {
272         if ([url.lastPathComponent isEqualToString:@"autoplay-check-in-iframe.html"])
273             return _WKWebsiteAutoplayPolicyDeny;
274         return _WKWebsiteAutoplayPolicyAllow;
275     }];
276
277     [webView loadRequest:requestWithAudioInIFrame];
278     [webView waitForMessage:@"did-not-play"];
279 }
280
281 #if PLATFORM(MAC)
282 static void handleAutoplayEvent(WKPageRef page, WKAutoplayEvent event, const void* clientInfo)
283 {
284     receivedAutoplayEvent = event;
285 }
286
287 static void runUntilReceivesAutoplayEvent(WKAutoplayEvent event)
288 {
289     while (!receivedAutoplayEvent || *receivedAutoplayEvent != event)
290         CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, true);
291 }
292
293 TEST(WebKit2, WebsitePoliciesPlayAfterPreventedAutoplay)
294 {
295     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
296     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 336, 276) configuration:configuration.get()]);
297
298     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
299     [delegate setAutoplayPolicyForURL:^(NSURL *) {
300         return _WKWebsiteAutoplayPolicyDeny;
301     }];
302     [webView setNavigationDelegate:delegate.get()];
303
304     WKPageUIClientV9 uiClient;
305     memset(&uiClient, 0, sizeof(uiClient));
306
307     uiClient.base.version = 9;
308     uiClient.handleAutoplayEvent = handleAutoplayEvent;
309
310     WKPageSetPageUIClient([webView _pageForTesting], &uiClient.base);
311     NSPoint playButtonClickPoint = NSMakePoint(20, 256);
312
313     receivedAutoplayEvent = std::nullopt;
314     NSURLRequest *jsPlayRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"js-play-with-controls" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
315     [webView loadRequest:jsPlayRequest];
316     [webView waitForMessage:@"loaded"];
317     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPreventFromAutoplaying);
318
319     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
320     [webView mouseUpAtPoint:playButtonClickPoint];
321     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPlayMediaPreventedFromAutoplaying);
322
323     receivedAutoplayEvent = std::nullopt;
324     [webView loadHTMLString:@"" baseURL:nil];
325
326     NSURLRequest *autoplayRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-with-controls" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
327     [webView loadRequest:autoplayRequest];
328     [webView waitForMessage:@"loaded"];
329     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPreventFromAutoplaying);
330
331     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
332     [webView mouseUpAtPoint:playButtonClickPoint];
333     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPlayMediaPreventedFromAutoplaying);
334
335     receivedAutoplayEvent = std::nullopt;
336     [webView loadHTMLString:@"" baseURL:nil];
337
338     NSURLRequest *noAutoplayRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"no-autoplay-with-controls" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
339     [webView loadRequest:noAutoplayRequest];
340     [webView waitForMessage:@"loaded"];
341     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
342     [webView mouseUpAtPoint:playButtonClickPoint];
343     [webView waitForMessage:@"played"];
344     ASSERT_TRUE(receivedAutoplayEvent == std::nullopt);
345
346     receivedAutoplayEvent = std::nullopt;
347     [webView loadHTMLString:@"" baseURL:nil];
348
349     [delegate setAutoplayPolicyForURL:^(NSURL *) {
350         return _WKWebsiteAutoplayPolicyAllowWithoutSound;
351     }];
352
353     NSURLRequest *autoplayMutedRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-muted-with-controls" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
354     [webView loadRequest:autoplayMutedRequest];
355     [webView waitForMessage:@"loaded"];
356     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPreventFromAutoplaying);
357
358     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
359     [webView mouseUpAtPoint:playButtonClickPoint];
360     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPlayMediaPreventedFromAutoplaying);
361 }
362
363 TEST(WebKit2, WebsitePoliciesPlayingWithoutInterference)
364 {
365     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
366     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 336, 276) configuration:configuration.get()]);
367
368     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
369     [delegate setAutoplayPolicyForURL:^(NSURL *) {
370         return _WKWebsiteAutoplayPolicyAllow;
371     }];
372     [webView setNavigationDelegate:delegate.get()];
373
374     WKPageUIClientV9 uiClient;
375     memset(&uiClient, 0, sizeof(uiClient));
376
377     uiClient.base.version = 9;
378     uiClient.handleAutoplayEvent = handleAutoplayEvent;
379
380     WKPageSetPageUIClient([webView _pageForTesting], &uiClient.base);
381
382     receivedAutoplayEvent = std::nullopt;
383     NSURLRequest *jsPlayRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"js-play-with-controls" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
384     [webView loadRequest:jsPlayRequest];
385     [webView waitForMessage:@"playing"];
386
387     ASSERT_TRUE(receivedAutoplayEvent == std::nullopt);
388
389     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"about:blank"]]];
390     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidEndMediaPlaybackWithoutUserInterference);
391
392     receivedAutoplayEvent = std::nullopt;
393     [webView loadRequest:jsPlayRequest];
394     [webView waitForMessage:@"ended"];
395     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidEndMediaPlaybackWithoutUserInterference);
396 }
397
398 TEST(WebKit2, WebsitePoliciesUserInterferenceWithPlaying)
399 {
400     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
401     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 336, 276) configuration:configuration.get()]);
402
403     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
404     [delegate setAutoplayPolicyForURL:^(NSURL *) {
405         return _WKWebsiteAutoplayPolicyAllow;
406     }];
407     [webView setNavigationDelegate:delegate.get()];
408
409     WKPageUIClientV9 uiClient;
410     memset(&uiClient, 0, sizeof(uiClient));
411
412     uiClient.base.version = 9;
413     uiClient.handleAutoplayEvent = handleAutoplayEvent;
414
415     WKPageSetPageUIClient([webView _pageForTesting], &uiClient.base);
416
417     receivedAutoplayEvent = std::nullopt;
418     NSURLRequest *jsPlayRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"js-play-with-controls" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
419     [webView loadRequest:jsPlayRequest];
420     [webView waitForMessage:@"playing"];
421     ASSERT_TRUE(receivedAutoplayEvent == std::nullopt);
422
423     WKPageSetMuted([webView _pageForTesting], kWKMediaAudioMuted);
424     runUntilReceivesAutoplayEvent(kWKAutoplayEventUserDidInterfereWithPlayback);
425
426     receivedAutoplayEvent = std::nullopt;
427     [webView loadRequest:jsPlayRequest];
428     [webView waitForMessage:@"playing"];
429     ASSERT_TRUE(receivedAutoplayEvent == std::nullopt);
430
431     const NSPoint muteButtonClickPoint = NSMakePoint(80, 256);
432     [webView mouseDownAtPoint:muteButtonClickPoint simulatePressure:NO];
433     [webView mouseUpAtPoint:muteButtonClickPoint];
434     runUntilReceivesAutoplayEvent(kWKAutoplayEventUserDidInterfereWithPlayback);
435
436     receivedAutoplayEvent = std::nullopt;
437     [webView loadRequest:jsPlayRequest];
438     [webView waitForMessage:@"playing"];
439     ASSERT_TRUE(receivedAutoplayEvent == std::nullopt);
440
441     const NSPoint playButtonClickPoint = NSMakePoint(20, 256);
442     [webView mouseDownAtPoint:playButtonClickPoint simulatePressure:NO];
443     [webView mouseUpAtPoint:playButtonClickPoint];
444     runUntilReceivesAutoplayEvent(kWKAutoplayEventUserDidInterfereWithPlayback);
445 }
446
447 TEST(WebKit2, WebsitePoliciesUserNeverPlayedMediaPreventedFromPlaying)
448 {
449     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
450     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 336, 276) configuration:configuration.get()]);
451
452     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
453     [delegate setAutoplayPolicyForURL:^(NSURL *) {
454         return _WKWebsiteAutoplayPolicyDeny;
455     }];
456     [webView setNavigationDelegate:delegate.get()];
457
458     WKPageUIClientV9 uiClient;
459     memset(&uiClient, 0, sizeof(uiClient));
460
461     uiClient.base.version = 9;
462     uiClient.handleAutoplayEvent = handleAutoplayEvent;
463
464     WKPageSetPageUIClient([webView _pageForTesting], &uiClient.base);
465
466     receivedAutoplayEvent = std::nullopt;
467     NSURLRequest *jsPlayRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"js-play-with-controls" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
468     [webView loadRequest:jsPlayRequest];
469     [webView waitForMessage:@"loaded"];
470     runUntilReceivesAutoplayEvent(kWKAutoplayEventDidPreventFromAutoplaying);
471
472     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"about:blank"]]];
473     runUntilReceivesAutoplayEvent(kWKAutoplayEventUserNeverPlayedMediaPreventedFromPlaying);
474 }
475
476 TEST(WebKit2, WebsitePoliciesAutoplayQuirks)
477 {
478     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
479     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
480
481     auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
482     [webView setNavigationDelegate:delegate.get()];
483
484     WKRetainPtr<WKPreferencesRef> preferences(AdoptWK, WKPreferencesCreate());
485     WKPreferencesSetNeedsSiteSpecificQuirks(preferences.get(), true);
486     WKPageGroupSetPreferences(WKPageGetPageGroup([webView _pageForTesting]), preferences.get());
487
488     NSURLRequest *requestWithAudio = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
489
490     [delegate setAllowsAutoplayQuirks:YES];
491     [delegate setAutoplayPolicyForURL:^(NSURL *) {
492         return _WKWebsiteAutoplayPolicyDeny;
493     }];
494     [webView loadRequest:requestWithAudio];
495     [webView waitForMessage:@"did-not-play"];
496     [webView waitForMessage:@"on-pause"];
497 }
498 #endif
499
500 #endif