749c97ff96c327afe68a705b7f40b4f8701a1278
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKitCocoa / _WKWebAuthenticationPanel.mm
1 /*
2  * Copyright (C) 2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "Test.h"
28
29 #if ENABLE(WEB_AUTHN)
30
31 #import "PlatformUtilities.h"
32 #import "TCPServer.h"
33 #import "TestWKWebView.h"
34 #import "WKWebViewConfigurationExtras.h"
35 #import <LocalAuthentication/LocalAuthentication.h>
36 #import <WebKit/WKPreferencesPrivate.h>
37 #import <WebKit/WKUIDelegatePrivate.h>
38 #import <WebKit/_WKExperimentalFeature.h>
39 #import <WebKit/_WKWebAuthenticationAssertionResponse.h>
40 #import <WebKit/_WKWebAuthenticationPanel.h>
41 #import <wtf/BlockPtr.h>
42 #import <wtf/RandomNumber.h>
43 #import <wtf/spi/cocoa/SecuritySPI.h>
44 #import <wtf/text/StringConcatenateNumbers.h>
45
46 static bool webAuthenticationPanelRan = false;
47 static bool webAuthenticationPanelFailed = false;
48 static bool webAuthenticationPanelSucceded = false;
49 static bool webAuthenticationPanelUpdateMultipleNFCTagsPresent = false;
50 static bool webAuthenticationPanelUpdateNoCredentialsFound = false;
51 static bool webAuthenticationPanelUpdatePINBlocked = false;
52 static bool webAuthenticationPanelUpdatePINAuthBlocked = false;
53 static bool webAuthenticationPanelUpdatePINInvalid = false;
54 static bool webAuthenticationPanelUpdateLAError = false;
55 static bool webAuthenticationPanelUpdateLAExcludeCredentialsMatched = false;
56 static bool webAuthenticationPanelUpdateLANoCredential = false;
57 static bool webAuthenticationPanelCancelImmediately = false;
58 static _WKLocalAuthenticatorPolicy localAuthenticatorPolicy = _WKLocalAuthenticatorPolicyDisallow;
59 static String webAuthenticationPanelPin;
60 static BOOL webAuthenticationPanelNullUserHandle = NO;
61 static String testES256PrivateKeyBase64 =
62     "BDj/zxSkzKgaBuS3cdWDF558of8AaIpgFpsjF/Qm1749VBJPgqUIwfhWHJ91nb7U"
63     "PH76c0+WFOzZKslPyyFse4goGIW2R7k9VHLPEZl5nfnBgEVFh5zev+/xpHQIvuq6"
64     "RQ==";
65 static String testUserhandleBase64 = "AAECAwQFBgcICQ==";
66
67 @interface TestWebAuthenticationPanelDelegate : NSObject <_WKWebAuthenticationPanelDelegate>
68 @end
69
70 @implementation TestWebAuthenticationPanelDelegate
71
72 - (void)panel:(_WKWebAuthenticationPanel *)panel updateWebAuthenticationPanel:(_WKWebAuthenticationPanelUpdate)update
73 {
74     ASSERT_NE(panel, nil);
75     if (webAuthenticationPanelCancelImmediately)
76         [panel cancel];
77
78     if (update == _WKWebAuthenticationPanelUpdateMultipleNFCTagsPresent) {
79         webAuthenticationPanelUpdateMultipleNFCTagsPresent = true;
80         return;
81     }
82     if (update == _WKWebAuthenticationPanelUpdateNoCredentialsFound) {
83         webAuthenticationPanelUpdateNoCredentialsFound = true;
84         return;
85     }
86     if (update == _WKWebAuthenticationPanelUpdatePINBlocked) {
87         webAuthenticationPanelUpdatePINBlocked = true;
88         return;
89     }
90     if (update == _WKWebAuthenticationPanelUpdatePINAuthBlocked) {
91         webAuthenticationPanelUpdatePINAuthBlocked = true;
92         return;
93     }
94     if (update == _WKWebAuthenticationPanelUpdatePINInvalid) {
95         webAuthenticationPanelUpdatePINInvalid = true;
96         return;
97     }
98     if (update == _WKWebAuthenticationPanelUpdateLAError) {
99         webAuthenticationPanelUpdateLAError = true;
100         return;
101     }
102     if (update == _WKWebAuthenticationPanelUpdateLAExcludeCredentialsMatched) {
103         webAuthenticationPanelUpdateLAExcludeCredentialsMatched = true;
104         return;
105     }
106     if (update == _WKWebAuthenticationPanelUpdateLANoCredential) {
107         webAuthenticationPanelUpdateLANoCredential = true;
108         return;
109     }
110 }
111
112 - (void)panel:(_WKWebAuthenticationPanel *)panel dismissWebAuthenticationPanelWithResult:(_WKWebAuthenticationResult)result
113 {
114     ASSERT_NE(panel, nil);
115     if (webAuthenticationPanelCancelImmediately)
116         [panel cancel];
117
118     if (result == _WKWebAuthenticationResultFailed) {
119         webAuthenticationPanelFailed = true;
120         return;
121     }
122     if (result == _WKWebAuthenticationResultSucceeded) {
123         webAuthenticationPanelSucceded = true;
124         return;
125     }
126 }
127
128 - (void)panel:(_WKWebAuthenticationPanel *)panel requestPINWithRemainingRetries:(NSUInteger)retries completionHandler:(void (^)(NSString *))completionHandler
129 {
130     ASSERT_NE(panel, nil);
131     EXPECT_EQ(retries, 8ul);
132     completionHandler(webAuthenticationPanelPin);
133 }
134
135 - (void)panel:(_WKWebAuthenticationPanel *)panel selectAssertionResponse:(NSArray < _WKWebAuthenticationAssertionResponse *> *)responses source:(_WKWebAuthenticationSource)source completionHandler:(void (^)(_WKWebAuthenticationAssertionResponse *))completionHandler
136 {
137     if (responses.count == 1) {
138         completionHandler(responses[0]);
139         return;
140     }
141
142     EXPECT_EQ(source, _WKWebAuthenticationSourceExternal);
143     EXPECT_EQ(responses.count, 2ul);
144     for (_WKWebAuthenticationAssertionResponse *response in responses) {
145         EXPECT_TRUE([response.name isEqual:@"johnpsmith@example.com"] || [response.name isEqual:@""]);
146         EXPECT_TRUE([response.displayName isEqual:@"John P. Smith"] || [response.displayName isEqual:@""]);
147         EXPECT_TRUE([[response.userHandle base64EncodedStringWithOptions:0] isEqual:@"MIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGTMII="] || !response.userHandle);
148     }
149
150     auto index = weakRandomUint32() % 2;
151     webAuthenticationPanelNullUserHandle = responses[index].userHandle ? NO : YES;
152     completionHandler(responses[index]);
153 }
154
155 - (void)panel:(_WKWebAuthenticationPanel *)panel decidePolicyForLocalAuthenticatorWithCompletionHandler:(void (^)(_WKLocalAuthenticatorPolicy policy))completionHandler
156 {
157     completionHandler(localAuthenticatorPolicy);
158 }
159
160 @end
161
162 @interface TestWebAuthenticationPanelFakeDelegate : NSObject <_WKWebAuthenticationPanelDelegate>
163 @end
164
165 @implementation TestWebAuthenticationPanelFakeDelegate
166 @end
167
168 @interface TestWebAuthenticationPanelUIDelegate : NSObject <WKUIDelegatePrivate>
169 @property bool isRacy;
170 @property bool isFake;
171 @property bool isNull;
172
173 - (instancetype)init;
174 @end
175
176 @implementation TestWebAuthenticationPanelUIDelegate {
177     RetainPtr<NSObject<_WKWebAuthenticationPanelDelegate>> _delegate;
178     BlockPtr<void(_WKWebAuthenticationPanelResult)> _callback;
179     RetainPtr<WKFrameInfo> _frameInfo;
180     RetainPtr<_WKWebAuthenticationPanel> _panel;
181 }
182
183 - (instancetype)init
184 {
185     if (self = [super init]) {
186         self.isRacy = false;
187         self.isFake = false;
188         self.isNull = false;
189     }
190     return self;
191 }
192
193 - (void)_webView:(WKWebView *)webView runWebAuthenticationPanel:(_WKWebAuthenticationPanel *)panel initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(_WKWebAuthenticationPanelResult))completionHandler
194 {
195     webAuthenticationPanelRan = true;
196     _frameInfo = frame;
197
198     if (!_isNull) {
199         if (!_isFake)
200             _delegate = adoptNS([[TestWebAuthenticationPanelDelegate alloc] init]);
201         else
202             _delegate = adoptNS([[TestWebAuthenticationPanelFakeDelegate alloc] init]);
203     }
204     ASSERT_NE(panel, nil);
205     _panel = panel;
206     [_panel setDelegate:_delegate.get()];
207
208     if (_isRacy) {
209         if (!_callback) {
210             _callback = makeBlockPtr(completionHandler);
211             return;
212         }
213         _callback(_WKWebAuthenticationPanelResultUnavailable);
214     }
215     completionHandler(_WKWebAuthenticationPanelResultPresented);
216 }
217
218 - (WKFrameInfo *)frame
219 {
220     return _frameInfo.get();
221 }
222
223 - (_WKWebAuthenticationPanel *)panel
224 {
225     return _panel.get();
226 }
227
228 @end
229
230 namespace TestWebKitAPI {
231
232 namespace {
233
234 const char parentFrame[] = "<html><iframe id='theFrame' src='iFrame.html'></iframe></html>";
235 const char subFrame[] =
236 "<html>"
237 "<input type='text' id='input'>"
238 "<script>"
239 "    if (window.internals) {"
240 "        internals.setMockWebAuthenticationConfiguration({ hid: { expectCancel: true } });"
241 "        internals.withUserGesture(() => { input.focus(); });"
242 "    }"
243 "    const options = {"
244 "        publicKey: {"
245 "            challenge: new Uint8Array(16)"
246 "        }"
247 "    };"
248 "    navigator.credentials.get(options);"
249 "</script>"
250 "</html>";
251
252 static _WKExperimentalFeature *webAuthenticationExperimentalFeature()
253 {
254     static RetainPtr<_WKExperimentalFeature> theFeature;
255     if (theFeature)
256         return theFeature.get();
257
258     NSArray *features = [WKPreferences _experimentalFeatures];
259     for (_WKExperimentalFeature *feature in features) {
260         if ([feature.key isEqual:@"WebAuthenticationEnabled"]) {
261             theFeature = feature;
262             break;
263         }
264     }
265     return theFeature.get();
266 }
267
268 #if USE(APPLE_INTERNAL_SDK) || PLATFORM(IOS)
269 static _WKExperimentalFeature *webAuthenticationLocalAuthenticatorExperimentalFeature()
270 {
271     static RetainPtr<_WKExperimentalFeature> theFeature;
272     if (theFeature)
273         return theFeature.get();
274
275     NSArray *features = [WKPreferences _experimentalFeatures];
276     for (_WKExperimentalFeature *feature in features) {
277         if ([feature.key isEqual:@"WebAuthenticationLocalAuthenticatorEnabled"]) {
278             theFeature = feature;
279             break;
280         }
281     }
282     return theFeature.get();
283 }
284 #endif // USE(APPLE_INTERNAL_SDK) || PLATFORM(IOS)
285
286 static void reset()
287 {
288     webAuthenticationPanelRan = false;
289     webAuthenticationPanelFailed = false;
290     webAuthenticationPanelSucceded = false;
291     webAuthenticationPanelUpdateMultipleNFCTagsPresent = false;
292     webAuthenticationPanelUpdateNoCredentialsFound = false;
293     webAuthenticationPanelUpdatePINBlocked = false;
294     webAuthenticationPanelUpdatePINAuthBlocked = false;
295     webAuthenticationPanelUpdatePINInvalid = false;
296     webAuthenticationPanelUpdateLAError = false;
297     webAuthenticationPanelUpdateLAExcludeCredentialsMatched = false;
298     webAuthenticationPanelUpdateLANoCredential = false;
299     webAuthenticationPanelCancelImmediately = false;
300     webAuthenticationPanelPin = emptyString();
301     webAuthenticationPanelNullUserHandle = NO;
302     localAuthenticatorPolicy = _WKLocalAuthenticatorPolicyDisallow;
303 }
304
305 static void checkPanel(_WKWebAuthenticationPanel *panel, NSString *relyingPartyID, NSArray *transports, _WKWebAuthenticationType type)
306 {
307     EXPECT_WK_STREQ(panel.relyingPartyID, relyingPartyID);
308
309     EXPECT_EQ(panel.transports.count, transports.count);
310     size_t count = 0;
311     for (NSNumber *transport : transports) {
312         if ([panel.transports containsObject:transport])
313             count++;
314     }
315     EXPECT_EQ(count, transports.count);
316
317     EXPECT_EQ(panel.type, type);
318 }
319
320 static void checkFrameInfo(WKFrameInfo *frame, bool isMainFrame, NSString *url, NSString *protocol, NSString *host, int port, WKWebView *webView)
321 {
322     EXPECT_EQ(frame.mainFrame, isMainFrame);
323     EXPECT_TRUE([frame.request.URL.absoluteString isEqual:url]);
324     EXPECT_WK_STREQ(frame.securityOrigin.protocol, protocol);
325     EXPECT_WK_STREQ(frame.securityOrigin.host, host);
326     EXPECT_EQ(frame.securityOrigin.port, port);
327     EXPECT_EQ(frame.webView, webView);
328 }
329
330 #if USE(APPLE_INTERNAL_SDK) || PLATFORM(IOS)
331
332 bool addKeyToKeychain(const String& privateKeyBase64, const String& rpId, const String& userHandleBase64)
333 {
334     NSDictionary* options = @{
335         (id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom,
336         (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
337         (id)kSecAttrKeySizeInBits: @256,
338     };
339     CFErrorRef errorRef = nullptr;
340     auto key = adoptCF(SecKeyCreateWithData(
341         (__bridge CFDataRef)adoptNS([[NSData alloc] initWithBase64EncodedString:privateKeyBase64 options:NSDataBase64DecodingIgnoreUnknownCharacters]).get(),
342         (__bridge CFDictionaryRef)options,
343         &errorRef
344     ));
345     if (errorRef)
346         return false;
347
348     NSDictionary* addQuery = @{
349         (id)kSecValueRef: (id)key.get(),
350         (id)kSecClass: (id)kSecClassKey,
351         (id)kSecAttrLabel: rpId,
352         (id)kSecAttrApplicationTag: adoptNS([[NSData alloc] initWithBase64EncodedString:userHandleBase64 options:NSDataBase64DecodingIgnoreUnknownCharacters]).get(),
353         (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock,
354 #if HAVE(DATA_PROTECTION_KEYCHAIN)
355         (id)kSecUseDataProtectionKeychain: @YES
356 #else
357         (id)kSecAttrNoLegacy: @YES
358 #endif
359     };
360     OSStatus status = SecItemAdd((__bridge CFDictionaryRef)addQuery, NULL);
361     if (status)
362         return false;
363
364     return true;
365 }
366
367 void cleanUpKeychain(const String& rpId)
368 {
369     NSDictionary* deleteQuery = @{
370         (id)kSecClass: (id)kSecClassKey,
371         (id)kSecAttrLabel: rpId,
372         (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock,
373 #if HAVE(DATA_PROTECTION_KEYCHAIN)
374         (id)kSecUseDataProtectionKeychain: @YES
375 #else
376         (id)kSecAttrNoLegacy: @YES
377 #endif
378     };
379     SecItemDelete((__bridge CFDictionaryRef)deleteQuery);
380 }
381
382 #endif // USE(APPLE_INTERNAL_SDK) || PLATFORM(IOS)
383
384 } // namesapce;
385
386 TEST(WebAuthenticationPanel, NoPanelTimeout)
387 {
388     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-nfc" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
389
390     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
391     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
392
393     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
394
395     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
396     [webView waitForMessage:@"Operation timed out."];
397 }
398
399 TEST(WebAuthenticationPanel, NoPanelHidSuccess)
400 {
401     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
402
403     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
404     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
405
406     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
407
408     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
409     [webView waitForMessage:@"Succeeded!"];
410 }
411
412 TEST(WebAuthenticationPanel, PanelTimeout)
413 {
414     reset();
415     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
416
417     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
418     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
419
420     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
421     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
422     [webView setUIDelegate:delegate.get()];
423
424     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
425     Util::run(&webAuthenticationPanelRan);
426     Util::run(&webAuthenticationPanelFailed);
427 }
428
429 TEST(WebAuthenticationPanel, PanelHidSuccess1)
430 {
431     reset();
432     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
433
434     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
435     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
436
437     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
438     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
439     [webView setUIDelegate:delegate.get()];
440
441     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
442     Util::run(&webAuthenticationPanelRan);
443     Util::run(&webAuthenticationPanelSucceded);
444
445     // A bit of extra checks.
446     checkFrameInfo([delegate frame], true, [testURL absoluteString], @"file", @"", 0, webView.get());
447     checkPanel([delegate panel], @"", @[adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportUSB]).get()], _WKWebAuthenticationTypeGet);
448 }
449
450 TEST(WebAuthenticationPanel, PanelHidSuccess2)
451 {
452     reset();
453     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
454
455     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
456     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
457
458     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
459     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
460     [webView setUIDelegate:delegate.get()];
461
462     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
463     Util::run(&webAuthenticationPanelRan);
464     Util::run(&webAuthenticationPanelSucceded);
465
466     // A bit of extra checks.
467     checkPanel([delegate panel], @"", @[adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportUSB]).get()], _WKWebAuthenticationTypeCreate);
468 }
469
470 #if HAVE(NEAR_FIELD)
471 // This test aims to see if the callback for the first ceremony could affect the second one.
472 // Therefore, the first callback will be held to return at the time when the second arrives.
473 // The first callback will return _WKWebAuthenticationPanelResultUnavailable which leads to timeout for NFC.
474 // The second callback will return _WKWebAuthenticationPanelResultPresented which leads to success.
475 TEST(WebAuthenticationPanel, PanelRacy1)
476 {
477     reset();
478     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-nfc" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
479
480     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
481     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
482
483     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
484     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
485     [delegate setIsRacy:true];
486     [webView setUIDelegate:delegate.get()];
487
488     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
489     Util::run(&webAuthenticationPanelRan);
490     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
491     [webView waitForMessage:@"Succeeded!"];
492
493     // A bit of extra checks.
494     checkPanel([delegate panel], @"", @[adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportNFC]).get()], _WKWebAuthenticationTypeGet);
495 }
496
497 // Unlike the previous one, this one focuses on the order of the delegate callbacks.
498 TEST(WebAuthenticationPanel, PanelRacy2)
499 {
500     reset();
501     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-nfc" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
502
503     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
504     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
505
506     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
507     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
508     [delegate setIsRacy:true];
509     [webView setUIDelegate:delegate.get()];
510
511     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
512     Util::run(&webAuthenticationPanelRan);
513     webAuthenticationPanelRan = false;
514     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
515     Util::run(&webAuthenticationPanelFailed);
516     Util::run(&webAuthenticationPanelRan);
517     Util::run(&webAuthenticationPanelSucceded);
518 }
519 #endif // HAVE(NEAR_FIELD)
520
521 TEST(WebAuthenticationPanel, PanelTwice)
522 {
523     reset();
524     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
525
526     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
527     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
528
529     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
530     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
531     [webView setUIDelegate:delegate.get()];
532
533     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
534     Util::run(&webAuthenticationPanelRan);
535     Util::run(&webAuthenticationPanelSucceded);
536
537     reset();
538     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
539     Util::run(&webAuthenticationPanelRan);
540     Util::run(&webAuthenticationPanelSucceded);
541 }
542
543 TEST(WebAuthenticationPanel, ReloadHidCancel)
544 {
545     reset();
546     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-cancel" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
547
548     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
549     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
550
551     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
552     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
553     [webView setUIDelegate:delegate.get()];
554
555     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
556     Util::run(&webAuthenticationPanelRan);
557     [webView reload];
558     Util::run(&webAuthenticationPanelFailed);
559 }
560
561 TEST(WebAuthenticationPanel, LocationChangeHidCancel)
562 {
563     reset();
564     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-cancel" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
565     RetainPtr<NSURL> otherURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
566
567     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
568     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
569
570     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
571     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
572     [webView setUIDelegate:delegate.get()];
573
574     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
575     Util::run(&webAuthenticationPanelRan);
576     [webView evaluateJavaScript: [NSString stringWithFormat:@"location = '%@'", [otherURL absoluteString]] completionHandler:nil];
577     Util::run(&webAuthenticationPanelFailed);
578 }
579
580 TEST(WebAuthenticationPanel, NewLoadHidCancel)
581 {
582     reset();
583     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-cancel" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
584     RetainPtr<NSURL> otherURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
585
586     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
587     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
588
589     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
590     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
591     [webView setUIDelegate:delegate.get()];
592
593     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
594     Util::run(&webAuthenticationPanelRan);
595     [webView loadRequest:[NSURLRequest requestWithURL:otherURL.get()]];
596     Util::run(&webAuthenticationPanelFailed);
597 }
598
599 TEST(WebAuthenticationPanel, CloseHidCancel)
600 {
601     reset();
602     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-cancel" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
603
604     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
605     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
606
607     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
608     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
609     [webView setUIDelegate:delegate.get()];
610
611     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
612     Util::run(&webAuthenticationPanelRan);
613     [webView _close];
614     Util::run(&webAuthenticationPanelFailed);
615 }
616
617 TEST(WebAuthenticationPanel, SubFrameChangeLocationHidCancel)
618 {
619     TCPServer server([parentFrame = String(parentFrame), subFrame = String(subFrame)] (int socket) {
620         NSString *firstResponse = [NSString stringWithFormat:
621             @"HTTP/1.1 200 OK\r\n"
622             "Content-Length: %d\r\n\r\n"
623             "%@",
624             parentFrame.length(),
625             (id)parentFrame
626         ];
627         NSString *secondResponse = [NSString stringWithFormat:
628             @"HTTP/1.1 200 OK\r\n"
629             "Content-Length: %d\r\n\r\n"
630             "%@",
631             subFrame.length(),
632             (id)subFrame
633         ];
634
635         TCPServer::read(socket);
636         TCPServer::write(socket, firstResponse.UTF8String, firstResponse.length);
637         TCPServer::read(socket);
638         TCPServer::write(socket, secondResponse.UTF8String, secondResponse.length);
639     });
640
641     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
642     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
643
644     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
645     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
646     [webView setUIDelegate:delegate.get()];
647
648     auto port = static_cast<unsigned>(server.port());
649     auto url = makeString("http://localhost:", port);
650     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:(id)url]]];
651     Util::run(&webAuthenticationPanelRan);
652     [webView evaluateJavaScript:@"theFrame.src = 'simple.html'" completionHandler:nil];
653     Util::run(&webAuthenticationPanelFailed);
654
655     // A bit of extra checks.
656     checkFrameInfo([delegate frame], false, (id)makeString(url, "/iFrame.html"), @"http", @"localhost", port, webView.get());
657     checkPanel([delegate panel], @"localhost", @[adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportUSB]).get()], _WKWebAuthenticationTypeGet);
658 }
659
660 TEST(WebAuthenticationPanel, SubFrameDestructionHidCancel)
661 {
662     TCPServer server([parentFrame = String(parentFrame), subFrame = String(subFrame)] (int socket) {
663         NSString *firstResponse = [NSString stringWithFormat:
664             @"HTTP/1.1 200 OK\r\n"
665             "Content-Length: %d\r\n\r\n"
666             "%@",
667             parentFrame.length(),
668             (id)parentFrame
669         ];
670         NSString *secondResponse = [NSString stringWithFormat:
671             @"HTTP/1.1 200 OK\r\n"
672             "Content-Length: %d\r\n\r\n"
673             "%@",
674             subFrame.length(),
675             (id)subFrame
676         ];
677
678         TCPServer::read(socket);
679         TCPServer::write(socket, firstResponse.UTF8String, firstResponse.length);
680         TCPServer::read(socket);
681         TCPServer::write(socket, secondResponse.UTF8String, secondResponse.length);
682     });
683
684     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
685     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
686
687     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
688     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
689     [webView setUIDelegate:delegate.get()];
690
691     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:(id)makeString("http://localhost:", static_cast<unsigned>(server.port()))]]];
692     Util::run(&webAuthenticationPanelRan);
693     [webView evaluateJavaScript:@"theFrame.parentNode.removeChild(theFrame)" completionHandler:nil];
694     Util::run(&webAuthenticationPanelFailed);
695 }
696
697 TEST(WebAuthenticationPanel, PanelHidCancel)
698 {
699     reset();
700     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-cancel" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
701
702     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
703     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
704
705     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
706     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
707     [webView setUIDelegate:delegate.get()];
708
709     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
710     Util::run(&webAuthenticationPanelRan);
711     [[delegate panel] cancel];
712     [webView waitForMessage:@"This request has been cancelled by the user."];
713     EXPECT_TRUE(webAuthenticationPanelFailed);
714 }
715
716 TEST(WebAuthenticationPanel, PanelHidCtapNoCredentialsFound)
717 {
718     reset();
719     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-no-credentials" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
720
721     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
722     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
723
724     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
725     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
726     [webView setUIDelegate:delegate.get()];
727
728     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
729     Util::run(&webAuthenticationPanelRan);
730     Util::run(&webAuthenticationPanelUpdateNoCredentialsFound);
731 }
732
733 TEST(WebAuthenticationPanel, PanelU2fCtapNoCredentialsFound)
734 {
735     reset();
736     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-u2f-no-credentials" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
737
738     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
739     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
740
741     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
742     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
743     [webView setUIDelegate:delegate.get()];
744
745     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
746     Util::run(&webAuthenticationPanelRan);
747     Util::run(&webAuthenticationPanelUpdateNoCredentialsFound);
748 }
749
750 TEST(WebAuthenticationPanel, FakePanelHidSuccess)
751 {
752     reset();
753     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
754
755     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
756     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
757
758     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
759     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
760     [delegate setIsFake:true];
761     [webView setUIDelegate:delegate.get()];
762
763     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
764     Util::run(&webAuthenticationPanelRan);
765     [webView waitForMessage:@"Succeeded!"];
766 }
767
768 TEST(WebAuthenticationPanel, FakePanelHidCtapNoCredentialsFound)
769 {
770     reset();
771     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-no-credentials" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
772
773     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
774     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
775
776     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
777     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
778     [delegate setIsFake:true];
779     [webView setUIDelegate:delegate.get()];
780
781     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
782     Util::run(&webAuthenticationPanelRan);
783     [webView waitForMessage:@"Operation timed out."];
784 }
785
786 TEST(WebAuthenticationPanel, NullPanelHidSuccess)
787 {
788     reset();
789     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
790
791     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
792     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
793
794     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
795     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
796     [delegate setIsNull:true];
797     [webView setUIDelegate:delegate.get()];
798
799     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
800     Util::run(&webAuthenticationPanelRan);
801     [webView waitForMessage:@"Succeeded!"];
802 }
803
804 TEST(WebAuthenticationPanel, NullPanelHidCtapNoCredentialsFound)
805 {
806     reset();
807     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-no-credentials" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
808
809     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
810     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
811
812     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
813     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
814     [delegate setIsNull:true];
815     [webView setUIDelegate:delegate.get()];
816
817     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
818     Util::run(&webAuthenticationPanelRan);
819     [webView waitForMessage:@"Operation timed out."];
820 }
821
822 #if HAVE(NEAR_FIELD)
823 TEST(WebAuthenticationPanel, PanelMultipleNFCTagsPresent)
824 {
825     reset();
826     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-nfc-multiple-tags" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
827
828     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
829     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
830
831     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
832     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
833     [webView setUIDelegate:delegate.get()];
834
835     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
836     Util::run(&webAuthenticationPanelRan);
837     Util::run(&webAuthenticationPanelUpdateMultipleNFCTagsPresent);
838 }
839 #endif
840
841 TEST(WebAuthenticationPanel, PanelHidCancelReloadNoCrash)
842 {
843     reset();
844     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-cancel" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
845
846     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
847     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
848
849     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
850     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
851     [webView setUIDelegate:delegate.get()];
852
853     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
854     Util::run(&webAuthenticationPanelRan);
855     [[delegate panel] cancel];
856     [webView reload];
857     [webView waitForMessage:@"Operation timed out."];
858 }
859
860 TEST(WebAuthenticationPanel, PanelHidSuccessCancelNoCrash)
861 {
862     reset();
863     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
864
865     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
866     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
867
868     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
869     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
870     [webView setUIDelegate:delegate.get()];
871     webAuthenticationPanelCancelImmediately = true;
872
873     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
874     [webView waitForMessage:@"Succeeded!"];
875 }
876
877 TEST(WebAuthenticationPanel, PanelHidCtapNoCredentialsFoundCancelNoCrash)
878 {
879     reset();
880     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-no-credentials" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
881
882     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
883     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
884
885     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
886     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
887     [webView setUIDelegate:delegate.get()];
888     webAuthenticationPanelCancelImmediately = true;
889
890     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
891     Util::run(&webAuthenticationPanelUpdateNoCredentialsFound);
892 }
893
894 TEST(WebAuthenticationPanel, PinGetRetriesError)
895 {
896     reset();
897     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin-get-retries-error" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
898
899     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
900     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
901
902     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
903     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
904     [webView waitForMessage:@"Unknown internal error. Error code: 2"];
905 }
906
907 TEST(WebAuthenticationPanel, PinGetKeyAgreementError)
908 {
909     reset();
910     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin-get-key-agreement-error" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
911
912     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
913     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
914
915     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
916     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
917     [webView waitForMessage:@"Unknown internal error. Error code: 2"];
918 }
919
920 TEST(WebAuthenticationPanel, PinRequestPinErrorNoDelegate)
921 {
922     reset();
923     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
924
925     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
926     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
927
928     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
929     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
930     [webView waitForMessage:@"Pin is not valid: "];
931 }
932
933 TEST(WebAuthenticationPanel, PinRequestPinErrorNullDelegate)
934 {
935     reset();
936     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
937
938     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
939     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
940
941     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
942     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
943     [delegate setIsNull:true];
944     [webView setUIDelegate:delegate.get()];
945
946     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
947     [webView waitForMessage:@"Pin is not valid: "];
948 }
949
950 TEST(WebAuthenticationPanel, PinRequestPinError)
951 {
952     reset();
953     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
954
955     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
956     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
957
958     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
959     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
960     [webView setUIDelegate:delegate.get()];
961
962     webAuthenticationPanelPin = "123";
963     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
964     [webView waitForMessage:@"Pin is not valid: 123"];
965 }
966
967 TEST(WebAuthenticationPanel, PinGetPinTokenPinBlockedError)
968 {
969     reset();
970     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin-get-pin-token-pin-blocked-error" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
971
972     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
973     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
974
975     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
976     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
977     [webView setUIDelegate:delegate.get()];
978
979     webAuthenticationPanelPin = "1234";
980     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
981     [webView waitForMessage:@"Unknown internal error. Error code: 50"];
982     EXPECT_FALSE(webAuthenticationPanelUpdatePINInvalid);
983     EXPECT_TRUE(webAuthenticationPanelUpdatePINBlocked);
984 }
985
986 TEST(WebAuthenticationPanel, PinGetPinTokenPinAuthBlockedError)
987 {
988     reset();
989     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin-get-pin-token-pin-auth-blocked-error" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
990
991     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
992     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
993
994     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
995     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
996     [webView setUIDelegate:delegate.get()];
997
998     webAuthenticationPanelPin = "1234";
999     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1000     [webView waitForMessage:@"Unknown internal error. Error code: 52"];
1001     EXPECT_FALSE(webAuthenticationPanelUpdatePINInvalid);
1002     EXPECT_TRUE(webAuthenticationPanelUpdatePINAuthBlocked);
1003 }
1004
1005 TEST(WebAuthenticationPanel, PinGetPinTokenPinInvalidErrorAndRetry)
1006 {
1007     reset();
1008     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin-get-pin-token-pin-invalid-error-retry" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1009
1010     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1011     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1012
1013     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1014     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1015     [webView setUIDelegate:delegate.get()];
1016
1017     webAuthenticationPanelPin = "1234";
1018     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1019     [webView waitForMessage:@"Succeeded!"];
1020     EXPECT_TRUE(webAuthenticationPanelUpdatePINInvalid);
1021 }
1022
1023 TEST(WebAuthenticationPanel, PinGetPinTokenPinAuthInvalidErrorAndRetry)
1024 {
1025     reset();
1026     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin-get-pin-token-pin-auth-invalid-error-retry" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1027
1028     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1029     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1030
1031     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1032     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1033     [webView setUIDelegate:delegate.get()];
1034
1035     webAuthenticationPanelPin = "1234";
1036     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1037     [webView waitForMessage:@"Succeeded!"];
1038     EXPECT_TRUE(webAuthenticationPanelUpdatePINInvalid);
1039 }
1040
1041 TEST(WebAuthenticationPanel, MakeCredentialPin)
1042 {
1043     reset();
1044     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1045
1046     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1047     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1048
1049     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1050     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1051     [webView setUIDelegate:delegate.get()];
1052
1053     webAuthenticationPanelPin = "1234";
1054     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1055     [webView waitForMessage:@"Succeeded!"];
1056 }
1057
1058 TEST(WebAuthenticationPanel, MakeCredentialPinAuthBlockedError)
1059 {
1060     reset();
1061     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin-auth-blocked-error" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1062
1063     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1064     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1065
1066     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1067     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1068     [webView setUIDelegate:delegate.get()];
1069
1070     webAuthenticationPanelPin = "1234";
1071     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1072     [webView waitForMessage:@"Unknown internal error. Error code: 52"];
1073     EXPECT_FALSE(webAuthenticationPanelUpdatePINInvalid);
1074     EXPECT_TRUE(webAuthenticationPanelUpdatePINAuthBlocked);
1075 }
1076
1077 TEST(WebAuthenticationPanel, MakeCredentialPinInvalidErrorAndRetry)
1078 {
1079     reset();
1080     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin-invalid-error-retry" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1081
1082     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1083     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1084
1085     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1086     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1087     [webView setUIDelegate:delegate.get()];
1088
1089     webAuthenticationPanelPin = "1234";
1090     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1091     [webView waitForMessage:@"Succeeded!"];
1092     EXPECT_TRUE(webAuthenticationPanelUpdatePINInvalid);
1093 }
1094
1095 TEST(WebAuthenticationPanel, GetAssertionPin)
1096 {
1097     reset();
1098     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-pin" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1099
1100     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1101     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1102
1103     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1104     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1105     [webView setUIDelegate:delegate.get()];
1106
1107     webAuthenticationPanelPin = "1234";
1108     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1109     [webView waitForMessage:@"Succeeded!"];
1110 }
1111
1112 TEST(WebAuthenticationPanel, GetAssertionPinAuthBlockedError)
1113 {
1114     reset();
1115     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-pin-auth-blocked-error" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1116
1117     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1118     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1119
1120     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1121     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1122     [webView setUIDelegate:delegate.get()];
1123
1124     webAuthenticationPanelPin = "1234";
1125     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1126     [webView waitForMessage:@"Unknown internal error. Error code: 52"];
1127     EXPECT_FALSE(webAuthenticationPanelUpdatePINInvalid);
1128     EXPECT_TRUE(webAuthenticationPanelUpdatePINAuthBlocked);
1129 }
1130
1131 TEST(WebAuthenticationPanel, GetAssertionPinInvalidErrorAndRetry)
1132 {
1133     reset();
1134     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-pin-invalid-error-retry" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1135
1136     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1137     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1138
1139     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1140     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1141     [webView setUIDelegate:delegate.get()];
1142
1143     webAuthenticationPanelPin = "1234";
1144     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1145     [webView waitForMessage:@"Succeeded!"];
1146     EXPECT_TRUE(webAuthenticationPanelUpdatePINInvalid);
1147 }
1148
1149 TEST(WebAuthenticationPanel, MultipleAccountsNullDelegate)
1150 {
1151     reset();
1152     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-multiple-accounts" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1153
1154     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1155     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1156
1157     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1158     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1159     [delegate setIsNull:true];
1160     [webView setUIDelegate:delegate.get()];
1161
1162     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1163     [webView waitForMessage:@"Operation timed out."];
1164 }
1165
1166 TEST(WebAuthenticationPanel, MultipleAccounts)
1167 {
1168     reset();
1169     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-multiple-accounts" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1170
1171     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1172     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1173
1174     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1175     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1176     [webView setUIDelegate:delegate.get()];
1177
1178     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1179     [webView waitForMessage:@"Succeeded!"];
1180     EXPECT_EQ([[webView stringByEvaluatingJavaScript:@"userHandle"] isEqualToString:@"<null>"], webAuthenticationPanelNullUserHandle);
1181 }
1182
1183 // For macOS, only internal builds can sign keychain entitlemnets
1184 // which are required to run local authenticator tests.
1185 #if USE(APPLE_INTERNAL_SDK) || PLATFORM(IOS)
1186
1187 TEST(WebAuthenticationPanel, LAError)
1188 {
1189     reset();
1190     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-la-error" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1191
1192     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1193     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1194     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationLocalAuthenticatorExperimentalFeature()];
1195
1196     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1197     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1198     [webView setUIDelegate:delegate.get()];
1199
1200     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1201     Util::run(&webAuthenticationPanelUpdateLAError);
1202 }
1203
1204 TEST(WebAuthenticationPanel, LADuplicateCredential)
1205 {
1206     reset();
1207     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-la-duplicate-credential" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1208
1209     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1210     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1211     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationLocalAuthenticatorExperimentalFeature()];
1212
1213     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1214     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1215     [webView setUIDelegate:delegate.get()];
1216
1217     ASSERT_TRUE(addKeyToKeychain(testES256PrivateKeyBase64, "", testUserhandleBase64));
1218     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1219     Util::run(&webAuthenticationPanelUpdateLAExcludeCredentialsMatched);
1220     cleanUpKeychain("");
1221 }
1222
1223 TEST(WebAuthenticationPanel, LANoCredential)
1224 {
1225     reset();
1226     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-la" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1227
1228     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1229     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1230     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationLocalAuthenticatorExperimentalFeature()];
1231
1232     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1233     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1234     [webView setUIDelegate:delegate.get()];
1235
1236     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1237     Util::run(&webAuthenticationPanelUpdateLANoCredential);
1238 }
1239
1240 TEST(WebAuthenticationPanel, LAMakeCredentialNullDelegate)
1241 {
1242     reset();
1243     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-la" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1244
1245     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1246     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1247     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationLocalAuthenticatorExperimentalFeature()];
1248
1249     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1250     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1251     [delegate setIsNull:true];
1252     [webView setUIDelegate:delegate.get()];
1253
1254     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1255     [webView waitForMessage:@"Disallow local authenticator."];
1256 }
1257
1258 TEST(WebAuthenticationPanel, LAMakeCredentialDisallowLocalAuthenticator)
1259 {
1260     reset();
1261     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-la" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1262
1263     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1264     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1265     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationLocalAuthenticatorExperimentalFeature()];
1266
1267     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1268     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1269     [webView setUIDelegate:delegate.get()];
1270
1271     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1272     [webView waitForMessage:@"Disallow local authenticator."];
1273 }
1274
1275 TEST(WebAuthenticationPanel, LAMakeCredentialAllowLocalAuthenticator)
1276 {
1277     reset();
1278     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-la" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1279
1280     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1281     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1282     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationLocalAuthenticatorExperimentalFeature()];
1283
1284     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1285     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1286     [webView setUIDelegate:delegate.get()];
1287
1288     localAuthenticatorPolicy = _WKLocalAuthenticatorPolicyAllow;
1289     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1290     [webView waitForMessage:@"Succeeded!"];
1291     checkPanel([delegate panel], @"", @[adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportUSB]).get(), adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportInternal]).get()], _WKWebAuthenticationTypeCreate);
1292     cleanUpKeychain("");
1293 }
1294
1295 TEST(WebAuthenticationPanel, LAGetAssertion)
1296 {
1297     reset();
1298     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-la" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
1299
1300     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
1301     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
1302     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationLocalAuthenticatorExperimentalFeature()];
1303
1304     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
1305     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
1306     [webView setUIDelegate:delegate.get()];
1307
1308     ASSERT_TRUE(addKeyToKeychain(testES256PrivateKeyBase64, "", testUserhandleBase64));
1309     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
1310     [webView waitForMessage:@"Succeeded!"];
1311     checkPanel([delegate panel], @"", @[adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportUSB]).get(), adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportInternal]).get()], _WKWebAuthenticationTypeGet);
1312     cleanUpKeychain("");
1313 }
1314
1315 #endif // USE(APPLE_INTERNAL_SDK) || PLATFORM(IOS)
1316
1317 } // namespace TestWebKitAPI
1318
1319 #endif // ENABLE(WEB_AUTHN)