Title: [228572] trunk
Revision
228572
Author
[email protected]
Date
2018-02-16 12:43:28 -0800 (Fri, 16 Feb 2018)

Log 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.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (228571 => 228572)


--- trunk/LayoutTests/ChangeLog	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/LayoutTests/ChangeLog	2018-02-16 20:43:28 UTC (rev 228572)
@@ -1,3 +1,14 @@
+2018-02-16  Jiewen Tan  <[email protected]>
+
+        [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  <[email protected]>
 
         fast/frames/sandboxed-iframe-navigation-top-denied.html is crashing in Inspector::createScriptCallStackForConsole::Exec for GTK

Added: trunk/LayoutTests/http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available-expected.txt (0 => 228572)


--- trunk/LayoutTests/http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available-expected.txt	2018-02-16 20:43:28 UTC (rev 228572)
@@ -0,0 +1,4 @@
+
+PASS PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() without any available authenticators. 
+PASS PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() with available authenticators. 
+

Added: trunk/LayoutTests/http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available.html (0 => 228572)


--- trunk/LayoutTests/http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-is-user-verifying-platform-authenticator-available.html	2018-02-16 20:43:28 UTC (rev 228572)
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>Web Authentication API: PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().</title>
+<script src=""
+<script src=""
+<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>

Modified: trunk/Source/WebCore/ChangeLog (228571 => 228572)


--- trunk/Source/WebCore/ChangeLog	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebCore/ChangeLog	2018-02-16 20:43:28 UTC (rev 228572)
@@ -1,3 +1,49 @@
+2018-02-16  Jiewen Tan  <[email protected]>
+
+        [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  <[email protected]>
 
         Stop using EXCLUDED_SOURCE_FILE_NAMES for touch and gesture files in WebCore

Modified: trunk/Source/WebCore/Modules/credentialmanagement/CredentialsContainer.cpp (228571 => 228572)


--- trunk/Source/WebCore/Modules/credentialmanagement/CredentialsContainer.cpp	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebCore/Modules/credentialmanagement/CredentialsContainer.cpp	2018-02-16 20:43:28 UTC (rev 228572)
@@ -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 @@
     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 @@
     // 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 @@
     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 @@
 
     // 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 @@
     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

Modified: trunk/Source/WebCore/Modules/credentialmanagement/CredentialsContainer.h (228571 => 228572)


--- trunk/Source/WebCore/Modules/credentialmanagement/CredentialsContainer.h	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebCore/Modules/credentialmanagement/CredentialsContainer.h	2018-02-16 20:43:28 UTC (rev 228572)
@@ -28,13 +28,12 @@
 
 #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 @@
 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>&&);

Modified: trunk/Source/WebCore/Modules/credentialmanagement/CredentialsMessenger.cpp (228571 => 228572)


--- trunk/Source/WebCore/Modules/credentialmanagement/CredentialsMessenger.cpp	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebCore/Modules/credentialmanagement/CredentialsMessenger.cpp	2018-02-16 20:43:28 UTC (rev 228572)
@@ -68,7 +68,6 @@
     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 @@
     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 @@
     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;

Modified: trunk/Source/WebCore/Modules/credentialmanagement/CredentialsMessenger.h (228571 => 228572)


--- trunk/Source/WebCore/Modules/credentialmanagement/CredentialsMessenger.h	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebCore/Modules/credentialmanagement/CredentialsMessenger.h	2018-02-16 20:43:28 UTC (rev 228572)
@@ -68,6 +68,7 @@
 
 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 @@
     // 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 @@
     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 @@
     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

Modified: trunk/Source/WebCore/Modules/webauthn/AuthenticatorManager.cpp (228571 => 228572)


--- trunk/Source/WebCore/Modules/webauthn/AuthenticatorManager.cpp	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebCore/Modules/webauthn/AuthenticatorManager.cpp	2018-02-16 20:43:28 UTC (rev 228572)
@@ -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 @@
 }
 
 // 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 @@
     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 @@
     // 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 @@
     // 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 @@
     // 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 @@
     // 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 @@
         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 @@
     // 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 @@
     // 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 @@
     // 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 @@
         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)

