[WebAuthN] Implement PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
authorjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Feb 2018 20:43:28 +0000 (20:43 +0000)
committerjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Feb 2018 20:43:28 +0000 (20:43 +0000)
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.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@228572 268f45cc-cd09-0410-ab3c-d52691b4dbfc

24 files changed:
LayoutTests/ChangeLog
LayoutTests/http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available-expected.txt [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/credentialmanagement/CredentialsContainer.cpp
Source/WebCore/Modules/credentialmanagement/CredentialsContainer.h
Source/WebCore/Modules/credentialmanagement/CredentialsMessenger.cpp
Source/WebCore/Modules/credentialmanagement/CredentialsMessenger.h
Source/WebCore/Modules/webauthn/AuthenticatorManager.cpp
Source/WebCore/Modules/webauthn/AuthenticatorManager.h
Source/WebCore/Modules/webauthn/PublicKeyCredential.cpp
Source/WebCore/Modules/webauthn/PublicKeyCredential.h
Source/WebCore/testing/MockCredentialsMessenger.cpp
Source/WebCore/testing/MockCredentialsMessenger.h
Source/WebCore/testing/MockCredentialsMessenger.idl
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.cpp
Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.h
Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.messages.in
Source/WebKit/UIProcess/CredentialManagement/cocoa/WebCredentialsMessengerProxyCocoa.mm [new file with mode: 0644]
Source/WebKit/WebKit.xcodeproj/project.pbxproj
Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.cpp
Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.h
Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.messages.in

index fe66a9b..be437b4 100644 (file)
@@ -1,3 +1,14 @@
+2018-02-16  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebAuthN] Implement PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
+        https://bugs.webkit.org/show_bug.cgi?id=182771
+        <rdar://problem/36459988>
+
+        Reviewed by Brent Fulgham.
+
+        * 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.
+
 2018-02-16  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         fast/frames/sandboxed-iframe-navigation-top-denied.html is crashing in Inspector::createScriptCallStackForConsole::Exec for GTK
diff --git a/LayoutTests/http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available-expected.txt b/LayoutTests/http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available-expected.txt
new file mode 100644 (file)
index 0000000..ef2a216
--- /dev/null
@@ -0,0 +1,4 @@
+
+PASS PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() without any available authenticators. 
+PASS PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() with available authenticators. 
+
diff --git a/LayoutTests/http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available.html b/LayoutTests/http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available.html
new file mode 100644 (file)
index 0000000..da8e534
--- /dev/null
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>Web Authentication API: PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+    promise_test(function(t) {
+        internals.mockCredentialsMessenger;
+
+        return PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().then(function(result) {
+            assert_equals(result, false);
+        });
+    }, "PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() without any available authenticators.");
+
+    promise_test(function(t) {
+        internals.mockCredentialsMessenger.setDidUserVerifyingPlatformAuthenticatorPresent();
+
+        return PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().then(function(result) {
+            assert_equals(result, true);
+        });
+    }, "PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() with available authenticators.");
+</script>
index 6badc59..028cdf4 100644 (file)
@@ -1,3 +1,49 @@
+2018-02-16  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebAuthN] Implement PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
+        https://bugs.webkit.org/show_bug.cgi?id=182771
+        <rdar://problem/36459988>
+
+        Reviewed by Brent Fulgham.
+
+        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:
+
 2018-02-16  Tim Horton  <timothy_horton@apple.com>
 
         Stop using EXCLUDED_SOURCE_FILE_NAMES for touch and gesture files in WebCore
index fb7d441..ad64b61 100644 (file)
@@ -30,7 +30,6 @@
 #if ENABLE(WEB_AUTHN)
 
 #include "AbortSignal.h"
-#include "AuthenticatorManager.h"
 #include "CredentialCreationOptions.h"
 #include "CredentialRequestOptions.h"
 #include "Document.h"
@@ -60,16 +59,16 @@ bool CredentialsContainer::doesHaveSameOriginAsItsAncestors()
     return true;
 }
 
