Source/WebKit/ChangeLog

 12020-01-10 Jiewen Tan <jiewen_tan@apple.com>
 2
 3 [WebAuthn] Implement SPI to tell UI clients to select assertion responses
 4 https://bugs.webkit.org/show_bug.cgi?id=206112
 5 <rdar://problem/58495733>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Covered by API tests.
 10
 11 This patch adds a new delegate method in _WKWebAuthenticationPanelDelegate to tell UI clients to
 12 select an assertion response when multiple are returned from an authenticator. Here is the SPI:
 13 @protocol _WKWebAuthenticationPanelDelegate <NSObject>
 14 @optional
 15 ...
 16 - (void)panel:(_WKWebAuthenticationPanel *)panel selectAssertionResponses:(NSArray < _WKWebAuthenticationAssertionResponse *> *)responses completionHandler:(void (^)(_WKWebAuthenticationAssertionResponse *))completionHandler;
 17 ...
 18 @end
 19
 20 A new interface is introduced to represent an authenticator assertion response:
 21 @interface _WKWebAuthenticationAssertionResponse : NSObject
 22 @property (nonatomic, readonly, copy) NSString *name;
 23 @property (nonatomic, readonly, copy) NSString *displayName;
 24 @property (nonatomic, readonly, copy) NSData *userHandle;
 25 @end
 26 Only members that can assist users to make a decision are exposed to UI clients.
 27
 28 * Shared/API/APIObject.h:
 29 * Shared/Cocoa/APIObject.mm:
 30 (API::Object::newObject):
 31 * Sources.txt:
 32 * SourcesCocoa.txt:
 33 * UIProcess/API/APIWebAuthenticationAssertionResponse.cpp: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h.
 34 (API::WebAuthenticationAssertionResponse::create):
 35 (API::WebAuthenticationAssertionResponse::WebAuthenticationAssertionResponse):
 36 * UIProcess/API/APIWebAuthenticationAssertionResponse.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h.
 37 * UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h.
 38 * UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.mm: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h.
 39 (-[_WKWebAuthenticationAssertionResponse dealloc]):
 40 (-[_WKWebAuthenticationAssertionResponse name]):
 41 (-[_WKWebAuthenticationAssertionResponse displayName]):
 42 (-[_WKWebAuthenticationAssertionResponse userHandle]):
 43 (-[_WKWebAuthenticationAssertionResponse _apiObject]):
 44 * UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponseInternal.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h.
 45 * UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h:
 46 * UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm:
 47 * UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h:
 48 * UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm:
 49 (WebKit::WebAuthenticationPanelClient::WebAuthenticationPanelClient):
 50 (WebKit::WebAuthenticationPanelClient::selectAssertionResponses const):
 51 * WebKit.xcodeproj/project.pbxproj:
 52
1532020-01-06 Jiewen Tan <jiewen_tan@apple.com>
254
355 [WebAuthn] Support CTAP Client Pin

Source/WebKit/Shared/API/APIObject.h

@@public:
183183#endif
184184
185185#if ENABLE(WEB_AUTHN)
 186 WebAuthenticationAssertionResponse,
186187 WebAuthenticationPanel,
187188#endif
188189

Source/WebKit/Shared/Cocoa/APIObject.mm

8888#import "_WKUserInitiatedActionInternal.h"
8989#import "_WKUserStyleSheetInternal.h"
9090#import "_WKVisitedLinkStoreInternal.h"
 91#import "_WKWebAuthenticationAssertionResponseInternal.h"
9192#import "_WKWebAuthenticationPanelInternal.h"
9293#import "_WKWebsiteDataStoreConfigurationInternal.h"
9394

@@void* Object::newObject(size_t size, Type type)
389390 case Type::WebAuthenticationPanel:
390391 wrapper = [_WKWebAuthenticationPanel alloc];
391392 break;
 393 case Type::WebAuthenticationAssertionResponse:
 394 wrapper = [_WKWebAuthenticationAssertionResponse alloc];
 395 break;
392396#endif
393397
394398 case Type::BundleFrame:

Source/WebKit/Sources.txt

@@UIProcess/API/APIURLSchemeTask.cpp
338338UIProcess/API/APIUserContentWorld.cpp
339339UIProcess/API/APIUserScript.cpp
340340UIProcess/API/APIUserStyleSheet.cpp
 341UIProcess/API/APIWebAuthenticationAssertionResponse.cpp
341342UIProcess/API/APIWebAuthenticationPanel.cpp
342343UIProcess/API/APIWebsitePolicies.cpp
343344UIProcess/API/APIWindowFeatures.cpp

Source/WebKit/SourcesCocoa.txt

@@UIProcess/API/Cocoa/_WKUserContentWorld.mm
278278UIProcess/API/Cocoa/_WKUserInitiatedAction.mm
279279UIProcess/API/Cocoa/_WKUserStyleSheet.mm
280280UIProcess/API/Cocoa/_WKVisitedLinkStore.mm
 281UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.mm
281282UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm
282283UIProcess/API/Cocoa/_WKWebsiteDataSize.mm
283284UIProcess/API/Cocoa/_WKWebsiteDataStore.mm

