Changeset 228572 in webkit


Ignore:
Timestamp:
Feb 16, 2018 12:43:28 PM (6 years ago)
Author:
jiewen_tan@apple.com
Message:

[WebAuthN] Implement PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
https://bugs.webkit.org/show_bug.cgi?id=182771
<rdar://problem/36459988>

Reviewed by Brent Fulgham.

Source/WebCore:

This patch implements PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
per https://www.w3.org/TR/webauthn/#isUserVerifyingPlatformAuthenticatorAvailable with some
limitations.

In addition, it changes DeferredPromise to DOMPromiseDeferred<> for all CredentialsManagement
and WebAuthN API.

Test: http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available.html

  • Modules/credentialmanagement/CredentialsContainer.cpp:

(WebCore::CredentialsContainer::get):
(WebCore::CredentialsContainer::store):
(WebCore::CredentialsContainer::isCreate):
(WebCore::CredentialsContainer::preventSilentAccess const):

  • Modules/credentialmanagement/CredentialsContainer.h:
  • Modules/credentialmanagement/CredentialsMessenger.cpp:

(WebCore::CredentialsMessenger::addCreationCompletionHandler):
Remove a redundant assertion.
(WebCore::CredentialsMessenger::addRequestCompletionHandler):
Remove a redundant assertion.
(WebCore::CredentialsMessenger::addQueryCompletionHandler):
(WebCore::CredentialsMessenger::takeQueryCompletionHandler):

  • Modules/credentialmanagement/CredentialsMessenger.h:
  • Modules/webauthn/AuthenticatorManager.cpp:

(WebCore::AuthenticatorManagerInternal::initTimeoutTimer):
(WebCore::AuthenticatorManager::create const):
(WebCore::AuthenticatorManager::discoverFromExternalSource const):
(WebCore::AuthenticatorManager::isUserVerifyingPlatformAuthenticatorAvailable const):

  • Modules/webauthn/AuthenticatorManager.h:
  • Modules/webauthn/PublicKeyCredential.cpp:

(WebCore::PublicKeyCredential::isUserVerifyingPlatformAuthenticatorAvailable):

  • Modules/webauthn/PublicKeyCredential.h:
  • testing/MockCredentialsMessenger.cpp:

(WebCore::MockCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailable):
(WebCore::MockCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailableReply):

  • testing/MockCredentialsMessenger.h:
  • testing/MockCredentialsMessenger.idl:

Source/WebKit:

This patch utilizes LocalAuthentication Framework to determine if biometrics
are enrolled on a device, which is the user verifying platform authenticator.
To do so, it links the framework to WebKit.

  • UIProcess/CredentialManagement/WebCredentialsMessengerProxy.cpp:

(WebKit::WebCredentialsMessengerProxy::isUserVerifyingPlatformAuthenticatorAvailable):
(WebKit::WebCredentialsMessengerProxy::isUserVerifyingPlatformAuthenticatorAvailableReply):

  • UIProcess/CredentialManagement/WebCredentialsMessengerProxy.h:
  • UIProcess/CredentialManagement/WebCredentialsMessengerProxy.messages.in:
  • UIProcess/CredentialManagement/cocoa/WebCredentialsMessengerProxyCocoa.mm:

(WebKit::WebCredentialsMessengerProxy::platformIsUserVerifyingPlatformAuthenticatorAvailable):

  • WebKit.xcodeproj/project.pbxproj:
  • WebProcess/CredentialManagement/WebCredentialsMessenger.cpp:

(WebKit::WebCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailable):
(WebKit::WebCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailableReply):

  • WebProcess/CredentialManagement/WebCredentialsMessenger.h:
  • WebProcess/CredentialManagement/WebCredentialsMessenger.messages.in:

LayoutTests:

  • http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available-expected.txt: Added.
  • http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available.html: Added.