-void CredentialsContainer::get(CredentialRequestOptions&& options, Ref<DeferredPromise>&& promise)
+void CredentialsContainer::get(CredentialRequestOptions&& options, CredentialPromise&& promise)
 {
     // The following implements https://www.w3.org/TR/credential-management-1/#algorithm-request as of 4 August 2017
     // with enhancement from 14 November 2017 Editor's Draft.
     if (!m_document) {
-        promise->reject(Exception { NotSupportedError });
+        promise.reject(Exception { NotSupportedError });
         return;
     }
     if (options.signal && options.signal->aborted()) {
-        promise->reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
+        promise.reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
         return;
     }
     // Step 1-2.
@@ -79,7 +78,7 @@ void CredentialsContainer::get(CredentialRequestOptions&& options, Ref<DeferredP
     // Step 4-6. Shortcut as we only support PublicKeyCredential which can only
     // be requested from [[discoverFromExternalSource]].
     if (!options.publicKey) {
-        promise->reject(Exception { NotSupportedError, ASCIILiteral("Only PublicKeyCredential is supported.") });
+        promise.reject(Exception { NotSupportedError, ASCIILiteral("Only PublicKeyCredential is supported.") });
         return;
     }
 
@@ -87,21 +86,21 @@ void CredentialsContainer::get(CredentialRequestOptions&& options, Ref<DeferredP
     AuthenticatorManager::singleton().discoverFromExternalSource(m_document->securityOrigin(), options.publicKey.value(), doesHaveSameOriginAsItsAncestors(), WTFMove(options.signal), WTFMove(promise));
 }
 
-void CredentialsContainer::store(const BasicCredential&, Ref<DeferredPromise>&& promise)
+void CredentialsContainer::store(const BasicCredential&, CredentialPromise&& promise)
 {
-    promise->reject(Exception { NotSupportedError, ASCIILiteral("Not implemented.") });
+    promise.reject(Exception { NotSupportedError, ASCIILiteral("Not implemented.") });
 }
 
-void CredentialsContainer::isCreate(CredentialCreationOptions&& options, Ref<DeferredPromise>&& promise)
+void CredentialsContainer::isCreate(CredentialCreationOptions&& options, CredentialPromise&& promise)
 {
     // The following implements https://www.w3.org/TR/credential-management-1/#algorithm-create as of 4 August 2017
     // with enhancement from 14 November 2017 Editor's Draft.
     if (!m_document) {
-        promise->reject(Exception { NotSupportedError });
+        promise.reject(Exception { NotSupportedError });
         return;
     }
     if (options.signal && options.signal->aborted()) {
-        promise->reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
+        promise.reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
         return;
     }
     // Step 1-2.
@@ -109,7 +108,7 @@ void CredentialsContainer::isCreate(CredentialCreationOptions&& options, Ref<Def
 
     // Step 3-7. Shortcut as we only support one kind of credentials.
     if (!options.publicKey) {
-        promise->reject(Exception { NotSupportedError, ASCIILiteral("Only PublicKeyCredential is supported.") });
+        promise.reject(Exception { NotSupportedError, ASCIILiteral("Only PublicKeyCredential is supported.") });
         return;
     }
 
@@ -117,9 +116,9 @@ void CredentialsContainer::isCreate(CredentialCreationOptions&& options, Ref<Def
     AuthenticatorManager::singleton().create(m_document->securityOrigin(), options.publicKey.value(), doesHaveSameOriginAsItsAncestors(), WTFMove(options.signal), WTFMove(promise));
 }
 
-void CredentialsContainer::preventSilentAccess(Ref<DeferredPromise>&& promise) const
+void CredentialsContainer::preventSilentAccess(DOMPromiseDeferred<void>&& promise) const
 {
-    promise->reject(Exception { NotSupportedError, ASCIILiteral("Not implemented.") });
+    promise.reject(Exception { NotSupportedError, ASCIILiteral("Not implemented.") });
 }
 
 } // namespace WebCore
index 07607e3..2d5b38b 100644 (file)
 
 #if ENABLE(WEB_AUTHN)
 
+#include "AuthenticatorManager.h"
 #include <wtf/RefCounted.h>
 #include <wtf/WeakPtr.h>
 
 namespace WebCore {
 
-class BasicCredential;
-class DeferredPromise;
 class Document;
 
 struct CredentialCreationOptions;
@@ -44,13 +43,13 @@ class CredentialsContainer : public RefCounted<CredentialsContainer> {
 public:
     static Ref<CredentialsContainer> create(WeakPtr<Document>&& document) { return adoptRef(*new CredentialsContainer(WTFMove(document))); }
 
-    void get(CredentialRequestOptions&&, Ref<DeferredPromise>&&);
+    void get(CredentialRequestOptions&&, CredentialPromise&&);
 
-    void store(const BasicCredential&, Ref<DeferredPromise>&&);
+    void store(const BasicCredential&, CredentialPromise&&);
 
-    void isCreate(CredentialCreationOptions&&, Ref<DeferredPromise>&&);
+    void isCreate(CredentialCreationOptions&&, CredentialPromise&&);
 
-    void preventSilentAccess(Ref<DeferredPromise>&&) const;
+    void preventSilentAccess(DOMPromiseDeferred<void>&&) const;
 
 private:
     CredentialsContainer(WeakPtr<Document>&&);
index d76ed36..b560c61 100644 (file)
@@ -68,7 +68,6 @@ uint64_t CredentialsMessenger::addCreationCompletionHandler(CreationCompletionHa
     messageId = messageId | CallBackClassifier::Creation << callBackClassifierOffset;
     auto addResult = m_pendingCreationCompletionHandlers.add(messageId, WTFMove(handler));
     ASSERT_UNUSED(addResult, addResult.isNewEntry);
-    ASSERT(addResult);
     return messageId;
 }
 
@@ -86,7 +85,6 @@ uint64_t CredentialsMessenger::addRequestCompletionHandler(RequestCompletionHand
     messageId = messageId | CallBackClassifier::Request << callBackClassifierOffset;
     auto addResult = m_pendingRequestCompletionHandlers.add(messageId, WTFMove(handler));
     ASSERT_UNUSED(addResult, addResult.isNewEntry);
-    ASSERT(addResult);
     return messageId;
 }
 
@@ -95,6 +93,23 @@ RequestCompletionHandler CredentialsMessenger::takeRequestCompletionHandler(uint
     return m_pendingRequestCompletionHandlers.take(messageId);
 }
 
+uint64_t CredentialsMessenger::addQueryCompletionHandler(QueryCompletionHandler&& handler)
+{
+    using namespace CredentialsMessengerInternal;
+
+    uint64_t messageId = m_accumulatedMessageId++;
+    ASSERT(messageId < maxMessageId);
+    messageId = messageId | CallBackClassifier::Query << callBackClassifierOffset;
+    auto addResult = m_pendingQueryCompletionHandlers.add(messageId, WTFMove(handler));
+    ASSERT_UNUSED(addResult, addResult.isNewEntry);
+    return messageId;
+}
+
+QueryCompletionHandler CredentialsMessenger::takeQueryCompletionHandler(uint64_t messageId)
+{
+    return m_pendingQueryCompletionHandlers.take(messageId);
+}
+
 RefPtr<ArrayBuffer> getIdFromAttestationObject(const Vector<uint8_t>& attestationObject)
 {
     using namespace CredentialsMessengerInternal;
index 927b67a..9cb6706 100644 (file)
@@ -68,6 +68,7 @@ struct AssertionReturnBundle {
 
 using CreationCompletionHandler = CompletionHandler<void(ExceptionOr<CreationReturnBundle>&&)>;
 using RequestCompletionHandler = CompletionHandler<void(ExceptionOr<AssertionReturnBundle>&&)>;
+using QueryCompletionHandler = CompletionHandler<void(bool)>;
 
 class CredentialsMessenger {
     WTF_MAKE_FAST_ALLOCATED;
@@ -75,11 +76,13 @@ public:
     // sender
     virtual void makeCredential(const Vector<uint8_t>& hash, const PublicKeyCredentialCreationOptions&, CreationCompletionHandler&&) = 0;
     virtual void getAssertion(const Vector<uint8_t>& hash, const PublicKeyCredentialRequestOptions&, RequestCompletionHandler&&) = 0;
+    virtual void isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&&) = 0;
 
     // receiver
     WEBCORE_EXPORT void exceptionReply(uint64_t messageId, const ExceptionData&);
     virtual void makeCredentialReply(uint64_t messageId, const Vector<uint8_t>&) = 0;
     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;
+    virtual void isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool) = 0;
 
     auto& weakPtrFactory() const { return m_weakFactory; }
 
@@ -90,6 +93,8 @@ protected:
     WEBCORE_EXPORT CreationCompletionHandler takeCreationCompletionHandler(uint64_t);
     WEBCORE_EXPORT uint64_t addRequestCompletionHandler(RequestCompletionHandler&&);
     WEBCORE_EXPORT RequestCompletionHandler takeRequestCompletionHandler(uint64_t);
+    WEBCORE_EXPORT uint64_t addQueryCompletionHandler(QueryCompletionHandler&&);
+    WEBCORE_EXPORT QueryCompletionHandler takeQueryCompletionHandler(uint64_t);
 
 private:
     WeakPtrFactory<CredentialsMessenger> m_weakFactory;
@@ -103,6 +108,7 @@ private:
     uint64_t m_accumulatedMessageId { 1 };
     HashMap<uint64_t, CreationCompletionHandler> m_pendingCreationCompletionHandlers;
     HashMap<uint64_t, RequestCompletionHandler> m_pendingRequestCompletionHandlers;
+    HashMap<uint64_t, QueryCompletionHandler> m_pendingQueryCompletionHandlers;
 };
 
 // FIXME: We shouldn't expose this into the messenger. Since the receivers can only be passed with const references, we couldn't
index c7fb14f..e22c493 100644 (file)
@@ -33,7 +33,6 @@
 #include "AuthenticatorAttestationResponse.h"
 #include "CredentialsMessenger.h"
 #include "JSBasicCredential.h"
-#include "JSDOMPromiseDeferred.h"
 #include "PublicKeyCredential.h"
 #include "PublicKeyCredentialCreationOptions.h"
 #include "PublicKeyCredentialRequestOptions.h"
@@ -83,13 +82,13 @@ static Vector<uint8_t> produceClientDataJsonHash(const ArrayBuffer& clientDataJs
 }
 
 // FIXME(181947): We should probably trim timeOutInMs to some max allowable number.
-static std::unique_ptr<Timer> initTimeoutTimer(std::optional<unsigned long> timeOutInMs, const Ref<DeferredPromise>& promise)
+static std::unique_ptr<Timer> initTimeoutTimer(std::optional<unsigned long> timeOutInMs, const CredentialPromise& promise)
 {
     if (!timeOutInMs)
         return nullptr;
 
-    auto timer = std::make_unique<Timer>([promise = promise.copyRef()] () {
-        promise->reject(Exception { NotAllowedError, ASCIILiteral("Operation timed out.") });
+    auto timer = std::make_unique<Timer>([promise = promise] () mutable {
+        promise.reject(Exception { NotAllowedError, ASCIILiteral("Operation timed out.") });
     });
     timer->startOneShot(Seconds::fromMilliseconds(*timeOutInMs));
     return timer;
@@ -119,7 +118,7 @@ void AuthenticatorManager::setMessenger(CredentialsMessenger& messenger)
     m_messenger = makeWeakPtr(messenger);
 }
 
-void AuthenticatorManager::create(const SecurityOrigin& callerOrigin, const PublicKeyCredentialCreationOptions& options, bool sameOriginWithAncestors, RefPtr<AbortSignal>&& abortSignal, Ref<DeferredPromise>&& promise) const
+void AuthenticatorManager::create(const SecurityOrigin& callerOrigin, const PublicKeyCredentialCreationOptions& options, bool sameOriginWithAncestors, RefPtr<AbortSignal>&& abortSignal, CredentialPromise&& promise) const
 {
     using namespace AuthenticatorManagerInternal;
 
@@ -128,7 +127,7 @@ void AuthenticatorManager::create(const SecurityOrigin& callerOrigin, const Publ
     // Step 1, 3, 16 are handled by the caller.
     // Step 2.
     if (!sameOriginWithAncestors) {
-        promise->reject(Exception { NotAllowedError, ASCIILiteral("The origin of the document is not the same as its ancestors.") });
+        promise.reject(Exception { NotAllowedError, ASCIILiteral("The origin of the document is not the same as its ancestors.") });
         return;
     }
 
@@ -140,7 +139,7 @@ void AuthenticatorManager::create(const SecurityOrigin& callerOrigin, const Publ
     // Step 6 is therefore skipped. Also, we lack the support to determine whether a domain is a registrable
     // domain suffix of another domain. Hence restrict the comparison to equal in Step 7.
     if (!options.rp.id.isEmpty() && callerOrigin.host() != options.rp.id) {
-        promise->reject(Exception { SecurityError, ASCIILiteral("The origin of the document is not a registrable domain suffix of the provided RP ID.") });
+        promise.reject(Exception { SecurityError, ASCIILiteral("The origin of the document is not a registrable domain suffix of the provided RP ID.") });
         return;
     }
     if (options.rp.id.isEmpty())
@@ -150,7 +149,7 @@ void AuthenticatorManager::create(const SecurityOrigin& callerOrigin, const Publ
     // Most of the jobs are done by bindings. However, we can't know if the JSValue of options.pubKeyCredParams
     // is empty or not. Return NotSupportedError as long as it is empty.
     if (options.pubKeyCredParams.isEmpty()) {
-        promise->reject(Exception { NotSupportedError, ASCIILiteral("No desired properties of the to be created credential are provided.") });
+        promise.reject(Exception { NotSupportedError, ASCIILiteral("No desired properties of the to be created credential are provided.") });
         return;
     }
 
@@ -163,7 +162,7 @@ void AuthenticatorManager::create(const SecurityOrigin& callerOrigin, const Publ
     // Also, resident keys, user verifications and direct attestation are enforced at this tage.
     // For better performance, no filtering is done here regarding to options.excludeCredentials.
     if (!m_messenger)  {
-        promise->reject(Exception { UnknownError, ASCIILiteral("Unknown internal error.") });
+        promise.reject(Exception { UnknownError, ASCIILiteral("Unknown internal error.") });
         return;
     }
 
@@ -171,22 +170,22 @@ void AuthenticatorManager::create(const SecurityOrigin& callerOrigin, const Publ
         if (didTimeoutTimerFire(timeoutTimer.get()))
             return;
         if (abortSignal && abortSignal->aborted()) {
-            promise->reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
+            promise.reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
             return;
         }
         if (result.hasException()) {
-            promise->reject(result.exception());
+            promise.reject(result.exception());
             return;
         }
 
         auto bundle = result.releaseReturnValue();
-        promise->resolve<IDLNullable<IDLInterface<BasicCredential>>>(PublicKeyCredential::create(WTFMove(bundle.credentialId), AuthenticatorAttestationResponse::create(WTFMove(clientDataJson), ArrayBuffer::create(WTFMove(bundle.attestationObject)))).ptr());
+        promise.resolve(PublicKeyCredential::create(WTFMove(bundle.credentialId), AuthenticatorAttestationResponse::create(WTFMove(clientDataJson), ArrayBuffer::create(WTFMove(bundle.attestationObject)))).ptr());
     };
     // Async operations are dispatched and handled in the messenger.
     m_messenger->makeCredential(clientDataJsonHash, options, WTFMove(completionHandler));
 }
 
-void AuthenticatorManager::discoverFromExternalSource(const SecurityOrigin& callerOrigin, const PublicKeyCredentialRequestOptions& options, bool sameOriginWithAncestors, RefPtr<AbortSignal>&& abortSignal, Ref<DeferredPromise>&& promise) const
+void AuthenticatorManager::discoverFromExternalSource(const SecurityOrigin& callerOrigin, const PublicKeyCredentialRequestOptions& options, bool sameOriginWithAncestors, RefPtr<AbortSignal>&& abortSignal, CredentialPromise&& promise) const
 {
     using namespace AuthenticatorManagerInternal;
 
@@ -195,7 +194,7 @@ void AuthenticatorManager::discoverFromExternalSource(const SecurityOrigin& call
     // Step 1, 3, 13 are handled by the caller.
     // Step 2.
     if (!sameOriginWithAncestors) {
-        promise->reject(Exception { NotAllowedError, ASCIILiteral("The origin of the document is not the same as its ancestors.") });
+        promise.reject(Exception { NotAllowedError, ASCIILiteral("The origin of the document is not the same as its ancestors.") });
         return;
     }
 
@@ -207,7 +206,7 @@ void AuthenticatorManager::discoverFromExternalSource(const SecurityOrigin& call
     // Step 6 is therefore skipped. Also, we lack the support to determine whether a domain is a registrable
     // domain suffix of another domain. Hence restrict the comparison to equal in Step 7.
     if (!options.rpId.isEmpty() && callerOrigin.host() != options.rpId) {
-        promise->reject(Exception { SecurityError, ASCIILiteral("The origin of the document is not a registrable domain suffix of the provided RP ID.") });
+        promise.reject(Exception { SecurityError, ASCIILiteral("The origin of the document is not a registrable domain suffix of the provided RP ID.") });
         return;
     }
     if (options.rpId.isEmpty())
@@ -222,7 +221,7 @@ void AuthenticatorManager::discoverFromExternalSource(const SecurityOrigin& call
     // Also, resident keys, user verifications and direct attestation are enforced at this tage.
     // For better performance, no filtering is done here regarding to options.allowCredentials.
     if (!m_messenger)  {
-        promise->reject(Exception { UnknownError, ASCIILiteral("Unknown internal error.") });
+        promise.reject(Exception { UnknownError, ASCIILiteral("Unknown internal error.") });
         return;
     }
 
@@ -230,21 +229,39 @@ void AuthenticatorManager::discoverFromExternalSource(const SecurityOrigin& call
         if (didTimeoutTimerFire(timeoutTimer.get()))
             return;
         if (abortSignal && abortSignal->aborted()) {
-            promise->reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
+            promise.reject(Exception { AbortError, ASCIILiteral("Aborted by AbortSignal.") });
             return;
         }
         if (result.hasException()) {
-            promise->reject(result.exception());
+            promise.reject(result.exception());
             return;
         }
 
         auto bundle = result.releaseReturnValue();
-        promise->resolve<IDLNullable<IDLInterface<BasicCredential>>>(PublicKeyCredential::create(WTFMove(bundle.credentialId), AuthenticatorAssertionResponse::create(WTFMove(clientDataJson), WTFMove(bundle.authenticatorData), WTFMove(bundle.signature), WTFMove(bundle.userHandle))).ptr());
+        promise.resolve(PublicKeyCredential::create(WTFMove(bundle.credentialId), AuthenticatorAssertionResponse::create(WTFMove(clientDataJson), WTFMove(bundle.authenticatorData), WTFMove(bundle.signature), WTFMove(bundle.userHandle))).ptr());
     };
     // Async operations are dispatched and handled in the messenger.
     m_messenger->getAssertion(clientDataJsonHash, options, WTFMove(completionHandler));
 }
 
+void AuthenticatorManager::isUserVerifyingPlatformAuthenticatorAvailable(DOMPromiseDeferred<IDLBoolean>&& promise) const
+{
+    // The following implements https://www.w3.org/TR/webauthn/#isUserVerifyingPlatformAuthenticatorAvailable
+    // as of 5 December 2017.
+    if (!m_messenger)  {
+        promise.reject(Exception { UnknownError, ASCIILiteral("Unknown internal error.") });
+        return;
+    }
+
+    // FIXME(182767): We should consider more on the assessment of the return value. Right now, we return true/false
+    // immediately according to platform specific procedures.
+    auto completionHandler = [promise = WTFMove(promise)] (bool result) mutable {
+        promise.resolve(result);
+    };
+    // Async operation are dispatched and handled in the messenger.
+    m_messenger->isUserVerifyingPlatformAuthenticatorAvailable(WTFMove(completionHandler));
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(WEB_AUTHN)
index 1745734..637276d 100644 (file)
@@ -27,6 +27,7 @@
 
 #if ENABLE(WEB_AUTHN)
 
+#include "JSDOMPromiseDeferred.h"
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/WeakPtr.h>
 namespace WebCore {
 
 class AbortSignal;
+class BasicCredential;
 class CredentialsMessenger;
-class DeferredPromise;
 class SecurityOrigin;
 
 struct PublicKeyCredentialCreationOptions;
 struct PublicKeyCredentialRequestOptions;
 
+using CredentialPromise = DOMPromiseDeferred<IDLNullable<IDLInterface<BasicCredential>>>;
+
 class AuthenticatorManager {
     WTF_MAKE_NONCOPYABLE(AuthenticatorManager);
     friend class NeverDestroyed<AuthenticatorManager>;
@@ -49,8 +52,9 @@ public:
     WEBCORE_EXPORT void setMessenger(CredentialsMessenger&);
 
     // The following methods implement static methods of PublicKeyCredential.
-    void create(const SecurityOrigin&, const PublicKeyCredentialCreationOptions&, bool sameOriginWithAncestors, RefPtr<AbortSignal>&&, Ref<DeferredPromise>&&) const;
-    void discoverFromExternalSource(const SecurityOrigin&, const PublicKeyCredentialRequestOptions&, bool sameOriginWithAncestors, RefPtr<AbortSignal>&&, Ref<DeferredPromise>&&) const;
+    void create(const SecurityOrigin&, const PublicKeyCredentialCreationOptions&, bool sameOriginWithAncestors, RefPtr<AbortSignal>&&, CredentialPromise&&) const;
+    void discoverFromExternalSource(const SecurityOrigin&, const PublicKeyCredentialRequestOptions&, bool sameOriginWithAncestors, RefPtr<AbortSignal>&&, CredentialPromise&&) const;
+    void isUserVerifyingPlatformAuthenticatorAvailable(DOMPromiseDeferred<IDLBoolean>&&) const;
 
 private:
     AuthenticatorManager() = default;
index 136e5f7..112f40a 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(WEB_AUTHN)
 
+#include "AuthenticatorManager.h"
 #include "JSDOMPromiseDeferred.h"
 #include <wtf/text/Base64.h>
 
@@ -45,9 +46,9 @@ ExceptionOr<bool> PublicKeyCredential::getClientExtensionResults() const
     return Exception { NotSupportedError };
 }
 
-void PublicKeyCredential::isUserVerifyingPlatformAuthenticatorAvailable(Ref<DeferredPromise>&& promise)
+void PublicKeyCredential::isUserVerifyingPlatformAuthenticatorAvailable(DOMPromiseDeferred<IDLBoolean>&& promise)
 {
-    promise->reject(Exception { NotSupportedError });
+    AuthenticatorManager::singleton().isUserVerifyingPlatformAuthenticatorAvailable(WTFMove(promise));
 }
 
 } // namespace WebCore
index 033dd23..fdedc58 100644 (file)
 
 #include "BasicCredential.h"
 #include "ExceptionOr.h"
+#include "JSDOMPromiseDeferred.h"
 #include <JavaScriptCore/ArrayBuffer.h>
 #include <wtf/Forward.h>
 
 namespace WebCore {
 
 class AuthenticatorResponse;
-class DeferredPromise;
 
 class PublicKeyCredential final : public BasicCredential {
 public:
@@ -49,7 +49,7 @@ public:
     // Not support yet. Always throws.
     ExceptionOr<bool> getClientExtensionResults() const;
 
-    static void isUserVerifyingPlatformAuthenticatorAvailable(Ref<DeferredPromise>&&);
+    static void isUserVerifyingPlatformAuthenticatorAvailable(DOMPromiseDeferred<IDLBoolean>&&);
 
 private:
     PublicKeyCredential(RefPtr<ArrayBuffer>&& id, RefPtr<AuthenticatorResponse>&&);
index 2b4d1c7..699cd0c 100644 (file)
@@ -117,6 +117,16 @@ void MockCredentialsMessenger::getAssertion(const Vector<uint8_t>&, const Public
     ASSERT_NOT_REACHED();
 }
 
+void MockCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&& handler)
+{
+    auto messageId = addQueryCompletionHandler(WTFMove(handler));
+    if (m_didUserVerifyingPlatformAuthenticatorPresent) {
+        isUserVerifyingPlatformAuthenticatorAvailableReply(messageId, true);
+        m_didUserVerifyingPlatformAuthenticatorPresent = false;
+    } else
+        isUserVerifyingPlatformAuthenticatorAvailableReply(messageId, false);
+}
+
 void MockCredentialsMessenger::makeCredentialReply(uint64_t messageId, const Vector<uint8_t>& attestationObject)
 {
     auto handler = takeCreationCompletionHandler(messageId);
@@ -129,6 +139,12 @@ void MockCredentialsMessenger::getAssertionReply(uint64_t messageId, const Vecto
     handler(AssertionReturnBundle(ArrayBuffer::create(credentialId.data(), credentialId.size()), ArrayBuffer::create(authenticatorData.data(), authenticatorData.size()), ArrayBuffer::create(signature.data(), signature.size()), ArrayBuffer::create(userHandle.data(), userHandle.size())));
 }
 
+void MockCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool result)
+{
+    auto handler = takeQueryCompletionHandler(messageId);
+    handler(result);
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(WEB_AUTHN)
index 9e3892a..b3a59b6 100644 (file)
@@ -42,6 +42,7 @@ public:
 
     void setDidTimeOut() { m_didTimeOut = true; }
     void setDidUserCancel() { m_didUserCancel = true; }
+    void setDidUserVerifyingPlatformAuthenticatorPresent() { m_didUserVerifyingPlatformAuthenticatorPresent = true; }
     void setAttestationObject(const BufferSource&);
     void setAssertionReturnBundle(const BufferSource& credentialId, const BufferSource& authenticatorData, const BufferSource& signature, const BufferSource& userHandle);
 
@@ -51,13 +52,16 @@ public:
 private:
     void makeCredential(const Vector<uint8_t>&, const PublicKeyCredentialCreationOptions&, CreationCompletionHandler&&) final;
     void getAssertion(const Vector<uint8_t>& hash, const PublicKeyCredentialRequestOptions&, RequestCompletionHandler&&) final;
+    void isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&&) final;
     void makeCredentialReply(uint64_t messageId, const Vector<uint8_t>&) final;
     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;
+    void isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool) final;
 
     Internals& m_internals;
     // All following fields are disposable.
     bool m_didTimeOut { false };
     bool m_didUserCancel { false };
+    bool m_didUserVerifyingPlatformAuthenticatorPresent { false };
     Vector<uint8_t> m_attestationObject;
     Vector<uint8_t> m_credentialId;
     Vector<uint8_t> m_authenticatorData;
index 1f42444..0371623 100644 (file)
@@ -29,6 +29,7 @@
 ] interface MockCredentialsMessenger {
     void setDidTimeOut();
     void setDidUserCancel();
+    void setDidUserVerifyingPlatformAuthenticatorPresent();
     void setAttestationObject(BufferSource attestationObject);
     void setAssertionReturnBundle(BufferSource credentialId, BufferSource authenticatorData, BufferSource signature, BufferSource userHandle);
 };
index c9d6365..ce29785 100644 (file)
@@ -1,3 +1,29 @@
+2018-02-16  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebAuthN] Implement PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
+        https://bugs.webkit.org/show_bug.cgi?id=182771
+        <rdar://problem/36459988>
+
+        Reviewed by Brent Fulgham.
+
+        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:
+
 2018-02-16  Per Arne Vollan  <pvollan@apple.com>
 
         Implement stopping of run loop in the WebContent process when using NSRunLoop.
index d6bdc1b..47d5d7c 100644 (file)
@@ -50,10 +50,20 @@ void WebCredentialsMessengerProxy::makeCredential(uint64_t)
 {
 }
 
+void WebCredentialsMessengerProxy::isUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId)
+{
+    platformIsUserVerifyingPlatformAuthenticatorAvailable(messageId);
+}
+
 void WebCredentialsMessengerProxy::getAssertion(uint64_t)
 {
 }
 
+void WebCredentialsMessengerProxy::isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool result)
+{
+    m_webPageProxy.send(Messages::WebCredentialsMessenger::IsUserVerifyingPlatformAuthenticatorAvailableReply(messageId, result));
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(WEB_AUTHN)
index eaffa81..a266a3e 100644 (file)
@@ -45,6 +45,15 @@ private:
     // Receivers.
     void makeCredential(uint64_t messageId);
     void getAssertion(uint64_t messageId);
+    void isUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId);
+
+    // Senders.
+    void isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool);
+
+    // Platform specific procedures.
+    // FIXME(182768): Might change to some forms of delegates later on.
+    // FIXME(182769): Figure out a way to auto-test the followings.
+    void platformIsUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId);
 
     WebPageProxy& m_webPageProxy;
 };
index fee59ff..6bc0e99 100644 (file)
@@ -28,6 +28,7 @@ messages -> WebCredentialsMessengerProxy {
 
     MakeCredential(uint64_t messageId);
     GetAssertion(uint64_t messageId);
+    IsUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId);
 }
 
 #endif
diff --git a/Source/WebKit/UIProcess/CredentialManagement/cocoa/WebCredentialsMessengerProxyCocoa.mm b/Source/WebKit/UIProcess/CredentialManagement/cocoa/WebCredentialsMessengerProxyCocoa.mm
new file mode 100644 (file)
index 0000000..216146a
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "WebCredentialsMessengerProxy.h"
+
+#if ENABLE(WEB_AUTHN)
+
+#import <LocalAuthentication/LocalAuthentication.h>
+#import <WebCore/NotImplemented.h>
+#import <wtf/RetainPtr.h>
+
+namespace WebKit {
+
+void WebCredentialsMessengerProxy::platformIsUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId)
+{
+#if defined(__i386__)
+    ASSERT_UNUSED(messageId, messageId);
+    notImplemented();
+#else
+    auto context = adoptNS([[LAContext alloc] init]);
+    NSError *error = nil;
+
+    if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error])
+        isUserVerifyingPlatformAuthenticatorAvailableReply(messageId, true);
+    else {
+        LOG_ERROR("Couldn't evaluate authentication with biometrics policy: %@", error);
+        isUserVerifyingPlatformAuthenticatorAvailableReply(messageId, false);
+    }
+#endif // defined(__i386__)
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(WEB_AUTHN)
index edf4a09..65a6832 100644 (file)
                53BA47D01DC2EF5E004DF4AD /* NetworkDataTaskBlob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 539EB5461DC2EE40009D48CF /* NetworkDataTaskBlob.cpp */; };
                53BA47D11DC2EF5E004DF4AD /* NetworkDataTaskBlob.h in Headers */ = {isa = PBXBuildFile; fileRef = 539EB5471DC2EE40009D48CF /* NetworkDataTaskBlob.h */; };
                53DEA3661DDE423100E82648 /* json.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 53DEA3651DDE422E00E82648 /* json.hpp */; };
+               5750F32B2032D4E500389347 /* LocalAuthentication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5750F32A2032D4E500389347 /* LocalAuthentication.framework */; };
                5760828E2029895E00116678 /* WebCredentialsMessenger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5760828C2029854200116678 /* WebCredentialsMessenger.cpp */; };
                57608298202BD8BA00116678 /* WebCredentialsMessengerProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57608296202BD8BA00116678 /* WebCredentialsMessengerProxy.cpp */; };
                5760829C202D2C3C00116678 /* WebCredentialsMessengerMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5760829020298FBD00116678 /* WebCredentialsMessengerMessageReceiver.cpp */; };
                5760829D202D2C4000116678 /* WebCredentialsMessengerMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 5760828F20298FBD00116678 /* WebCredentialsMessengerMessages.h */; };
                5760829E202D2C4300116678 /* WebCredentialsMessengerProxyMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5760829A202BEE5A00116678 /* WebCredentialsMessengerProxyMessageReceiver.cpp */; };
                5760829F202D2C4600116678 /* WebCredentialsMessengerProxyMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 5760829B202BEE5A00116678 /* WebCredentialsMessengerProxyMessages.h */; };