Source/WebKit/UIProcess/API/APIResourceLoadClient.h

2525
2626#pragma once
2727
 28#include <WebCore/ResourceError.h>
 29#include <WebCore/ResourceRequest.h>
 30#include <WebCore/ResourceResponse.h>
 31
2832namespace WebKit {
2933class AuthenticationChallengeProxy;
3034struct ResourceLoadInfo;

Source/WebKit/UIProcess/API/APIWebAuthenticationAssertionResponse.cpp

 1/*
 2 * Copyright (C) 2020 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#include "APIWebAuthenticationAssertionResponse.h"
 28
 29#if ENABLE(WEB_AUTHN)
 30
 31namespace API {
 32using namespace WebCore;
 33
 34Ref<WebAuthenticationAssertionResponse> WebAuthenticationAssertionResponse::create(Ref<WebCore::AuthenticatorAssertionResponse>&& response)
 35{
 36 return adoptRef(*new WebAuthenticationAssertionResponse(WTFMove(response)));
 37}
 38
 39WebAuthenticationAssertionResponse::WebAuthenticationAssertionResponse(Ref<WebCore::AuthenticatorAssertionResponse>&& response)
 40 : m_response(WTFMove(response))
 41{
 42}
 43
 44WebAuthenticationAssertionResponse::~WebAuthenticationAssertionResponse() = default;
 45
 46} // namespace API
 47
 48#endif // ENABLE(WEB_AUTHN)

Source/WebKit/UIProcess/API/APIWebAuthenticationAssertionResponse.h

 1/*
 2 * Copyright (C) 2020 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#pragma once
 27
 28#if ENABLE(WEB_AUTHN)
 29
 30#include "APIObject.h"
 31#include <WebCore/AuthenticatorAssertionResponse.h>
 32
 33namespace API {
 34
 35class WebAuthenticationAssertionResponse final : public ObjectImpl<Object::Type::WebAuthenticationAssertionResponse> {
 36public:
 37 static Ref<WebAuthenticationAssertionResponse> create(Ref<WebCore::AuthenticatorAssertionResponse>&&);
 38 ~WebAuthenticationAssertionResponse();
 39
 40 WTF::String name() const { return m_response->name(); }
 41 WTF::String displayName() const { return m_response->displayName(); }
 42 ArrayBuffer* userHandle() const { return m_response->userHandle(); }
 43
 44 const Ref<WebCore::AuthenticatorAssertionResponse>& response() { return m_response; }
 45
 46private:
 47 WebAuthenticationAssertionResponse(Ref<WebCore::AuthenticatorAssertionResponse>&&);
 48
 49 Ref<WebCore::AuthenticatorAssertionResponse> m_response;
 50};
 51
 52} // namespace API
 53
 54#endif // ENABLE(WEB_AUTHN)

Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.h

 1/*
 2 * Copyright (C) 2020 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#pragma once
 27
 28#import <WebKit/WKFoundation.h>
 29
 30#import <Foundation/Foundation.h>
 31
 32NS_ASSUME_NONNULL_BEGIN
 33
 34WK_CLASS_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA))
 35@interface _WKWebAuthenticationAssertionResponse : NSObject
 36
 37@property (nonatomic, readonly, copy) NSString *name;
 38@property (nonatomic, readonly, copy) NSString *displayName;
 39@property (nonatomic, readonly, copy) NSData *userHandle;
 40
 41@end
 42
 43NS_ASSUME_NONNULL_END

Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.mm

 1/*
 2 * Copyright (C) 2020 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 "_WKWebAuthenticationAssertionResponseInternal.h"
 28
 29@implementation _WKWebAuthenticationAssertionResponse {
 30 RetainPtr<NSData> _userHandle;
 31}
 32
 33#if ENABLE(WEB_AUTHN)
 34
 35- (void)dealloc
 36{
 37 _response->~WebAuthenticationAssertionResponse();
 38
 39 [super dealloc];
 40}
 41
 42- (NSString *)name
 43{
 44 return _response->name();
 45}
 46
 47- (NSString *)displayName
 48{
 49 return _response->displayName();
 50}
 51
 52- (NSData *)userHandle
 53{
 54 if (_userHandle)
 55 return _userHandle.get();
 56
 57 if (auto* userHandle = _response->userHandle())
 58 _userHandle = [[NSData alloc] initWithBytes:userHandle->data() length:userHandle->byteLength()];
 59 return _userHandle.get();
 60}
 61
 62#pragma mark WKObject protocol implementation
 63
 64- (API::Object&)_apiObject
 65{
 66 return *_response;
 67}
 68#endif
 69
 70@end

Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponseInternal.h

 1/*
 2 * Copyright (C) 2020 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#pragma once
 27
 28#import "_WKWebAuthenticationAssertionResponse.h"
 29
 30#if ENABLE(WEB_AUTHN)
 31
 32#import "APIWebAuthenticationAssertionResponse.h"
 33#import "WKObject.h"
 34
 35namespace WebKit {
 36
 37template<> struct WrapperTraits<API::WebAuthenticationAssertionResponse> {
 38 using WrapperClass = _WKWebAuthenticationAssertionResponse;
 39};
 40
 41}
 42
 43@interface _WKWebAuthenticationAssertionResponse () <WKObject> {
 44@package
 45 API::ObjectStorage<API::WebAuthenticationAssertionResponse> _response;
 46}
 47@end
 48
 49#endif // ENABLE(WEB_AUTHN)

Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h

3131
3232NS_ASSUME_NONNULL_BEGIN
3333
 34@class _WKWebAuthenticationAssertionResponse;
3435@class _WKWebAuthenticationPanel;
3536
3637typedef NS_ENUM(NSInteger, _WKWebAuthenticationPanelResult) {

@@typedef NS_ENUM(NSInteger, _WKWebAuthenticationType) {
6970- (void)panel:(_WKWebAuthenticationPanel *)panel updateWebAuthenticationPanel:(_WKWebAuthenticationPanelUpdate)update WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
7071- (void)panel:(_WKWebAuthenticationPanel *)panel dismissWebAuthenticationPanelWithResult:(_WKWebAuthenticationResult)result WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
7172- (void)panel:(_WKWebAuthenticationPanel *)panel requestPINWithRemainingRetries:(NSUInteger)retries completionHandler:(void (^)(NSString *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 73- (void)panel:(_WKWebAuthenticationPanel *)panel selectAssertionResponses:(NSArray < _WKWebAuthenticationAssertionResponse *> *)responses completionHandler:(void (^)(_WKWebAuthenticationAssertionResponse *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
7274
7375@end
7476

Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm

2424 */
2525
2626#import "config.h"
27 #import "WebAuthenticationPanelClient.h"
2827#import "_WKWebAuthenticationPanelInternal.h"
29 #import <WebCore/WebAuthenticationConstants.h>
3028
 29#import "WebAuthenticationPanelClient.h"
 30#import <WebCore/WebAuthenticationConstants.h>
3131#import <wtf/RetainPtr.h>
3232
3333@implementation _WKWebAuthenticationPanel {

Source/WebKit/UIProcess/Cocoa/ResourceLoadDelegate.h

2929#import "WKFoundation.h"
3030#import <wtf/WeakObjCPtr.h>
3131
 32@class WKWebView;
 33
3234@protocol _WKResourceLoadDelegate;
3335
3436namespace API {

Source/WebKit/UIProcess/Cocoa/ResourceLoadDelegate.mm

2626#import "config.h"
2727#import "ResourceLoadDelegate.h"
2828
 29#import "AuthenticationChallengeProxy.h"
 30#import "WKNSURLAuthenticationChallenge.h"
2931#import "_WKResourceLoadDelegate.h"
3032#import "_WKResourceLoadInfoInternal.h"
3133

@@void ResourceLoadDelegate::ResourceLoadClient::didSendRequest(WebKit::ResourceLo
8082 if (!delegate)
8183 return;
8284
83  [delegate webView:m_resourceLoadDelegate.m_webView.get().get() resourceLoad:wrapper(API::ResourceLoadInfo::create(WTFMove(loadInfo)).get()) didSendRequest:request.nsURLRequest(HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody)];
 85 [delegate webView:m_resourceLoadDelegate.m_webView.get().get() resourceLoad:wrapper(API::ResourceLoadInfo::create(WTFMove(loadInfo)).get()) didSendRequest:request.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody)];
8486}
8587
8688void ResourceLoadDelegate::ResourceLoadClient::didPerformHTTPRedirection(WebKit::ResourceLoadInfo&& loadInfo, WebCore::ResourceResponse&& response, WebCore::ResourceRequest&& request) const

@@void ResourceLoadDelegate::ResourceLoadClient::didPerformHTTPRedirection(WebKit:
9294 if (!delegate)
9395 return;
9496
95  [delegate webView:m_resourceLoadDelegate.m_webView.get().get() resourceLoad:wrapper(API::ResourceLoadInfo::create(WTFMove(loadInfo)).get()) didPerformHTTPRedirection:response.nsURLResponse() newRequest:request.nsURLRequest(HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody)];
 97 [delegate webView:m_resourceLoadDelegate.m_webView.get().get() resourceLoad:wrapper(API::ResourceLoadInfo::create(WTFMove(loadInfo)).get()) didPerformHTTPRedirection:response.nsURLResponse() newRequest:request.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody)];
9698}
9799
98100void ResourceLoadDelegate::ResourceLoadClient::didReceiveChallenge(WebKit::ResourceLoadInfo&& loadInfo, WebKit::AuthenticationChallengeProxy& challenge) const

Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h

@@private:
5050 void updatePanel(WebAuthenticationStatus) const final;
5151 void dismissPanel(WebAuthenticationResult) const final;
5252 void requestPin(uint64_t, CompletionHandler<void(const WTF::String&)>&&) const final;
 53 void selectAssertionResponses(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>&, CompletionHandler<void(const Ref<WebCore::AuthenticatorAssertionResponse>&)>&&) const final;
5354
5455 _WKWebAuthenticationPanel *m_panel;
5556 WeakObjCPtr<id <_WKWebAuthenticationPanelDelegate> > m_delegate;

@@private:
5859 bool panelUpdateWebAuthenticationPanel : 1;
5960 bool panelDismissWebAuthenticationPanelWithResult : 1;
6061 bool panelRequestPinWithRemainingRetriesCompletionHandler : 1;
 62 bool panelSelectAssertionResponsesCompletionHandler : 1;
6163 } m_delegateMethods;
6264};
6365

Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm

2828
2929#if ENABLE(WEB_AUTHN)
3030
 31#import "APIWebAuthenticationAssertionResponse.h"
3132#import "CompletionHandlerCallChecker.h"
3233#import "WebAuthenticationFlags.h"
 34#import "_WKWebAuthenticationAssertionResponseInternal.h"
3335#import "_WKWebAuthenticationPanel.h"
3436#import <wtf/BlockPtr.h>
3537#import <wtf/RunLoop.h>

@@WebAuthenticationPanelClient::WebAuthenticationPanelClient(_WKWebAuthenticationP
4345 m_delegateMethods.panelUpdateWebAuthenticationPanel = [delegate respondsToSelector:@selector(panel:updateWebAuthenticationPanel:)];
4446 m_delegateMethods.panelDismissWebAuthenticationPanelWithResult = [delegate respondsToSelector:@selector(panel:dismissWebAuthenticationPanelWithResult:)];
4547 m_delegateMethods.panelRequestPinWithRemainingRetriesCompletionHandler = [delegate respondsToSelector:@selector(panel:requestPINWithRemainingRetries:completionHandler:)];
 48 m_delegateMethods.panelSelectAssertionResponsesCompletionHandler = [delegate respondsToSelector:@selector(panel:selectAssertionResponses:completionHandler:)];
4649}
4750
4851RetainPtr<id <_WKWebAuthenticationPanelDelegate> > WebAuthenticationPanelClient::delegate()