Location:
trunk
Files:
3 added
21 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r228561 r228572  
     12018-02-16  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthN] Implement PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
     4        https://bugs.webkit.org/show_bug.cgi?id=182771
     5        <rdar://problem/36459988>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        * http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available-expected.txt: Added.
     10        * http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available.html: Added.
     11
    1122018-02-16  Fujii Hironori  <Hironori.Fujii@sony.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r228571 r228572  
     12018-02-16  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthN] Implement PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
     4        https://bugs.webkit.org/show_bug.cgi?id=182771
     5        <rdar://problem/36459988>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        This patch implements PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
     10        per https://www.w3.org/TR/webauthn/#isUserVerifyingPlatformAuthenticatorAvailable with some
     11        limitations.
     12
     13        In addition, it changes DeferredPromise to DOMPromiseDeferred<> for all CredentialsManagement
     14        and WebAuthN API.
     15
     16        Test: http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available.html
     17
     18        * Modules/credentialmanagement/CredentialsContainer.cpp:
     19        (WebCore::CredentialsContainer::get):
     20        (WebCore::CredentialsContainer::store):
     21        (WebCore::CredentialsContainer::isCreate):
     22        (WebCore::CredentialsContainer::preventSilentAccess const):
     23        * Modules/credentialmanagement/CredentialsContainer.h:
     24        * Modules/credentialmanagement/CredentialsMessenger.cpp:
     25        (WebCore::CredentialsMessenger::addCreationCompletionHandler):
     26        Remove a redundant assertion.
     27        (WebCore::CredentialsMessenger::addRequestCompletionHandler):
     28        Remove a redundant assertion.
     29        (WebCore::CredentialsMessenger::addQueryCompletionHandler):
     30        (WebCore::CredentialsMessenger::takeQueryCompletionHandler):
     31        * Modules/credentialmanagement/CredentialsMessenger.h:
     32        * Modules/webauthn/AuthenticatorManager.cpp:
     33        (WebCore::AuthenticatorManagerInternal::initTimeoutTimer):
     34        (WebCore::AuthenticatorManager::create const):
     35        (WebCore::AuthenticatorManager::discoverFromExternalSource const):
     36        (WebCore::AuthenticatorManager::isUserVerifyingPlatformAuthenticatorAvailable const):
     37        * Modules/webauthn/AuthenticatorManager.h:
     38        * Modules/webauthn/PublicKeyCredential.cpp:
     39        (WebCore::PublicKeyCredential::isUserVerifyingPlatformAuthenticatorAvailable):
     40        * Modules/webauthn/PublicKeyCredential.h:
     41        * testing/MockCredentialsMessenger.cpp:
     42        (WebCore::MockCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailable):
     43        (WebCore::MockCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailableReply):
     44        * testing/MockCredentialsMessenger.h:
     45        * testing/MockCredentialsMessenger.idl:
     46
    1472018-02-16  Tim Horton  <timothy_horton@apple.com>
    248
  • trunk/Source/WebCore/Modules/credentialmanagement/CredentialsContainer.cpp

    r228523 r228572  
    3131
    3232#include "AbortSignal.h"
    33 #include "AuthenticatorManager.h"
    3433#include "CredentialCreationOptions.h"
    3534#include "CredentialRequestOptions.h"
     
    6160}
    6261
    63 void CredentialsContainer::get(CredentialRequestOptions&& options, Ref<DeferredPromise>&& promise)
     62void CredentialsContainer::get(CredentialRequestOptions&& options, CredentialPromise&& promise)
    6463{
    6564    // The following implements https://www.w3.org/TR/credential-management-1/#algorithm-request as of 4 August 2017
    6665    // with enhancement from 14 November 2017 Editor's Draft.
    6766    if (!m_document) {
    68         promise->reject(Exception { NotSupportedError });
     67        promise.reject(Exception { NotSupportedError });
    6968        return;
    7069    }
    7170    if (options.signal && options.signal->aborted()) {
    72         promise->reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
     71        promise.reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
    7372        return;
    7473    }
     
    8079    // be requested from [[discoverFromExternalSource]].
    8180    if (!options.publicKey) {
    82         promise->reject(Exception { NotSupportedError, ASCIILiteral("Only PublicKeyCredential is supported.") });
     81        promise.reject(Exception { NotSupportedError, ASCIILiteral("Only PublicKeyCredential is supported.") });
    8382        return;
    8483    }
     
    8887}
    8988
    90 void CredentialsContainer::store(const BasicCredential&, Ref<DeferredPromise>&& promise)
     89void CredentialsContainer::store(const BasicCredential&, CredentialPromise&& promise)
    9190{
    92     promise->reject(Exception { NotSupportedError, ASCIILiteral("Not implemented.") });
     91    promise.reject(Exception { NotSupportedError, ASCIILiteral("Not implemented.") });
    9392}
    9493
    95 void CredentialsContainer::isCreate(CredentialCreationOptions&& options, Ref<DeferredPromise>&& promise)
     94void CredentialsContainer::isCreate(CredentialCreationOptions&& options, CredentialPromise&& promise)
    9695{
    9796    // The following implements https://www.w3.org/TR/credential-management-1/#algorithm-create as of 4 August 2017
    9897    // with enhancement from 14 November 2017 Editor's Draft.
    9998    if (!m_document) {
    100         promise->reject(Exception { NotSupportedError });
     99        promise.reject(Exception { NotSupportedError });
    101100        return;
    102101    }
    103102    if (options.signal && options.signal->aborted()) {
    104         promise->reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
     103        promise.reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
    105104        return;
    106105    }
     
    110109    // Step 3-7. Shortcut as we only support one kind of credentials.
    111110    if (!options.publicKey) {
    112         promise->reject(Exception { NotSupportedError, ASCIILiteral("Only PublicKeyCredential is supported.") });
     111        promise.reject(Exception { NotSupportedError, ASCIILiteral("Only PublicKeyCredential is supported.") });
    113112        return;
    114113    }
     
    118117}
    119118
    120 void CredentialsContainer::preventSilentAccess(Ref<DeferredPromise>&& promise) const
     119void CredentialsContainer::preventSilentAccess(DOMPromiseDeferred<void>&& promise) const
    121120{
    122     promise->reject(Exception { NotSupportedError, ASCIILiteral("Not implemented.") });
     121    promise.reject(Exception { NotSupportedError, ASCIILiteral("Not implemented.") });
    123122}
    124123
  • trunk/Source/WebCore/Modules/credentialmanagement/CredentialsContainer.h

    r228523 r228572  
    2929#if ENABLE(WEB_AUTHN)
    3030
     31#include "AuthenticatorManager.h"
    3132#include <wtf/RefCounted.h>
    3233#include <wtf/WeakPtr.h>
     
    3435namespace WebCore {
    3536
    36 class BasicCredential;
    37 class DeferredPromise;
    3837class Document;
    3938
     
    4544    static Ref<CredentialsContainer> create(WeakPtr<Document>&& document) { return adoptRef(*new CredentialsContainer(WTFMove(document))); }
    4645
    47     void get(CredentialRequestOptions&&, Ref<DeferredPromise>&&);
     46    void get(CredentialRequestOptions&&, CredentialPromise&&);
    4847
    49     void store(const BasicCredential&, Ref<DeferredPromise>&&);
     48    void store(const BasicCredential&, CredentialPromise&&);
    5049
    51     void isCreate(CredentialCreationOptions&&, Ref<DeferredPromise>&&);
     50    void isCreate(CredentialCreationOptions&&, CredentialPromise&&);
    5251
    53     void preventSilentAccess(Ref<DeferredPromise>&&) const;
     52    void preventSilentAccess(DOMPromiseDeferred<void>&&) const;
    5453
    5554private:
  • trunk/Source/WebCore/Modules/credentialmanagement/CredentialsMessenger.cpp

    r228523 r228572  
    6969    auto addResult = m_pendingCreationCompletionHandlers.add(messageId, WTFMove(handler));
    7070    ASSERT_UNUSED(addResult, addResult.isNewEntry);
    71     ASSERT(addResult);
    7271    return messageId;
    7372}
     
    8786    auto addResult = m_pendingRequestCompletionHandlers.add(messageId, WTFMove(handler));
    8887    ASSERT_UNUSED(addResult, addResult.isNewEntry);
    89     ASSERT(addResult);
    9088    return messageId;
    9189}
     
    9492{
    9593    return m_pendingRequestCompletionHandlers.take(messageId);
     94}
     95
     96uint64_t CredentialsMessenger::addQueryCompletionHandler(QueryCompletionHandler&& handler)
     97{
     98    using namespace CredentialsMessengerInternal;
     99
     100    uint64_t messageId = m_accumulatedMessageId++;
     101    ASSERT(messageId < maxMessageId);
     102    messageId = messageId | CallBackClassifier::Query << callBackClassifierOffset;
     103    auto addResult = m_pendingQueryCompletionHandlers.add(messageId, WTFMove(handler));
     104    ASSERT_UNUSED(addResult, addResult.isNewEntry);
     105    return messageId;
     106}
     107
     108QueryCompletionHandler CredentialsMessenger::takeQueryCompletionHandler(uint64_t messageId)
     109{
     110    return m_pendingQueryCompletionHandlers.take(messageId);
    96111}
    97112
  • trunk/Source/WebCore/Modules/credentialmanagement/CredentialsMessenger.h

    r228523 r228572  
    6969using CreationCompletionHandler = CompletionHandler<void(ExceptionOr<CreationReturnBundle>&&)>;
    7070using RequestCompletionHandler = CompletionHandler<void(ExceptionOr<AssertionReturnBundle>&&)>;
     71using QueryCompletionHandler = CompletionHandler<void(bool)>;
    7172
    7273class CredentialsMessenger {
     
    7677    virtual void makeCredential(const Vector<uint8_t>& hash, const PublicKeyCredentialCreationOptions&, CreationCompletionHandler&&) = 0;
    7778    virtual void getAssertion(const Vector<uint8_t>& hash, const PublicKeyCredentialRequestOptions&, RequestCompletionHandler&&) = 0;
     79    virtual void isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&&) = 0;
    7880
    7981    // receiver
     
    8183    virtual void makeCredentialReply(uint64_t messageId, const Vector<uint8_t>&) = 0;
    8284    virtual void getAssertionReply(uint64_t messageId, const Vector<uint8_t>& credentialId, const Vector<uint8_t>& authenticatorData, const Vector<uint8_t>& signature, const Vector<uint8_t>& userHandle) = 0;
     85    virtual void isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool) = 0;
    8386
    8487    auto& weakPtrFactory() const { return m_weakFactory; }
     
    9194    WEBCORE_EXPORT uint64_t addRequestCompletionHandler(RequestCompletionHandler&&);
    9295    WEBCORE_EXPORT RequestCompletionHandler takeRequestCompletionHandler(uint64_t);
     96    WEBCORE_EXPORT uint64_t addQueryCompletionHandler(QueryCompletionHandler&&);
     97    WEBCORE_EXPORT QueryCompletionHandler takeQueryCompletionHandler(uint64_t);
    9398
    9499private:
     
    104109    HashMap<uint64_t, CreationCompletionHandler> m_pendingCreationCompletionHandlers;
    105110    HashMap<uint64_t, RequestCompletionHandler> m_pendingRequestCompletionHandlers;
     111    HashMap<uint64_t, QueryCompletionHandler> m_pendingQueryCompletionHandlers;
    106112};
    107113
  • trunk/Source/WebCore/Modules/webauthn/AuthenticatorManager.cpp

    r228523 r228572  
    3434#include "CredentialsMessenger.h"
    3535#include "JSBasicCredential.h"
    36 #include "JSDOMPromiseDeferred.h"
    3736#include "PublicKeyCredential.h"
    3837#include "PublicKeyCredentialCreationOptions.h"
     
    8483
    8584// FIXME(181947): We should probably trim timeOutInMs to some max allowable number.
    86 static std::unique_ptr<Timer> initTimeoutTimer(std::optional<unsigned long> timeOutInMs, const Ref<DeferredPromise>& promise)
     85static std::unique_ptr<Timer> initTimeoutTimer(std::optional<unsigned long> timeOutInMs, const CredentialPromise& promise)
    8786{
    8887    if (!timeOutInMs)
    8988        return nullptr;
    9089
    91     auto timer = std::make_unique<Timer>([promise = promise.copyRef()] () {
    92         promise->reject(Exception { NotAllowedError, ASCIILiteral("Operation timed out.") });
     90    auto timer = std::make_unique<Timer>([promise = promise] () mutable {
     91        promise.reject(Exception { NotAllowedError, ASCIILiteral("Operation timed out.") });
    9392    });
    9493    timer->startOneShot(Seconds::fromMilliseconds(*timeOutInMs));
     
    120119}
    121120
    122 void AuthenticatorManager::create(const SecurityOrigin& callerOrigin, const PublicKeyCredentialCreationOptions& options, bool sameOriginWithAncestors, RefPtr<AbortSignal>&& abortSignal, Ref<DeferredPromise>&& promise) const
     121void AuthenticatorManager::create(const SecurityOrigin& callerOrigin, const PublicKeyCredentialCreationOptions& options, bool sameOriginWithAncestors, RefPtr<AbortSignal>&& abortSignal, CredentialPromise&& promise) const
    123122{
    124123    using namespace AuthenticatorManagerInternal;
     
    129128    // Step 2.
    130129    if (!sameOriginWithAncestors) {
    131         promise->reject(Exception { NotAllowedError, ASCIILiteral("The origin of the document is not the same as its ancestors.") });
     130        promise.reject(Exception { NotAllowedError, ASCIILiteral("The origin of the document is not the same as its ancestors.") });
    132131        return;
    133132    }
     
    141140    // domain suffix of another domain. Hence restrict the comparison to equal in Step 7.
    142141    if (!options.rp.id.isEmpty() && callerOrigin.host() != options.rp.id) {
    143         promise->reject(Exception { SecurityError, ASCIILiteral("The origin of the document is not a registrable domain suffix of the provided RP ID.") });
     142        promise.reject(Exception { SecurityError, ASCIILiteral("The origin of the document is not a registrable domain suffix of the provided RP ID.") });
    144143        return;
    145144    }
     
    151150    // is empty or not. Return NotSupportedError as long as it is empty.
    152151    if (options.pubKeyCredParams.isEmpty()) {
    153         promise->reject(Exception { NotSupportedError, ASCIILiteral("No desired properties of the to be created credential are provided.") });
     152        promise.reject(Exception { NotSupportedError, ASCIILiteral("No desired properties of the to be created credential are provided.") });
    154153        return;
    155154    }
     
    164163    // For better performance, no filtering is done here regarding to options.excludeCredentials.
    165164    if (!m_messenger)  {
    166         promise->reject(Exception { UnknownError, ASCIILiteral("Unknown internal error.") });
     165        promise.reject(Exception { UnknownError, ASCIILiteral("Unknown internal error.") });
    167166        return;
    168167    }
     
    172171            return;
    173172        if (abortSignal && abortSignal->aborted()) {
    174             promise->reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
     173            promise.reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
    175174            return;
    176175        }
    177176        if (result.hasException()) {
    178             promise->reject(result.exception());
     177            promise.reject(result.exception());
    179178            return;
    180179        }
    181180
    182181        auto bundle = result.releaseReturnValue();
    183         promise->resolve<IDLNullable<IDLInterface<BasicCredential>>>(PublicKeyCredential::create(WTFMove(bundle.credentialId), AuthenticatorAttestationResponse::create(WTFMove(clientDataJson), ArrayBuffer::create(WTFMove(bundle.attestationObject)))).ptr());
     182        promise.resolve(PublicKeyCredential::create(WTFMove(bundle.credentialId), AuthenticatorAttestationResponse::create(WTFMove(clientDataJson), ArrayBuffer::create(WTFMove(bundle.attestationObject)))).ptr());
    184183    };
    185184    // Async operations are dispatched and handled in the messenger.
     
    187186}
    188187
    189 void AuthenticatorManager::discoverFromExternalSource(const SecurityOrigin& callerOrigin, const PublicKeyCredentialRequestOptions& options, bool sameOriginWithAncestors, RefPtr<AbortSignal>&& abortSignal, Ref<DeferredPromise>&& promise) const
     188void AuthenticatorManager::discoverFromExternalSource(const SecurityOrigin& callerOrigin, const PublicKeyCredentialRequestOptions& options, bool sameOriginWithAncestors, RefPtr<AbortSignal>&& abortSignal, CredentialPromise&& promise) const
    190189{
    191190    using namespace AuthenticatorManagerInternal;
     
    196195    // Step 2.
    197196    if (!sameOriginWithAncestors) {
    198         promise->reject(Exception { NotAllowedError, ASCIILiteral("The origin of the document is not the same as its ancestors.") });
     197        promise.reject(Exception { NotAllowedError, ASCIILiteral("The origin of the document is not the same as its ancestors.") });
    199198        return;
    200199    }
     
    208207    // domain suffix of another domain. Hence restrict the comparison to equal in Step 7.
    209208    if (!options.rpId.isEmpty() && callerOrigin.host() != options.rpId) {
    210         promise->reject(Exception { SecurityError, ASCIILiteral("The origin of the document is not a registrable domain suffix of the provided RP ID.") });
     209        promise.reject(Exception { SecurityError, ASCIILiteral("The origin of the document is not a registrable domain suffix of the provided RP ID.") });
    211210        return;
    212211    }
     
    223222    // For better performance, no filtering is done here regarding to options.allowCredentials.
    224223    if (!m_messenger)  {
    225         promise->reject(Exception { UnknownError, ASCIILiteral("Unknown internal error.") });
     224        promise.reject(Exception { UnknownError, ASCIILiteral("Unknown internal error.") });
    226225        return;
    227226    }
     
    231230            return;
    232231        if (abortSignal && abortSignal->aborted()) {
    233             promise->reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
     232            promise.reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
    234233            return;
    235234        }
    236235        if (result.hasException()) {
    237             promise->reject(result.exception());
     236            promise.reject(result.exception());
    238237            return;
    239238        }
    240239
    241240        auto bundle = result.releaseReturnValue();
    242         promise->resolve<IDLNullable<IDLInterface<BasicCredential>>>(PublicKeyCredential::create(WTFMove(bundle.credentialId), AuthenticatorAssertionResponse::create(WTFMove(clientDataJson), WTFMove(bundle.authenticatorData), WTFMove(bundle.signature), WTFMove(bundle.userHandle))).ptr());
     241        promise.resolve(PublicKeyCredential::create(WTFMove(bundle.credentialId), AuthenticatorAssertionResponse::create(WTFMove(clientDataJson), WTFMove(bundle.authenticatorData), WTFMove(bundle.signature), WTFMove(bundle.userHandle))).ptr());
    243242    };
    244243    // Async operations are dispatched and handled in the messenger.
     
    246245}
    247246
     247void AuthenticatorManager::isUserVerifyingPlatformAuthenticatorAvailable(DOMPromiseDeferred<IDLBoolean>&& promise) const
     248{
     249    // The following implements https://www.w3.org/TR/webauthn/#isUserVerifyingPlatformAuthenticatorAvailable
     250    // as of 5 December 2017.
     251    if (!m_messenger)  {
     252        promise.reject(Exception { UnknownError, ASCIILiteral("Unknown internal error.") });
     253        return;
     254    }
     255
     256    // FIXME(182767): We should consider more on the assessment of the return value. Right now, we return true/false
     257    // immediately according to platform specific procedures.
     258    auto completionHandler = [promise = WTFMove(promise)] (bool result) mutable {
     259        promise.resolve(result);
     260    };
     261    // Async operation are dispatched and handled in the messenger.
     262    m_messenger->isUserVerifyingPlatformAuthenticatorAvailable(WTFMove(completionHandler));
     263}
     264
    248265} // namespace WebCore
    249266
  • trunk/Source/WebCore/Modules/webauthn/AuthenticatorManager.h

    r228523 r228572  
    2828#if ENABLE(WEB_AUTHN)
    2929
     30#include "JSDOMPromiseDeferred.h"
    3031#include <wtf/Forward.h>
    3132#include <wtf/Noncopyable.h>
     
    3536
    3637class AbortSignal;
     38class BasicCredential;
    3739class CredentialsMessenger;
    38 class DeferredPromise;
    3940class SecurityOrigin;
    4041
    4142struct PublicKeyCredentialCreationOptions;
    4243struct PublicKeyCredentialRequestOptions;
     44
     45using CredentialPromise = DOMPromiseDeferred<IDLNullable<IDLInterface<BasicCredential>>>;
    4346
    4447class AuthenticatorManager {
     
    5053
    5154    // The following methods implement static methods of PublicKeyCredential.
    52     void create(const SecurityOrigin&, const PublicKeyCredentialCreationOptions&, bool sameOriginWithAncestors, RefPtr<AbortSignal>&&, Ref<DeferredPromise>&&) const;
    53     void discoverFromExternalSource(const SecurityOrigin&, const PublicKeyCredentialRequestOptions&, bool sameOriginWithAncestors, RefPtr<AbortSignal>&&, Ref<DeferredPromise>&&) const;
     55    void create(const SecurityOrigin&, const PublicKeyCredentialCreationOptions&, bool sameOriginWithAncestors, RefPtr<AbortSignal>&&, CredentialPromise&&) const;
     56    void discoverFromExternalSource(const SecurityOrigin&, const PublicKeyCredentialRequestOptions&, bool sameOriginWithAncestors, RefPtr<AbortSignal>&&, CredentialPromise&&) const;
     57    void isUserVerifyingPlatformAuthenticatorAvailable(DOMPromiseDeferred<IDLBoolean>&&) const;
    5458
    5559private:
  • trunk/Source/WebCore/Modules/webauthn/PublicKeyCredential.cpp

    r228523 r228572  
    2929#if ENABLE(WEB_AUTHN)
    3030
     31#include "AuthenticatorManager.h"
    3132#include "JSDOMPromiseDeferred.h"
    3233#include <wtf/text/Base64.h>
     
    4647}
    4748
    48 void PublicKeyCredential::isUserVerifyingPlatformAuthenticatorAvailable(Ref<DeferredPromise>&& promise)
     49void PublicKeyCredential::isUserVerifyingPlatformAuthenticatorAvailable(DOMPromiseDeferred<IDLBoolean>&& promise)
    4950{
    50     promise->reject(Exception { NotSupportedError });
     51    AuthenticatorManager::singleton().isUserVerifyingPlatformAuthenticatorAvailable(WTFMove(promise));
    5152}
    5253
  • trunk/Source/WebCore/Modules/webauthn/PublicKeyCredential.h

    r228523 r228572  
    3030#include "BasicCredential.h"
    3131#include "ExceptionOr.h"
     32#include "JSDOMPromiseDeferred.h"
    3233#include <JavaScriptCore/ArrayBuffer.h>
    3334#include <wtf/Forward.h>
     
    3637
    3738class AuthenticatorResponse;
    38 class DeferredPromise;
    3939
    4040class PublicKeyCredential final : public BasicCredential {
     
    5050    ExceptionOr<bool> getClientExtensionResults() const;
    5151
    52     static void isUserVerifyingPlatformAuthenticatorAvailable(Ref<DeferredPromise>&&);
     52    static void isUserVerifyingPlatformAuthenticatorAvailable(DOMPromiseDeferred<IDLBoolean>&&);
    5353
    5454private:
  • trunk/Source/WebCore/testing/MockCredentialsMessenger.cpp

    r228523 r228572  
    118118}
    119119
     120void MockCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&& handler)
     121{
     122    auto messageId = addQueryCompletionHandler(WTFMove(handler));
     123    if (m_didUserVerifyingPlatformAuthenticatorPresent) {
     124        isUserVerifyingPlatformAuthenticatorAvailableReply(messageId, true);
     125        m_didUserVerifyingPlatformAuthenticatorPresent = false;
     126    } else
     127        isUserVerifyingPlatformAuthenticatorAvailableReply(messageId, false);
     128}
     129
    120130void MockCredentialsMessenger::makeCredentialReply(uint64_t messageId, const Vector<uint8_t>& attestationObject)
    121131{
     
    130140}
    131141
     142void MockCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool result)
     143{
     144    auto handler = takeQueryCompletionHandler(messageId);
     145    handler(result);
     146}
     147
    132148} // namespace WebCore
    133149
  • trunk/Source/WebCore/testing/MockCredentialsMessenger.h

    r228523 r228572  
    4343    void setDidTimeOut() { m_didTimeOut = true; }
    4444    void setDidUserCancel() { m_didUserCancel = true; }
     45    void setDidUserVerifyingPlatformAuthenticatorPresent() { m_didUserVerifyingPlatformAuthenticatorPresent = true; }
    4546    void setAttestationObject(const BufferSource&);
    4647    void setAssertionReturnBundle(const BufferSource& credentialId, const BufferSource& authenticatorData, const BufferSource& signature, const BufferSource& userHandle);
     
    5253    void makeCredential(const Vector<uint8_t>&, const PublicKeyCredentialCreationOptions&, CreationCompletionHandler&&) final;
    5354    void getAssertion(const Vector<uint8_t>& hash, const PublicKeyCredentialRequestOptions&, RequestCompletionHandler&&) final;
     55    void isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&&) final;
    5456    void makeCredentialReply(uint64_t messageId, const Vector<uint8_t>&) final;
    5557    void getAssertionReply(uint64_t messageId, const Vector<uint8_t>& credentialId, const Vector<uint8_t>& authenticatorData, const Vector<uint8_t>& signature, const Vector<uint8_t>& userHandle) final;
     58    void isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool) final;
    5659
    5760    Internals& m_internals;
     
    5962    bool m_didTimeOut { false };
    6063    bool m_didUserCancel { false };
     64    bool m_didUserVerifyingPlatformAuthenticatorPresent { false };
    6165    Vector<uint8_t> m_attestationObject;
    6266    Vector<uint8_t> m_credentialId;
  • trunk/Source/WebCore/testing/MockCredentialsMessenger.idl

    r228523 r228572  
    3030    void setDidTimeOut();
    3131    void setDidUserCancel();
     32    void setDidUserVerifyingPlatformAuthenticatorPresent();
    3233    void setAttestationObject(BufferSource attestationObject);
    3334    void setAssertionReturnBundle(BufferSource credentialId, BufferSource authenticatorData, BufferSource signature, BufferSource userHandle);
  • trunk/Source/WebKit/ChangeLog

    r228569 r228572  
     12018-02-16  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthN] Implement PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
     4        https://bugs.webkit.org/show_bug.cgi?id=182771
     5        <rdar://problem/36459988>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        This patch utilizes LocalAuthentication Framework to determine if biometrics
     10        are enrolled on a device, which is the user verifying platform authenticator.
     11        To do so, it links the framework to WebKit.
     12
     13        * UIProcess/CredentialManagement/WebCredentialsMessengerProxy.cpp:
     14        (WebKit::WebCredentialsMessengerProxy::isUserVerifyingPlatformAuthenticatorAvailable):
     15        (WebKit::WebCredentialsMessengerProxy::isUserVerifyingPlatformAuthenticatorAvailableReply):
     16        * UIProcess/CredentialManagement/WebCredentialsMessengerProxy.h:
     17        * UIProcess/CredentialManagement/WebCredentialsMessengerProxy.messages.in:
     18        * UIProcess/CredentialManagement/cocoa/WebCredentialsMessengerProxyCocoa.mm:
     19        (WebKit::WebCredentialsMessengerProxy::platformIsUserVerifyingPlatformAuthenticatorAvailable):
     20        * WebKit.xcodeproj/project.pbxproj:
     21        * WebProcess/CredentialManagement/WebCredentialsMessenger.cpp:
     22        (WebKit::WebCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailable):
     23        (WebKit::WebCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailableReply):
     24        * WebProcess/CredentialManagement/WebCredentialsMessenger.h:
     25        * WebProcess/CredentialManagement/WebCredentialsMessenger.messages.in:
     26
    1272018-02-16  Per Arne Vollan  <pvollan@apple.com>
    228
  • trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.cpp

    r228523 r228572  
    5151}
    5252
     53void WebCredentialsMessengerProxy::isUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId)
     54{
     55    platformIsUserVerifyingPlatformAuthenticatorAvailable(messageId);
     56}
     57
    5358void WebCredentialsMessengerProxy::getAssertion(uint64_t)
    5459{
     60}
     61
     62void WebCredentialsMessengerProxy::isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool result)
     63{
     64    m_webPageProxy.send(Messages::WebCredentialsMessenger::IsUserVerifyingPlatformAuthenticatorAvailableReply(messageId, result));
    5565}
    5666
  • trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.h

    r228523 r228572  
    4646    void makeCredential(uint64_t messageId);
    4747    void getAssertion(uint64_t messageId);
     48    void isUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId);
     49
     50    // Senders.
     51    void isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool);
     52
     53    // Platform specific procedures.
     54    // FIXME(182768): Might change to some forms of delegates later on.
     55    // FIXME(182769): Figure out a way to auto-test the followings.
     56    void platformIsUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId);
    4857
    4958    WebPageProxy& m_webPageProxy;
  • trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.messages.in

    r228523 r228572  
    2929    MakeCredential(uint64_t messageId);
    3030    GetAssertion(uint64_t messageId);
     31    IsUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId);
    3132}
    3233
  • trunk/Source/WebKit/UIProcess/CredentialManagement/cocoa/WebCredentialsMessengerProxyCocoa.mm

    r228571 r228572  
    2424 */
    2525
    26 #include "config.h"
    27 #include "WebCredentialsMessengerProxy.h"
     26#import "config.h"
     27#import "WebCredentialsMessengerProxy.h"
    2828
    2929#if ENABLE(WEB_AUTHN)
    3030
    31 #include "WebCredentialsMessengerMessages.h"
    32 #include "WebCredentialsMessengerProxyMessages.h"
    33 #include "WebPageProxy.h"
    34 #include "WebProcessProxy.h"
     31#import <LocalAuthentication/LocalAuthentication.h>
     32#import <WebCore/NotImplemented.h>
     33#import <wtf/RetainPtr.h>
    3534
    3635namespace WebKit {
    3736
    38 WebCredentialsMessengerProxy::WebCredentialsMessengerProxy(WebPageProxy& webPageProxy)
    39     : m_webPageProxy(webPageProxy)
     37void WebCredentialsMessengerProxy::platformIsUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId)
    4038{
    41     m_webPageProxy.process().addMessageReceiver(Messages::WebCredentialsMessengerProxy::messageReceiverName(), m_webPageProxy.pageID(), *this);
    42 }
     39#if defined(__i386__)
     40    ASSERT_UNUSED(messageId, messageId);
     41    notImplemented();
     42#else
     43    auto context = adoptNS([[LAContext alloc] init]);
     44    NSError *error = nil;
    4345
    44 WebCredentialsMessengerProxy::~WebCredentialsMessengerProxy()
    45 {
    46     m_webPageProxy.process().removeMessageReceiver(Messages::WebCredentialsMessengerProxy::messageReceiverName(), m_webPageProxy.pageID());
    47 }
    48 
    49 void WebCredentialsMessengerProxy::makeCredential(uint64_t)
    50 {
    51 }
    52 
    53 void WebCredentialsMessengerProxy::getAssertion(uint64_t)
    54 {
     46    if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error])
     47        isUserVerifyingPlatformAuthenticatorAvailableReply(messageId, true);
     48    else {
     49        LOG_ERROR("Couldn't evaluate authentication with biometrics policy: %@", error);
     50        isUserVerifyingPlatformAuthenticatorAvailableReply(messageId, false);
     51    }
     52#endif // defined(__i386__)
    5553}
    5654
  • trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj

    r228557 r228572  
    12121212                53BA47D11DC2EF5E004DF4AD /* NetworkDataTaskBlob.h in Headers */ = {isa = PBXBuildFile; fileRef = 539EB5471DC2EE40009D48CF /* NetworkDataTaskBlob.h */; };
    12131213                53DEA3661DDE423100E82648 /* json.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 53DEA3651DDE422E00E82648 /* json.hpp */; };
     1214                5750F32B2032D4E500389347 /* LocalAuthentication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5750F32A2032D4E500389347 /* LocalAuthentication.framework */; };
    12141215                5760828E2029895E00116678 /* WebCredentialsMessenger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5760828C2029854200116678 /* WebCredentialsMessenger.cpp */; };
    12151216                57608298202BD8BA00116678 /* WebCredentialsMessengerProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57608296202BD8BA00116678 /* WebCredentialsMessengerProxy.cpp */; };
     
    12181219                5760829E202D2C4300116678 /* WebCredentialsMessengerProxyMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5760829A202BEE5A00116678 /* WebCredentialsMessengerProxyMessageReceiver.cpp */; };
    12191220                5760829F202D2C4600116678 /* WebCredentialsMessengerProxyMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 5760829B202BEE5A00116678 /* WebCredentialsMessengerProxyMessages.h */; };
     1221                57B90AAD203637F4000E61FA /* WebCredentialsMessengerProxyCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57B90AAC203637F4000E61FA /* WebCredentialsMessengerProxyCocoa.mm */; };
    12201222                5C0B17781E7C880E00E9123C /* NetworkSocketStreamMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C0B17741E7C879C00E9123C /* NetworkSocketStreamMessageReceiver.cpp */; };
    12211223                5C0B17791E7C882100E9123C /* WebSocketStreamMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C0B17761E7C879C00E9123C /* WebSocketStreamMessageReceiver.cpp */; };
     
    36413643                539EB5471DC2EE40009D48CF /* NetworkDataTaskBlob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkDataTaskBlob.h; path = NetworkProcess/NetworkDataTaskBlob.h; sourceTree = "<group>"; };
    36423644                53DEA3651DDE422E00E82648 /* json.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = json.hpp; path = NetworkProcess/capture/json.hpp; sourceTree = "<group>"; };
     3645                5750F32A2032D4E500389347 /* LocalAuthentication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LocalAuthentication.framework; path = System/Library/Frameworks/LocalAuthentication.framework; sourceTree = SDKROOT; };
    36433646                5760828B2029854200116678 /* WebCredentialsMessenger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebCredentialsMessenger.h; sourceTree = "<group>"; };
    36443647                5760828C2029854200116678 /* WebCredentialsMessenger.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebCredentialsMessenger.cpp; sourceTree = "<group>"; };
     
    36513654                5760829A202BEE5A00116678 /* WebCredentialsMessengerProxyMessageReceiver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebCredentialsMessengerProxyMessageReceiver.cpp; sourceTree = "<group>"; };
    36523655                5760829B202BEE5A00116678 /* WebCredentialsMessengerProxyMessages.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebCredentialsMessengerProxyMessages.h; sourceTree = "<group>"; };
     3656                57B90AAC203637F4000E61FA /* WebCredentialsMessengerProxyCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCredentialsMessengerProxyCocoa.mm; sourceTree = "<group>"; };
    36533657                5C0B17741E7C879C00E9123C /* NetworkSocketStreamMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkSocketStreamMessageReceiver.cpp; sourceTree = "<group>"; };
    36543658                5C0B17751E7C879C00E9123C /* NetworkSocketStreamMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkSocketStreamMessages.h; sourceTree = "<group>"; };
     
    47234727                                3766F9EE189A1241003CF19B /* JavaScriptCore.framework in Frameworks */,
    47244728                                3766F9F1189A1254003CF19B /* libicucore.dylib in Frameworks */,
     4729                                5750F32B2032D4E500389347 /* LocalAuthentication.framework in Frameworks */,
    47254730                                3766F9EF189A1244003CF19B /* QuartzCore.framework in Frameworks */,
    47264731                                37694525184FC6B600CDE21F /* Security.framework in Frameworks */,
     
    48154820                                0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
    48164821                                034768DFFF38A50411DB9C8B /* Products */,
     4822                                5750F3292032D4E300389347 /* Frameworks */,
    48174823                        );
    48184824                        name = WebKit2;
     
    67036709                        sourceTree = "<group>";
    67046710                };
     6711                5750F3292032D4E300389347 /* Frameworks */ = {
     6712                        isa = PBXGroup;
     6713                        children = (
     6714                                5750F32A2032D4E500389347 /* LocalAuthentication.framework */,
     6715                        );
     6716                        name = Frameworks;
     6717                        sourceTree = "<group>";
     6718                };
    67056719                5760828A202984C900116678 /* CredentialManagement */ = {
    67066720                        isa = PBXGroup;
     
    67166730                        isa = PBXGroup;
    67176731                        children = (
     6732                                57B90AAB20363758000E61FA /* cocoa */,
    67186733                                57608296202BD8BA00116678 /* WebCredentialsMessengerProxy.cpp */,
    67196734                                57608295202BD8BA00116678 /* WebCredentialsMessengerProxy.h */,
     
    67216736                        );
    67226737                        path = CredentialManagement;
     6738                        sourceTree = "<group>";
     6739                };
     6740                57B90AAB20363758000E61FA /* cocoa */ = {
     6741                        isa = PBXGroup;
     6742                        children = (
     6743                                57B90AAC203637F4000E61FA /* WebCredentialsMessengerProxyCocoa.mm */,
     6744                        );
     6745                        path = cocoa;
    67236746                        sourceTree = "<group>";
    67246747                };
     
    1085610879                                5760829C202D2C3C00116678 /* WebCredentialsMessengerMessageReceiver.cpp in Sources */,
    1085710880                                57608298202BD8BA00116678 /* WebCredentialsMessengerProxy.cpp in Sources */,
     10881                                57B90AAD203637F4000E61FA /* WebCredentialsMessengerProxyCocoa.mm in Sources */,
    1085810882                                5760829E202D2C4300116678 /* WebCredentialsMessengerProxyMessageReceiver.cpp in Sources */,
    1085910883                                1AA83F6C1A5B63FF00026EC6 /* WebDatabaseProvider.cpp in Sources */,
  • trunk/Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.cpp

    r228523 r228572  
    5555}
    5656
     57void WebCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailable(WebCore::QueryCompletionHandler&& handler)
     58{
     59    auto messageId = addQueryCompletionHandler(WTFMove(handler));
     60    m_webPage.send(Messages::WebCredentialsMessengerProxy::IsUserVerifyingPlatformAuthenticatorAvailable(messageId));
     61}
     62
    5763void WebCredentialsMessenger::makeCredentialReply(uint64_t messageId, const Vector<uint8_t>&)
    5864{
     
    6369}
    6470
     71void WebCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool result)
     72{
     73    auto handler = takeQueryCompletionHandler(messageId);
     74    handler(result);
     75}
     76
     77
    6578} // namespace WebKit
    6679
  • trunk/Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.h

    r228523 r228572  
    4545    void makeCredential(const Vector<uint8_t>&, const WebCore::PublicKeyCredentialCreationOptions&, WebCore::CreationCompletionHandler&&) final;
    4646    void getAssertion(const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialRequestOptions&, WebCore::RequestCompletionHandler&&) final;
     47    void isUserVerifyingPlatformAuthenticatorAvailable(WebCore::QueryCompletionHandler&&) final;
    4748
    4849    // receiver
    4950    void makeCredentialReply(uint64_t messageId, const Vector<uint8_t>&) final;
    5051    void getAssertionReply(uint64_t messageId, const Vector<uint8_t>& credentialId, const Vector<uint8_t>& authenticatorData, const Vector<uint8_t>& signature, const Vector<uint8_t>& userHandle) final;
     52    void isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool) final;
    5153
    5254    // IPC::MessageReceiver.
  • trunk/Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.messages.in

    r228523 r228572  
    3030    MakeCredentialReply(uint64_t messageId, Vector<uint8_t> attestationObject);
    3131    GetAssertionReply(uint64_t messageId, Vector<uint8_t> credentialId, Vector<uint8_t> authenticatorData, Vector<uint8_t> signature, Vector<uint8_t> userHandle);
     32    IsUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool result);
     33exceptionReply(uint64_t messageId, struct WebCore::ExceptionData exception);
    3234}
    3335
Note: See TracChangeset for help on using the changeset viewer.