+               57B90AAD203637F4000E61FA /* WebCredentialsMessengerProxyCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57B90AAC203637F4000E61FA /* WebCredentialsMessengerProxyCocoa.mm */; };
                5C0B17781E7C880E00E9123C /* NetworkSocketStreamMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C0B17741E7C879C00E9123C /* NetworkSocketStreamMessageReceiver.cpp */; };
                5C0B17791E7C882100E9123C /* WebSocketStreamMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C0B17761E7C879C00E9123C /* WebSocketStreamMessageReceiver.cpp */; };
                5C0B177C1E7C885400E9123C /* WebSocketStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C0B177A1E7C884F00E9123C /* WebSocketStream.cpp */; };
                539EB5461DC2EE40009D48CF /* NetworkDataTaskBlob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetworkDataTaskBlob.cpp; path = NetworkProcess/NetworkDataTaskBlob.cpp; sourceTree = "<group>"; };
                539EB5471DC2EE40009D48CF /* NetworkDataTaskBlob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkDataTaskBlob.h; path = NetworkProcess/NetworkDataTaskBlob.h; sourceTree = "<group>"; };
                53DEA3651DDE422E00E82648 /* json.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = json.hpp; path = NetworkProcess/capture/json.hpp; sourceTree = "<group>"; };
+               5750F32A2032D4E500389347 /* LocalAuthentication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LocalAuthentication.framework; path = System/Library/Frameworks/LocalAuthentication.framework; sourceTree = SDKROOT; };
                5760828B2029854200116678 /* WebCredentialsMessenger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebCredentialsMessenger.h; sourceTree = "<group>"; };
                5760828C2029854200116678 /* WebCredentialsMessenger.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebCredentialsMessenger.cpp; sourceTree = "<group>"; };
                5760828D202987E600116678 /* WebCredentialsMessenger.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = WebCredentialsMessenger.messages.in; sourceTree = "<group>"; };
                57608299202BDAE200116678 /* WebCredentialsMessengerProxy.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = WebCredentialsMessengerProxy.messages.in; sourceTree = "<group>"; };
                5760829A202BEE5A00116678 /* WebCredentialsMessengerProxyMessageReceiver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebCredentialsMessengerProxyMessageReceiver.cpp; sourceTree = "<group>"; };
                5760829B202BEE5A00116678 /* WebCredentialsMessengerProxyMessages.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebCredentialsMessengerProxyMessages.h; sourceTree = "<group>"; };
+               57B90AAC203637F4000E61FA /* WebCredentialsMessengerProxyCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCredentialsMessengerProxyCocoa.mm; sourceTree = "<group>"; };
                5C0B17741E7C879C00E9123C /* NetworkSocketStreamMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkSocketStreamMessageReceiver.cpp; sourceTree = "<group>"; };
                5C0B17751E7C879C00E9123C /* NetworkSocketStreamMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkSocketStreamMessages.h; sourceTree = "<group>"; };
                5C0B17761E7C879C00E9123C /* WebSocketStreamMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocketStreamMessageReceiver.cpp; sourceTree = "<group>"; };
                        files = (
                                3766F9EE189A1241003CF19B /* JavaScriptCore.framework in Frameworks */,
                                3766F9F1189A1254003CF19B /* libicucore.dylib in Frameworks */,