Modified: trunk/Source/WebCore/Modules/webauthn/AuthenticatorManager.h (228571 => 228572)


--- trunk/Source/WebCore/Modules/webauthn/AuthenticatorManager.h	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebCore/Modules/webauthn/AuthenticatorManager.h	2018-02-16 20:43:28 UTC (rev 228572)
@@ -27,6 +27,7 @@
 
 #if ENABLE(WEB_AUTHN)
 
+#include "JSDOMPromiseDeferred.h"
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/WeakPtr.h>
@@ -34,13 +35,15 @@
 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 @@
     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;

Modified: trunk/Source/WebCore/Modules/webauthn/PublicKeyCredential.cpp (228571 => 228572)


--- trunk/Source/WebCore/Modules/webauthn/PublicKeyCredential.cpp	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebCore/Modules/webauthn/PublicKeyCredential.cpp	2018-02-16 20:43:28 UTC (rev 228572)
@@ -28,6 +28,7 @@
 
 #if ENABLE(WEB_AUTHN)
 
+#include "AuthenticatorManager.h"
 #include "JSDOMPromiseDeferred.h"
 #include <wtf/text/Base64.h>
 
@@ -45,9 +46,9 @@
     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

Modified: trunk/Source/WebCore/Modules/webauthn/PublicKeyCredential.h (228571 => 228572)


--- trunk/Source/WebCore/Modules/webauthn/PublicKeyCredential.h	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebCore/Modules/webauthn/PublicKeyCredential.h	2018-02-16 20:43:28 UTC (rev 228572)
@@ -29,6 +29,7 @@
 
 #include "BasicCredential.h"
 #include "ExceptionOr.h"
+#include "JSDOMPromiseDeferred.h"
 #include <_javascript_Core/ArrayBuffer.h>
 #include <wtf/Forward.h>
 
@@ -35,7 +36,6 @@
 namespace WebCore {
 
 class AuthenticatorResponse;
-class DeferredPromise;
 
 class PublicKeyCredential final : public BasicCredential {
 public:
@@ -49,7 +49,7 @@
     // 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>&&);

Modified: trunk/Source/WebCore/testing/MockCredentialsMessenger.cpp (228571 => 228572)


--- trunk/Source/WebCore/testing/MockCredentialsMessenger.cpp	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebCore/testing/MockCredentialsMessenger.cpp	2018-02-16 20:43:28 UTC (rev 228572)
@@ -117,6 +117,16 @@
     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 @@
     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)

Modified: trunk/Source/WebCore/testing/MockCredentialsMessenger.h (228571 => 228572)


--- trunk/Source/WebCore/testing/MockCredentialsMessenger.h	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebCore/testing/MockCredentialsMessenger.h	2018-02-16 20:43:28 UTC (rev 228572)
@@ -42,6 +42,7 @@
 
     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 @@
 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;

Modified: trunk/Source/WebCore/testing/MockCredentialsMessenger.idl (228571 => 228572)


--- trunk/Source/WebCore/testing/MockCredentialsMessenger.idl	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebCore/testing/MockCredentialsMessenger.idl	2018-02-16 20:43:28 UTC (rev 228572)
@@ -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);
 };

Modified: trunk/Source/WebKit/ChangeLog (228571 => 228572)


--- trunk/Source/WebKit/ChangeLog	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebKit/ChangeLog	2018-02-16 20:43:28 UTC (rev 228572)
@@ -1,3 +1,29 @@
+2018-02-16  Jiewen Tan  <[email protected]>
+
+        [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  <[email protected]>
 
         Implement stopping of run loop in the WebContent process when using NSRunLoop.

Modified: trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.cpp (228571 => 228572)


--- trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.cpp	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.cpp	2018-02-16 20:43:28 UTC (rev 228572)
@@ -50,10 +50,20 @@
 {
 }
 
+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)

Modified: trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.h (228571 => 228572)


--- trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.h	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.h	2018-02-16 20:43:28 UTC (rev 228572)
@@ -45,7 +45,16 @@
     // 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;
 };
 

Modified: trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.messages.in (228571 => 228572)


--- trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.messages.in	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.messages.in	2018-02-16 20:43:28 UTC (rev 228572)
@@ -28,6 +28,7 @@
 
     MakeCredential(uint64_t messageId);
     GetAssertion(uint64_t messageId);
+    IsUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId);
 }
 
 #endif

Copied: trunk/Source/WebKit/UIProcess/CredentialManagement/cocoa/WebCredentialsMessengerProxyCocoa.mm (from rev 228571, trunk/Source/WebKit/UIProcess/CredentialManagement/WebCredentialsMessengerProxy.cpp) (0 => 228572)


--- trunk/Source/WebKit/UIProcess/CredentialManagement/cocoa/WebCredentialsMessengerProxyCocoa.mm	                        (rev 0)
+++ trunk/Source/WebKit/UIProcess/CredentialManagement/cocoa/WebCredentialsMessengerProxyCocoa.mm	2018-02-16 20:43:28 UTC (rev 228572)
@@ -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)

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (228571 => 228572)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2018-02-16 20:43:28 UTC (rev 228572)
@@ -1211,6 +1211,7 @@
 		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 */; };
@@ -1217,6 +1218,7 @@
 		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 */; };
@@ -3640,6 +3642,7 @@
 		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>"; };
@@ -3650,6 +3653,7 @@
 		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>"; };
@@ -4722,6 +4726,7 @@
 			files = (
 				3766F9EE189A1241003CF19B /* _javascript_Core.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 */,
@@ -4814,6 +4819,7 @@
 				1A4F9769100E7B6600637A18 /* Configurations */,
 				0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
 				034768DFFF38A50411DB9C8B /* Products */,
+				5750F3292032D4E300389347 /* Frameworks */,
 			);
 			name = WebKit2;
 			sourceTree = "<group>";
@@ -6702,6 +6708,14 @@
 			name = capture;
 			sourceTree = "<group>";
 		};
+		5750F3292032D4E300389347 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				5750F32A2032D4E500389347 /* LocalAuthentication.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
 		5760828A202984C900116678 /* CredentialManagement */ = {
 			isa = PBXGroup;
 			children = (
@@ -6715,6 +6729,7 @@
 		57608294202BD84900116678 /* CredentialManagement */ = {
 			isa = PBXGroup;
 			children = (
+				57B90AAB20363758000E61FA /* cocoa */,
 				57608296202BD8BA00116678 /* WebCredentialsMessengerProxy.cpp */,
 				57608295202BD8BA00116678 /* WebCredentialsMessengerProxy.h */,
 				57608299202BDAE200116678 /* WebCredentialsMessengerProxy.messages.in */,
@@ -6722,6 +6737,14 @@
 			path = CredentialManagement;
 			sourceTree = "<group>";
 		};
+		57B90AAB20363758000E61FA /* cocoa */ = {
+			isa = PBXGroup;
+			children = (
+				57B90AAC203637F4000E61FA /* WebCredentialsMessengerProxyCocoa.mm */,
+			);
+			path = cocoa;
+			sourceTree = "<group>";
+		};
 		5C1426F11C23F81700D41183 /* Downloads */ = {
 			isa = PBXGroup;
 			children = (
@@ -10855,6 +10878,7 @@
 				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 */,

Modified: trunk/Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.cpp (228571 => 228572)


--- trunk/Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.cpp	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.cpp	2018-02-16 20:43:28 UTC (rev 228572)
@@ -54,6 +54,12 @@
 {
 }
 
+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::isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool result)
+{
+    auto handler = takeQueryCompletionHandler(messageId);
+    handler(result);
+}
+
+
 } // namespace WebKit
 
 #endif // ENABLE(WEB_AUTHN)

Modified: trunk/Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.h (228571 => 228572)


--- trunk/Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.h	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.h	2018-02-16 20:43:28 UTC (rev 228572)
@@ -44,10 +44,12 @@
     // 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;

Modified: trunk/Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.messages.in (228571 => 228572)


--- trunk/Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.messages.in	2018-02-16 19:53:19 UTC (rev 228571)
+++ trunk/Source/WebKit/WebProcess/CredentialManagement/WebCredentialsMessenger.messages.in	2018-02-16 20:43:28 UTC (rev 228572)
@@ -29,6 +29,8 @@
     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
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to