@@void WebAuthenticationPanelClient::requestPin(uint64_t retries, CompletionHandle
141144 });
142145}
143146
 147void WebAuthenticationPanelClient::selectAssertionResponses(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>& responses, CompletionHandler<void(const Ref<WebCore::AuthenticatorAssertionResponse>&)>&& completionHandler) const
 148{
 149 auto nsResponses = adoptNS([[NSMutableArray alloc] initWithCapacity:responses.size()]);
 150 for (auto& response : responses)
 151 [nsResponses addObject:wrapper(API::WebAuthenticationAssertionResponse::create(response.copyRef()))];
 152
 153 // Call delegates in the next run loop to prevent clients' reentrance that would potentially modify the state
 154 // of the current run loop in unexpected ways.
 155 RunLoop::main().dispatch([weakThis = makeWeakPtr(*this), this, nsResponses = WTFMove(nsResponses), completionHandler = WTFMove(completionHandler)] () mutable {
 156 if (!weakThis) {
 157 completionHandler(static_cast<API::WebAuthenticationAssertionResponse&>([[nsResponses firstObject] _apiObject]).response());
 158 return;
 159 }
 160
 161 if (!m_delegateMethods.panelSelectAssertionResponsesCompletionHandler) {
 162 completionHandler(static_cast<API::WebAuthenticationAssertionResponse&>([[nsResponses firstObject] _apiObject]).response());
 163 return;
 164 }
 165
 166 auto delegate = m_delegate.get();
 167 if (!delegate) {
 168 completionHandler(static_cast<API::WebAuthenticationAssertionResponse&>([[nsResponses firstObject] _apiObject]).response());
 169 return;
 170 }
 171
 172 auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(panel:selectAssertionResponses:completionHandler:));
 173 [delegate panel:m_panel selectAssertionResponses:nsResponses.get() completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](_WKWebAuthenticationAssertionResponse *response) mutable {
 174 if (checker->completionHandlerHasBeenCalled())
 175 return;
 176 checker->didCallCompletionHandler();
 177 completionHandler(static_cast<API::WebAuthenticationAssertionResponse&>([response _apiObject]).response());
 178 }).get()];
 179 });
 180}
 181
144182} // namespace WebKit
145183
146184#endif // ENABLE(WEB_AUTHN)

Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.h

@@private:
6363 void getRetries();
6464 void continueGetKeyAgreementAfterGetRetries(Vector<uint8_t>&&);
6565 void continueRequestPinAfterGetKeyAgreement(Vector<uint8_t>&&, uint64_t retries);
66  void continueGetPinTokenAfterRequestPin(const String& pin, const CryptoKeyEC&);
 66 void continueGetPinTokenAfterRequestPin(const String& pin, const WebCore::CryptoKeyEC&);
6767 void continueRequestAfterGetPinToken(Vector<uint8_t>&&, const fido::pin::TokenRequest&);
6868
6969 bool tryDowngrade();

Source/WebKit/WebKit.xcodeproj/project.pbxproj