+                               5750F32B2032D4E500389347 /* LocalAuthentication.framework in Frameworks */,
                                3766F9EF189A1244003CF19B /* QuartzCore.framework in Frameworks */,
                                37694525184FC6B600CDE21F /* Security.framework in Frameworks */,
                                37BEC4DD1948FC6A008B4286 /* WebCore.framework in Frameworks */,
                                1A4F9769100E7B6600637A18 /* Configurations */,
                                0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
                                034768DFFF38A50411DB9C8B /* Products */,
+                               5750F3292032D4E300389347 /* Frameworks */,
                        );
                        name = WebKit2;
                        sourceTree = "<group>";
                        name = capture;
                        sourceTree = "<group>";
                };
+               5750F3292032D4E300389347 /* Frameworks */ = {
+                       isa = PBXGroup;
+                       children = (
+                               5750F32A2032D4E500389347 /* LocalAuthentication.framework */,
+                       );
+                       name = Frameworks;
+                       sourceTree = "<group>";
+               };
                5760828A202984C900116678 /* CredentialManagement */ = {
                        isa = PBXGroup;
                        children = (
                57608294202BD84900116678 /* CredentialManagement */ = {
                        isa = PBXGroup;
                        children = (
+                               57B90AAB20363758000E61FA /* cocoa */,
                                57608296202BD8BA00116678 /* WebCredentialsMessengerProxy.cpp */,
                                57608295202BD8BA00116678 /* WebCredentialsMessengerProxy.h */,
                                57608299202BDAE200116678 /* WebCredentialsMessengerProxy.messages.in */,
                        path = CredentialManagement;
                        sourceTree = "<group>";
                };
+               57B90AAB20363758000E61FA /* cocoa */ = {
+                       isa = PBXGroup;
+                       children = (
+                               57B90AAC203637F4000E61FA /* WebCredentialsMessengerProxyCocoa.mm */,
+                       );
+                       path = cocoa;
+                       sourceTree = "<group>";
+               };
                5C1426F11C23F81700D41183 /* Downloads */ = {
                        isa = PBXGroup;
                        children = (
                                5760828E2029895E00116678 /* WebCredentialsMessenger.cpp in Sources */,
                                5760829C202D2C3C00116678 /* WebCredentialsMessengerMessageReceiver.cpp in Sources */,
                                57608298202BD8BA00116678 /* WebCredentialsMessengerProxy.cpp in Sources */,
+                               57B90AAD203637F4000E61FA /* WebCredentialsMessengerProxyCocoa.mm in Sources */,
                                5760829E202D2C4300116678 /* WebCredentialsMessengerProxyMessageReceiver.cpp in Sources */,
                                1AA83F6C1A5B63FF00026EC6 /* WebDatabaseProvider.cpp in Sources */,
                                CD19A26D1A13E82A008D650E /* WebDiagnosticLoggingClient.cpp in Sources */,
index 3938f7e..d115aff 100644 (file)
@@ -54,6 +54,12 @@ void WebCredentialsMessenger::getAssertion(const Vector<uint8_t>&, const WebCore
 {
 }
 
+void WebCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailable(WebCore::QueryCompletionHandler&& handler)
+{
+    auto messageId = addQueryCompletionHandler(WTFMove(handler));
+    m_webPage.send(Messages::WebCredentialsMessengerProxy::IsUserVerifyingPlatformAuthenticatorAvailable(messageId));
+}
+
 void WebCredentialsMessenger::makeCredentialReply(uint64_t messageId, const Vector<uint8_t>&)
 {
 }
@@ -62,6 +68,13 @@ void WebCredentialsMessenger::getAssertionReply(uint64_t messageId, const Vector
 {
 }
 
+void WebCredentialsMessenger::isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool result)
+{
+    auto handler = takeQueryCompletionHandler(messageId);
+    handler(result);
+}
+
+
 } // namespace WebKit
 
 #endif // ENABLE(WEB_AUTHN)
index 4d5f6bd..6de0b0e 100644 (file)
@@ -44,10 +44,12 @@ private:
     // sender
     void makeCredential(const Vector<uint8_t>&, const WebCore::PublicKeyCredentialCreationOptions&, WebCore::CreationCompletionHandler&&) final;
     void getAssertion(const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialRequestOptions&, WebCore::RequestCompletionHandler&&) final;
+    void isUserVerifyingPlatformAuthenticatorAvailable(WebCore::QueryCompletionHandler&&) final;
 
     // receiver
     void makeCredentialReply(uint64_t messageId, const Vector<uint8_t>&) final;
     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;
+    void isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool) final;
 
     // IPC::MessageReceiver.
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
index 3a2c85d..3ab1116 100644 (file)
@@ -29,6 +29,8 @@ messages -> WebCredentialsMessenger {
     ExceptionReply(uint64_t messageId, struct WebCore::ExceptionData exception);
     MakeCredentialReply(uint64_t messageId, Vector<uint8_t> attestationObject);
     GetAssertionReply(uint64_t messageId, Vector<uint8_t> credentialId, Vector<uint8_t> authenticatorData, Vector<uint8_t> signature, Vector<uint8_t> userHandle);
+    IsUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool result);
+exceptionReply(uint64_t messageId, struct WebCore::ExceptionData exception);
 }
 
 #endif