10951095 577FF7822346E81C004EDFB9 /* APIWebAuthenticationPanelClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 577FF7812346E81C004EDFB9 /* APIWebAuthenticationPanelClient.h */; };
10961096 577FF7852346ECAA004EDFB9 /* WebAuthenticationPanelClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 577FF7832346ECAA004EDFB9 /* WebAuthenticationPanelClient.h */; };
10971097 578DC2982155A0020074E815 /* LocalAuthenticationSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 578DC2972155A0010074E815 /* LocalAuthenticationSoftLink.h */; };
 1098 579F1BF623C80DB600C7D4B4 /* _WKWebAuthenticationAssertionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 579F1BF423C80DB600C7D4B4 /* _WKWebAuthenticationAssertionResponse.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1099 579F1BF923C80EC600C7D4B4 /* _WKWebAuthenticationAssertionResponseInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 579F1BF823C80EC600C7D4B4 /* _WKWebAuthenticationAssertionResponseInternal.h */; };
 1100 579F1BFC23C811CF00C7D4B4 /* APIWebAuthenticationAssertionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 579F1BFA23C811CF00C7D4B4 /* APIWebAuthenticationAssertionResponse.h */; };
10981101 57AC8F50217FEED90055438C /* HidConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 57AC8F4E217FEED90055438C /* HidConnection.h */; };
10991102 57B4B46020B504AC00D4AD79 /* ClientCertificateAuthenticationXPCConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B4B45E20B504AB00D4AD79 /* ClientCertificateAuthenticationXPCConstants.h */; };
11001103 57B826412304EB3E00B72EB0 /* NearFieldSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B826402304EB3E00B72EB0 /* NearFieldSPI.h */; };

37553758 577FF7832346ECAA004EDFB9 /* WebAuthenticationPanelClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebAuthenticationPanelClient.h; sourceTree = "<group>"; };
37563759 577FF7842346ECAA004EDFB9 /* WebAuthenticationPanelClient.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebAuthenticationPanelClient.mm; sourceTree = "<group>"; };
37573760 578DC2972155A0010074E815 /* LocalAuthenticationSoftLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalAuthenticationSoftLink.h; sourceTree = "<group>"; };
 3761 579F1BF423C80DB600C7D4B4 /* _WKWebAuthenticationAssertionResponse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKWebAuthenticationAssertionResponse.h; sourceTree = "<group>"; };
 3762 579F1BF523C80DB600C7D4B4 /* _WKWebAuthenticationAssertionResponse.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKWebAuthenticationAssertionResponse.mm; sourceTree = "<group>"; };
 3763 579F1BF823C80EC600C7D4B4 /* _WKWebAuthenticationAssertionResponseInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKWebAuthenticationAssertionResponseInternal.h; sourceTree = "<group>"; };
 3764 579F1BFA23C811CF00C7D4B4 /* APIWebAuthenticationAssertionResponse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APIWebAuthenticationAssertionResponse.h; sourceTree = "<group>"; };
 3765 579F1BFB23C811CF00C7D4B4 /* APIWebAuthenticationAssertionResponse.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = APIWebAuthenticationAssertionResponse.cpp; sourceTree = "<group>"; };
37583766 57AC8F4E217FEED90055438C /* HidConnection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HidConnection.h; sourceTree = "<group>"; };
37593767 57AC8F4F217FEED90055438C /* HidConnection.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = HidConnection.mm; sourceTree = "<group>"; };
37603768 57B4B45D20B504AB00D4AD79 /* AuthenticationManagerCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AuthenticationManagerCocoa.mm; sourceTree = "<group>"; };

68456853 1A81B37F18BD66AD0007FDAC /* _WKVisitedLinkStore.h */,
68466854 1A81B37E18BD66AD0007FDAC /* _WKVisitedLinkStore.mm */,
68476855 1A81B38418BD673A0007FDAC /* _WKVisitedLinkStoreInternal.h */,
 6856 579F1BF423C80DB600C7D4B4 /* _WKWebAuthenticationAssertionResponse.h */,
 6857 579F1BF523C80DB600C7D4B4 /* _WKWebAuthenticationAssertionResponse.mm */,
 6858 579F1BF823C80EC600C7D4B4 /* _WKWebAuthenticationAssertionResponseInternal.h */,
68486859 574728CF23456E98001700AF /* _WKWebAuthenticationPanel.h */,
68496860 574728D023456E98001700AF /* _WKWebAuthenticationPanel.mm */,
68506861 574728D3234570AE001700AF /* _WKWebAuthenticationPanelInternal.h */,

85268537 7C89D2921A67122F003A5FDE /* APIUserScript.h */,
85278538 2D8786211BDB58FF00D02ABB /* APIUserStyleSheet.cpp */,
85288539 2D8786221BDB58FF00D02ABB /* APIUserStyleSheet.h */,
 8540 579F1BFB23C811CF00C7D4B4 /* APIWebAuthenticationAssertionResponse.cpp */,
 8541 579F1BFA23C811CF00C7D4B4 /* APIWebAuthenticationAssertionResponse.h */,
85298542 57EBE269234676C5008D8AF9 /* APIWebAuthenticationPanel.cpp */,
85308543 57EBE268234676C5008D8AF9 /* APIWebAuthenticationPanel.h */,
85318544 577FF7812346E81C004EDFB9 /* APIWebAuthenticationPanelClient.h */,

98969909 2D8786201BDB57F500D02ABB /* _WKUserStyleSheetInternal.h in Headers */,
98979910 1A81B38118BD66AD0007FDAC /* _WKVisitedLinkStore.h in Headers */,
98989911 1A81B38518BD673A0007FDAC /* _WKVisitedLinkStoreInternal.h in Headers */,
 9912 579F1BF623C80DB600C7D4B4 /* _WKWebAuthenticationAssertionResponse.h in Headers */,
 9913 579F1BF923C80EC600C7D4B4 /* _WKWebAuthenticationAssertionResponseInternal.h in Headers */,
98999914 574728D123456E98001700AF /* _WKWebAuthenticationPanel.h in Headers */,
99009915 574728D4234570AE001700AF /* _WKWebAuthenticationPanelInternal.h in Headers */,
99019916 1AE286781C7E76510069AC4F /* _WKWebsiteDataSize.h in Headers */,

99789993 2D8786241BDB58FF00D02ABB /* APIUserStyleSheet.h in Headers */,
99799994 C5E1AFED16B21017006CC1F2 /* APIWebArchive.h in Headers */,
99809995 C5E1AFEF16B21029006CC1F2 /* APIWebArchiveResource.h in Headers */,
 9996 579F1BFC23C811CF00C7D4B4 /* APIWebAuthenticationAssertionResponse.h in Headers */,
99819997 57EBE26A234676C5008D8AF9 /* APIWebAuthenticationPanel.h in Headers */,
99829998 577FF7822346E81C004EDFB9 /* APIWebAuthenticationPanelClient.h in Headers */,
99839999 1AE286841C7F93860069AC4F /* APIWebsiteDataRecord.h in Headers */,

Tools/ChangeLog

 12020-01-10 Jiewen Tan <jiewen_tan@apple.com>
 2
 3 [WebAuthn] Implement SPI to tell UI clients to select assertion responses
 4 https://bugs.webkit.org/show_bug.cgi?id=206112
 5 <rdar://problem/58495733>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
 10 * TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
 11 (-[TestWebAuthenticationPanelDelegate panel:selectAssertionResponses:completionHandler:]):
 12 (TestWebKitAPI::TEST):
 13 * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-hid-multiple-accounts.html: Added.
 14 * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-hid.html:
 15
1162020-01-06 Jiewen Tan <jiewen_tan@apple.com>
217
318 [WebAuthn] Support CTAP Client Pin

Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

368368 5797FE331EB15AB100B2F4A0 /* navigation-client-default-crypto.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5797FE321EB15A8900B2F4A0 /* navigation-client-default-crypto.html */; };
369369 5798337E236019A4008E5547 /* web-authentication-make-credential-hid.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5798337D2360196D008E5547 /* web-authentication-make-credential-hid.html */; };
370370 579833922368FA37008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5798337B235EB65C008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html */; };
 371 579F1C0123C93AF500C7D4B4 /* web-authentication-get-assertion-hid-multiple-accounts.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 579F1BFF23C92FD300C7D4B4 /* web-authentication-get-assertion-hid-multiple-accounts.html */; };
371372 57A79857224AB34E00A7F6F1 /* WebCryptoMasterKey.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57A79856224AB34E00A7F6F1 /* WebCryptoMasterKey.mm */; };
372373 57C3FA661F7C248F009D4B80 /* WeakPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CB9BC371A67482300FE5678 /* WeakPtr.cpp */; };
373374 57C6244E2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57C6244D2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm */; };

14841485 2EBD9D0A2134730D002DA758 /* video.html in Copy Resources */,
14851486 CD577799211CE0E4001B371E /* web-audio-only.html in Copy Resources */,
14861487 57663DF32357E48900E85E09 /* web-authentication-get-assertion-hid-cancel.html in Copy Resources */,
 1488 579F1C0123C93AF500C7D4B4 /* web-authentication-get-assertion-hid-multiple-accounts.html in Copy Resources */,
14871489 577454D02359B378008E1ED7 /* web-authentication-get-assertion-hid-no-credentials.html in Copy Resources */,
14881490 570D26FC23C3F87000D5CF67 /* web-authentication-get-assertion-hid-pin.html in Copy Resources */,
14891491 57663DEC234F1F9300E85E09 /* web-authentication-get-assertion-hid.html in Copy Resources */,

19491951 5798337B235EB65C008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "web-authentication-get-assertion-nfc-multiple-tags.html"; sourceTree = "<group>"; };
19501952 5798337D2360196D008E5547 /* web-authentication-make-credential-hid.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "web-authentication-make-credential-hid.html"; sourceTree = "<group>"; };
19511953 5798E2AF1CAF5C2800C5CBA0 /* ProvisionalURLNotChange.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ProvisionalURLNotChange.mm; sourceTree = "<group>"; };
 1954 579F1BFF23C92FD300C7D4B4 /* web-authentication-get-assertion-hid-multiple-accounts.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-get-assertion-hid-multiple-accounts.html"; sourceTree = "<group>"; };
19521955 57A79856224AB34E00A7F6F1 /* WebCryptoMasterKey.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCryptoMasterKey.mm; sourceTree = "<group>"; };
19531956 57C6244D2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKWebAuthenticationPanel.mm; sourceTree = "<group>"; };
19541957 57C6244F2346C1EC00383FE7 /* web-authentication-get-assertion.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "web-authentication-get-assertion.html"; sourceTree = "<group>"; };

35013504 CD57779B211CE6CE001B371E /* video-with-audio-and-web-audio.html */,
35023505 CD577798211CDE8F001B371E /* web-audio-only.html */,
35033506 57663DF22357E45D00E85E09 /* web-authentication-get-assertion-hid-cancel.html */,
 3507 579F1BFF23C92FD300C7D4B4 /* web-authentication-get-assertion-hid-multiple-accounts.html */,
35043508 577454CF2359B338008E1ED7 /* web-authentication-get-assertion-hid-no-credentials.html */,
35053509 570D26FB23C3F86500D5CF67 /* web-authentication-get-assertion-hid-pin.html */,
35063510 57663DEB234F1F8000E85E09 /* web-authentication-get-assertion-hid.html */,

48704874 2D2BEB2D22324E5F005544CA /* RequestTextInputContext.mm in Sources */,
48714875 7C83E0C41D0A654200FEBCF3 /* RequiresUserActionForPlayback.mm in Sources */,
48724876 7CCE7F0E1A411AE600447C4C /* ResizeReversePaginatedWebView.cpp in Sources */,
4873  CD27A1C123C661ED006E11DD /* WKWebViewPausePlayingAudioTests.mm in Sources */,
48744877 7CCE7F0F1A411AE600447C4C /* ResizeWindowAfterCrash.cpp in Sources */,
48754878 5CB7AFDC23C4529700E49CF3 /* ResourceLoadDelegate.mm in Sources */,
48764879 51C8E1A51F26AF4C00BF731B /* ResourceLoadStatistics.mm in Sources */,

50525055 D34E08761E4E42E1005FF14A /* WKWebViewGetContents.mm in Sources */,
50535056 F4FA91811E61849B007B8C1D /* WKWebViewMacEditingTests.mm in Sources */,
50545057 1CACADA1230620AE0007D54C /* WKWebViewOpaque.mm in Sources */,
 5058 CD27A1C123C661ED006E11DD /* WKWebViewPausePlayingAudioTests.mm in Sources */,
50555059 2D01D06E23218FEE0039AA3A /* WKWebViewPrintFormatter.mm in Sources */,
50565060 37A9DBE9213B4C9300D261A2 /* WKWebViewServerTrustKVC.mm in Sources */,
50575061 93F56DA91E5F919D003EDE84 /* WKWebViewSnapshot.mm in Sources */,

Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm

3535#import <WebKit/WKPreferencesPrivate.h>
3636#import <WebKit/WKUIDelegatePrivate.h>
3737#import <WebKit/_WKExperimentalFeature.h>
 38#import <WebKit/_WKWebAuthenticationAssertionResponse.h>
3839#import <WebKit/_WKWebAuthenticationPanel.h>
3940#import <wtf/BlockPtr.h>
 41#import <wtf/RandomNumber.h>
4042#import <wtf/text/StringConcatenateNumbers.h>
4143
4244static bool webAuthenticationPanelRan = false;

@@static bool webAuthenticationPanelUpdateMultipleNFCTagsPresent = false;
4648static bool webAuthenticationPanelUpdateNoCredentialsFound = false;
4749static bool webAuthenticationPanelCancelImmediately = false;
4850static String webAuthenticationPanelPin;
 51static BOOL webAuthenticationPanelNullUserHandle = NO;
4952
5053@interface TestWebAuthenticationPanelDelegate : NSObject <_WKWebAuthenticationPanelDelegate>
5154@end

@@- (void)panel:(_WKWebAuthenticationPanel *)panel requestPINWithRemainingRetries:
9194 completionHandler(webAuthenticationPanelPin);
9295}
9396
 97- (void)panel:(_WKWebAuthenticationPanel *)panel selectAssertionResponses:(NSArray < _WKWebAuthenticationAssertionResponse *> *)responses completionHandler:(void (^)(_WKWebAuthenticationAssertionResponse *))completionHandler
 98{
 99 EXPECT_EQ(responses.count, 2ul);
 100 for (_WKWebAuthenticationAssertionResponse *response in responses) {
 101 EXPECT_TRUE([response.name isEqual:@"johnpsmith@example.com"] || [response.name isEqual:@""]);
 102 EXPECT_TRUE([response.displayName isEqual:@"John P. Smith"] || [response.displayName isEqual:@""]);
 103 EXPECT_TRUE([[response.userHandle base64EncodedStringWithOptions:0] isEqual:@"MIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGTMII="] || !response.userHandle);
 104 }
 105
 106 auto index = weakRandomUint32() % 2;
 107 webAuthenticationPanelNullUserHandle = responses[index].userHandle ? NO : YES;
 108 completionHandler(responses[index]);
 109}
 110
94111@end
95112
96113@interface TestWebAuthenticationPanelFakeDelegate : NSObject <_WKWebAuthenticationPanelDelegate>

@@TEST(WebAuthenticationPanel, GetAssertionPin)
872889 [webView waitForMessage:@"Succeeded!"];
873890}
874891
 892TEST(WebAuthenticationPanel, MultipleAccountsNullDelegate)
 893{
 894 reset();
 895 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-multiple-accounts" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
 896
 897 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
 898 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
 899
 900 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
 901 auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
 902 [delegate setIsNull:true];
 903 [webView setUIDelegate:delegate.get()];
 904
 905 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
 906 [webView waitForMessage:@"Succeeded!"];
 907}
 908
 909TEST(WebAuthenticationPanel, MultipleAccounts)
 910{
 911 reset();
 912 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-multiple-accounts" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
 913
 914 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
 915 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
 916
 917 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
 918 auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
 919 [webView setUIDelegate:delegate.get()];
 920
 921 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
 922 [webView waitForMessage:@"Succeeded!"];
 923 EXPECT_EQ([[webView stringByEvaluatingJavaScript:@"userHandle"] isEqualToString:@"<null>"], webAuthenticationPanelNullUserHandle);
 924}
 925
875926} // namespace TestWebKitAPI
876927
877928#endif // ENABLE(WEB_AUTHN)

Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-hid-multiple-accounts.html

 1<input type="text" id="input">
 2<script>
 3 const testAssertionMessageLongBase64 =
 4 "AKUBomJpZFhAKAitzuj+Tslzelf3/vZwIGtDQNgoKeFd5oEieYzhyzA65saf0tK2" +
 5 "w/mooa7tQtGgDdwZIjOhjcuZ0pQ1ajoE4GR0eXBlanB1YmxpYy1rZXkCWCVGzH+5" +
 6 "Z51VstuQkuHI2eXh0Ct1gPC0gSx3CWLh5I9a2AEAAABQA1hHMEUCIQCSFTuuBWgB" +
 7 "4/F0VB7DlUVM09IHPmxe1MzHUwRoCRZbCAIgGKov6xoAx2MEf6/6qNs8OutzhP2C" +
 8 "QoJ1L7Fe64G9uBcEpGJpZFggMIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGT" +
 9 "MIJkaWNvbngoaHR0cHM6Ly9waWNzLmFjbWUuY29tLzAwL3AvYUJqampwcVBiLnBu" +
 10 "Z2RuYW1ldmpvaG5wc21pdGhAZXhhbXBsZS5jb21rZGlzcGxheU5hbWVtSm9obiBQ" +
 11 "LiBTbWl0aAUC";
 12 const testAssertionMessageBase64 =
 13 "AKMBomJpZFhAKAitzuj+Tslzelf3/vZwIGtDQNgoKeFd5oEieYzhyzA65saf0tK2" +
 14 "w/mooa7tQtGgDdwZIjOhjcuZ0pQ1ajoE4GR0eXBlanB1YmxpYy1rZXkCWCVGzH+5" +
 15 "Z51VstuQkuHI2eXh0Ct1gPC0gSx3CWLh5I9a2AEAAABQA1hHMEUCIQCSFTuuBWgB" +
 16 "4/F0VB7DlUVM09IHPmxe1MzHUwRoCRZbCAIgGKov6xoAx2MEf6/6qNs8OutzhP2C" +
 17 "QoJ1L7Fe64G9uBc=";
 18 if (window.internals) {
 19 internals.setMockWebAuthenticationConfiguration({ silentFailure: true, hid: { payloadBase64: [testAssertionMessageLongBase64, testAssertionMessageBase64] } });
 20 internals.withUserGesture(() => { input.focus(); });
 21 }
 22
 23 function bytesToHexString(bytes)
 24 {
 25 if (!bytes)
 26 return null;
 27
 28 bytes = new Uint8Array(bytes);
 29 var hexBytes = [];
 30
 31 for (var i = 0; i < bytes.length; ++i) {
 32 var byteString = bytes[i].toString(16);
 33 if (byteString.length < 2)
 34 byteString = "0" + byteString;
 35 hexBytes.push(byteString);
 36 }
 37
 38 return hexBytes.join("");
 39 }
 40
 41 const options = {
 42 publicKey: {
 43 challenge: new Uint8Array(16),
 44 timeout: 1000
 45 }
 46 };
 47
 48 navigator.credentials.get(options).then(credential => {
 49 userHandle = bytesToHexString(credential.response.userHandle);
 50 // console.log("Succeeded!");
 51 window.webkit.messageHandlers.testHandler.postMessage("Succeeded!");
 52 }, error => {
 53 // console.log(error.message);
 54 window.webkit.messageHandlers.testHandler.postMessage(error.message);
 55 });
 56</script>

Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-hid.html

3939 },
4040 challenge: new Uint8Array(16),
4141 pubKeyCredParams: [{ type: "public-key", alg: -7 }],
42  timeout: 100
 42 timeout: 100,
4343 }
4444 };
4545