⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 245043 in webkit


Ignore:
Timestamp:
May 7, 2019, 4:43:18 PM (7 years ago)
Author:
jiewen_tan@apple.com
Message:

[WebAuthN] A new request should always suppress the pending request if any
https://bugs.webkit.org/show_bug.cgi?id=191517
<rdar://problem/46888222>

Reviewed by Brent Fulgham.

Source/WebCore:

Blocking new requests from the same page when there is a pending request could DoS the
WebAuthN API in the period between [the page is refreshed, the pending request is
hanedled/timeout]. Therefore, the policy will be to always cancel any pending requests
whenever a new request is made. This will enforce the policy of handling only one
request at a time.

Covered by new tests in existing files.

  • Modules/webauthn/AuthenticatorCoordinatorClient.cpp:

(WebCore::AuthenticatorCoordinatorClient::requestReply):
(WebCore::AuthenticatorCoordinatorClient::setRequestCompletionHandler):
(WebCore::AuthenticatorCoordinatorClient::addQueryCompletionHandler):

  • Modules/webauthn/AuthenticatorCoordinatorClient.h:

Source/WebKit:

Previously we blocked new WebAuthN requests whenever a pending request was in progress
to prevent background tabs from DoS foreground tabs. However, in r244938, the WebAuthN
API was changed to restrict request handling to the focused document. Therefore, we no
longer have a risk of DoS.

Apart from the vanished benefit, this behavoir actually blocks new pages to use
WebAuthN API in the period between [the previous initating page is closed, the pending
request is hanedled/timeout].

Also, it makes sense to have the current focused document preempt the pending request.
Therefore, the policy will be to always cancel any pending requests whenever a new
request is made. This will enforce the policy of handling only one request at a time.

Note that the current implementation doesn't explicitly cancel pending requests in the
Authenticators, which means that we could receive responses from the Authenticator that
were meant for a previous (now cancelled) request. A follow-up patch (see Bug 191523)
will implement an Authenticator feature to support immediate cancellation.

In the meantime, to protect the atomicity of the request/response pair, i.e., preventing an old
response being used for a new request, there are two safeguards:
1) In web process, each request to UI process is paired with an incremental ID, and therefore an old
response from UI process would have a different ID than the current request, which will then be ignored.
2) In UI process, all responses from authenticators will be piped to the main run loop for processing.
Therefore, when the new request comes in, the old response is either processed or waiting in the pipe.
To prevent the latter being processed, the new request will immediately destroy any authenticators bound
to the old response in the current run loop. Hence, in the next run loop when dealing the old response,
the lambda will have no where to hand the response over.

  • UIProcess/WebAuthentication/AuthenticatorManager.cpp:

(WebKit::AuthenticatorManager::makeCredential):
(WebKit::AuthenticatorManager::getAssertion):
(WebKit::AuthenticatorManager::clearStateAsync):
(WebKit::AuthenticatorManager::clearState):
(WebKit::AuthenticatorManager::timeOutTimerFired):

  • UIProcess/WebAuthentication/AuthenticatorManager.h:
  • UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp:

(WebKit::WebAuthenticatorCoordinatorProxy::makeCredential):
(WebKit::WebAuthenticatorCoordinatorProxy::getAssertion):
(WebKit::WebAuthenticatorCoordinatorProxy::requestReply):

  • UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.h:
  • UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.messages.in:
  • WebProcess/WebAuthentication/WebAuthenticatorCoordinator.cpp:

(WebKit::WebAuthenticatorCoordinator::makeCredential):
(WebKit::WebAuthenticatorCoordinator::getAssertion):

  • WebProcess/WebAuthentication/WebAuthenticatorCoordinator.messages.in:

LayoutTests:

  • http/wpt/webauthn/public-key-credential-create-failure.https-expected.txt:
  • http/wpt/webauthn/public-key-credential-create-failure.https.html:
  • http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt:
  • http/wpt/webauthn/public-key-credential-create-success-hid.https.html:
  • http/wpt/webauthn/public-key-credential-get-failure.https-expected.txt:
  • http/wpt/webauthn/public-key-credential-get-failure.https.html:
  • http/wpt/webauthn/public-key-credential-get-success-hid.https-expected.txt:
  • http/wpt/webauthn/public-key-credential-get-success-hid.https.html:
  • http/wpt/webauthn/resources/new-page.html: Added.
Location:
trunk
Files:
1 added
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r245033 r245043  
     12019-05-07  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthN] A new request should always suppress the pending request if any
     4        https://bugs.webkit.org/show_bug.cgi?id=191517
     5        <rdar://problem/46888222>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        * http/wpt/webauthn/public-key-credential-create-failure.https-expected.txt:
     10        * http/wpt/webauthn/public-key-credential-create-failure.https.html:
     11        * http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt:
     12        * http/wpt/webauthn/public-key-credential-create-success-hid.https.html:
     13        * http/wpt/webauthn/public-key-credential-get-failure.https-expected.txt:
     14        * http/wpt/webauthn/public-key-credential-get-failure.https.html:
     15        * http/wpt/webauthn/public-key-credential-get-success-hid.https-expected.txt:
     16        * http/wpt/webauthn/public-key-credential-get-success-hid.https.html:
     17        * http/wpt/webauthn/resources/new-page.html: Added.
     18
    1192019-05-07  Youenn Fablet  <youenn@apple.com>
    220
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure.https-expected.txt

    r236842 r245043  
    33PASS PublicKeyCredential's [[create]] with a mismatched RP ID
    44PASS PublicKeyCredential's [[create]] with an empty pubKeyCredParams
     5PASS PublicKeyCredential's [[create]] with two consecutive requests
     6PASS PublicKeyCredential's [[create]] with two consecutive requests (2)
     7PASS PublicKeyCredential's [[create]] with new requests in a new page
     8PASS PublicKeyCredential's [[create]] with new requests in a new page (2)
    59
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure.https.html

    r244863 r245043  
    7171            navigator.credentials.create(options), "No desired properties of the to be created credential are provided.");
    7272    }, "PublicKeyCredential's [[create]] with an empty pubKeyCredParams");
     73
     74    promise_test(function(t) {
     75        const options = {
     76            publicKey: {
     77                rp: {
     78                    name: "example.com"
     79                },
     80                user: {
     81                    name: "John Appleseed",
     82                    id: asciiToUint8Array("123456"),
     83                    displayName: "John",
     84                },
     85                challenge: asciiToUint8Array("123456"),
     86                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
     87            }
     88        };
     89
     90        const result = promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "This request has been voided by a new request.");
     91        promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "This request has been voided by a new request.");
     92        return result;
     93    }, "PublicKeyCredential's [[create]] with two consecutive requests");
     94
     95    promise_test(function(t) {
     96        const creationOptions = {
     97            publicKey: {
     98                rp: {
     99                    name: "example.com"
     100                },
     101                user: {
     102                    name: "John Appleseed",
     103                    id: asciiToUint8Array("123456"),
     104                    displayName: "John",
     105                },
     106                challenge: asciiToUint8Array("123456"),
     107                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
     108            }
     109        };
     110        const result = promiseRejects(t, "NotAllowedError", navigator.credentials.create(creationOptions), "This request has been voided by a new request.");
     111
     112        const requestOptions = {
     113            publicKey: {
     114                challenge: asciiToUint8Array("123456")
     115            }
     116        };
     117        promiseRejects(t, "NotAllowedError", navigator.credentials.get(requestOptions), "This request has been voided by a new request.");
     118        return result;
     119    }, "PublicKeyCredential's [[create]] with two consecutive requests (2)");
     120
     121    promise_test(function(t) {
     122        const options = {
     123            publicKey: {
     124                rp: {
     125                    name: "example.com"
     126                },
     127                user: {
     128                    name: "John Appleseed",
     129                    id: asciiToUint8Array("123456"),
     130                    displayName: "John",
     131                },
     132                challenge: asciiToUint8Array("123456"),
     133                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
     134            }
     135        };
     136
     137        const result = promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "This request has been cancelled by a new request.");
     138        window.open("./resources/new-page.html?isCreation=true");
     139        return result;
     140    }, "PublicKeyCredential's [[create]] with new requests in a new page");
     141
     142    promise_test(function(t) {
     143        const options = {
     144            publicKey: {
     145                rp: {
     146                    name: "example.com"
     147                },
     148                user: {
     149                    name: "John Appleseed",
     150                    id: asciiToUint8Array("123456"),
     151                    displayName: "John",
     152                },
     153                challenge: asciiToUint8Array("123456"),
     154                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
     155            }
     156        };
     157
     158        const result = promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "This request has been cancelled by a new request.");
     159        window.open("./resources/new-page.html?isCreation=false");
     160        return result;
     161    }, "PublicKeyCredential's [[create]] with new requests in a new page (2)");
    73162</script>
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt

    r238166 r245043  
    66PASS PublicKeyCredential's [[create]] with userVerification { 'discouraged' } in a mock local authenticator.
    77PASS PublicKeyCredential's [[create]] with mixed options in a mock local authenticator.
     8PASS PublicKeyCredential's [[create]] with two consecutive requests.
    89
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html

    r243193 r245043  
    171171        });
    172172    }, "PublicKeyCredential's [[create]] with mixed options in a mock local authenticator.");
     173
     174    promise_test(t => {
     175        const options = {
     176            publicKey: {
     177                rp: {
     178                    name: "localhost",
     179                },
     180                user: {
     181                    name: "John Appleseed",
     182                    id: Base64URL.parse(testUserhandleBase64),
     183                    displayName: "Appleseed",
     184                },
     185                challenge: Base64URL.parse("MTIzNDU2"),
     186                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
     187                timeout: 100
     188            }
     189        };
     190
     191        promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "This request is suppressed by a new request.");
     192        return navigator.credentials.create(options).then(credential => {
     193            checkResult(credential);
     194        });
     195    }, "PublicKeyCredential's [[create]] with two consecutive requests.");
    173196</script>
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure.https-expected.txt

    r243193 r245043  
    66PASS PublicKeyCredential's [[get]] with a mismatched APP ID (different sites 1)
    77PASS PublicKeyCredential's [[get]] with a mismatched APP ID (different sites 2)
     8PASS PublicKeyCredential's [[get]] with two consecutive requests
     9PASS PublicKeyCredential's [[get]] with two consecutive requests (2)
     10PASS PublicKeyCredential's [[get]] with new requests in a new page
     11PASS PublicKeyCredential's [[get]] with new requests in a new page (2)
    812
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure.https.html

    r244863 r245043  
    8080            navigator.credentials.get(options), "The origin of the document is not authorized for the provided App ID.");
    8181    }, "PublicKeyCredential's [[get]] with a mismatched APP ID (different sites 2)");
     82
     83    promise_test(t => {
     84        const options = {
     85            publicKey: {
     86                challenge: asciiToUint8Array("123456")
     87            }
     88        };
     89
     90        const result = promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "This request has been voided by a new request.");
     91        promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "This request has been voided by a new request.");
     92        return result;
     93    }, "PublicKeyCredential's [[get]] with two consecutive requests");
     94
     95    promise_test(function(t) {
     96        const requestOptions = {
     97            publicKey: {
     98                challenge: asciiToUint8Array("123456")
     99            }
     100        };
     101        const result = promiseRejects(t, "NotAllowedError", navigator.credentials.get(requestOptions), "This request has been voided by a new request.");
     102
     103        const creationOptions = {
     104            publicKey: {
     105                rp: {
     106                    name: "example.com"
     107                },
     108                user: {
     109                    name: "John Appleseed",
     110                    id: asciiToUint8Array("123456"),
     111                    displayName: "John",
     112                },
     113                challenge: asciiToUint8Array("123456"),
     114                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
     115            }
     116        };
     117        promiseRejects(t, "NotAllowedError", navigator.credentials.create(creationOptions), "This request has been voided by a new request.");
     118
     119        return result;
     120    }, "PublicKeyCredential's [[get]] with two consecutive requests (2)");
     121
     122    promise_test(t => {
     123        const options = {
     124            publicKey: {
     125                challenge: asciiToUint8Array("123456")
     126            }
     127        };
     128
     129        const result = promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "This request has been cancelled by a new request.");
     130        window.open("./resources/new-page.html?isCreation=false");
     131        return result;
     132    }, "PublicKeyCredential's [[get]] with new requests in a new page");
     133
     134    promise_test(t => {
     135        const options = {
     136            publicKey: {
     137                challenge: asciiToUint8Array("123456")
     138            }
     139        };
     140
     141        const result = promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "This request has been cancelled by a new request.");
     142        window.open("./resources/new-page.html?isCreation=true");
     143        return result;
     144    }, "PublicKeyCredential's [[get]] with new requests in a new page (2)");
    82145</script>
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https-expected.txt

    r238166 r245043  
    55PASS PublicKeyCredential's [[get]] with userVerification { discouraged } in a mock hid authenticator.
    66PASS PublicKeyCredential's [[get]] with mixed options in a mock hid authenticator.
     7PASS PublicKeyCredential's [[get]] with two consecutive requests.
    78
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https.html

    r243193 r245043  
    9999        });
    100100    }, "PublicKeyCredential's [[get]] with mixed options in a mock hid authenticator.");
     101
     102    promise_test(t => {
     103        const options = {
     104            publicKey: {
     105                challenge: Base64URL.parse("MTIzNDU2"),
     106                timeout: 100
     107            }
     108        };
     109
     110        promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "This request is suppressed by a new request.");
     111        return navigator.credentials.get(options).then(credential => {
     112            return checkResult(credential);
     113        });
     114    }, "PublicKeyCredential's [[get]] with two consecutive requests.");
    101115</script>
  • trunk/Source/WebCore/ChangeLog

    r245039 r245043  
     12019-05-07  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthN] A new request should always suppress the pending request if any
     4        https://bugs.webkit.org/show_bug.cgi?id=191517
     5        <rdar://problem/46888222>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        Blocking new requests from the same page when there is a pending request could DoS the
     10        WebAuthN API in the period between [the page is refreshed, the pending request is
     11        hanedled/timeout]. Therefore, the policy will be to always cancel any pending requests
     12        whenever a new request is made. This will enforce the policy of handling only one
     13        request at a time.
     14
     15        Covered by new tests in existing files.
     16
     17        * Modules/webauthn/AuthenticatorCoordinatorClient.cpp:
     18        (WebCore::AuthenticatorCoordinatorClient::requestReply):
     19        (WebCore::AuthenticatorCoordinatorClient::setRequestCompletionHandler):
     20        (WebCore::AuthenticatorCoordinatorClient::addQueryCompletionHandler):
     21        * Modules/webauthn/AuthenticatorCoordinatorClient.h:
     22
    1232019-05-07  Eric Carlson  <eric.carlson@apple.com>
    224
  • trunk/Source/WebCore/Modules/webauthn/AuthenticatorCoordinatorClient.cpp

    r238166 r245043  
    3333namespace WebCore {
    3434
    35 void AuthenticatorCoordinatorClient::requestReply(const WebCore::PublicKeyCredentialData& data, const WebCore::ExceptionData& exception)
     35void AuthenticatorCoordinatorClient::requestReply(uint64_t messageId, const WebCore::PublicKeyCredentialData& data, const WebCore::ExceptionData& exception)
    3636{
     37    if (messageId != m_accumulatedRequestMessageId - 1)
     38        return;
    3739    m_pendingCompletionHandler(data, exception);
    3840}
     
    4446}
    4547
    46 bool AuthenticatorCoordinatorClient::setRequestCompletionHandler(RequestCompletionHandler&& handler)
     48uint64_t AuthenticatorCoordinatorClient::setRequestCompletionHandler(RequestCompletionHandler&& handler)
    4749{
    48     if (m_pendingCompletionHandler) {
    49         handler({ }, { NotAllowedError, "A request is pending."_s });
    50         return false;
    51     }
     50    if (m_pendingCompletionHandler)
     51        m_pendingCompletionHandler({ }, { NotAllowedError, "This request has been voided by a new request."_s });
    5252
    5353    m_pendingCompletionHandler = WTFMove(handler);
    54     return true;
     54    return m_accumulatedRequestMessageId++;
    5555}
    5656
    5757uint64_t AuthenticatorCoordinatorClient::addQueryCompletionHandler(QueryCompletionHandler&& handler)
    5858{
    59     uint64_t messageId = m_accumulatedMessageId++;
     59    uint64_t messageId = m_accumulatedQueryMessageId++;
    6060    auto addResult = m_pendingQueryCompletionHandlers.add(messageId, WTFMove(handler));
    6161    ASSERT_UNUSED(addResult, addResult.isNewEntry);
  • trunk/Source/WebCore/Modules/webauthn/AuthenticatorCoordinatorClient.h

    r238166 r245043  
    5757
    5858    // Receivers.
    59     void requestReply(const WebCore::PublicKeyCredentialData&, const WebCore::ExceptionData&);
     59    void requestReply(uint64_t messageId, const WebCore::PublicKeyCredentialData&, const WebCore::ExceptionData&);
    6060    void isUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool);
    6161
    6262protected:
    63     // Only one request is allowed at one time. It returns false whenever there is an existing pending request.
    64     // And invokes the provided handler with NotAllowedError.
    65     bool setRequestCompletionHandler(RequestCompletionHandler&&);
     63    // Only one request is allowed at one time. A new request will cancel any pending request.
     64    // A message id that is tied to the request wil be generated each time to prevent mismatching responses.
     65    uint64_t setRequestCompletionHandler(RequestCompletionHandler&&);
    6666    uint64_t addQueryCompletionHandler(QueryCompletionHandler&&);
    6767
    6868private:
     69    uint64_t m_accumulatedRequestMessageId { 1 };
    6970    RequestCompletionHandler m_pendingCompletionHandler;
    70     uint64_t m_accumulatedMessageId { 1 };
     71    uint64_t m_accumulatedQueryMessageId { 1 };
    7172    HashMap<uint64_t, QueryCompletionHandler> m_pendingQueryCompletionHandlers;
    7273};
  • trunk/Source/WebKit/ChangeLog

    r245041 r245043  
     12019-05-07  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthN] A new request should always suppress the pending request if any
     4        https://bugs.webkit.org/show_bug.cgi?id=191517
     5        <rdar://problem/46888222>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        Previously we blocked new WebAuthN requests whenever a pending request was in progress
     10        to prevent background tabs from DoS foreground tabs. However, in r244938, the WebAuthN
     11        API was changed to restrict request handling to the focused document. Therefore, we no
     12        longer have a risk of DoS.
     13
     14        Apart from the vanished benefit, this behavoir actually blocks new pages to use
     15        WebAuthN API in the period between [the previous initating page is closed, the pending
     16        request is hanedled/timeout].
     17
     18        Also, it makes sense to have the current focused document preempt the pending request.
     19        Therefore, the policy will be to always cancel any pending requests whenever a new
     20        request is made. This will enforce the policy of handling only one request at a time.
     21
     22        Note that the current implementation doesn't explicitly cancel pending requests in the
     23        Authenticators, which means that we could receive responses from the Authenticator that
     24        were meant for a previous (now cancelled) request. A follow-up patch (see Bug 191523)
     25        will implement an Authenticator feature to support immediate cancellation.
     26
     27        In the meantime, to protect the atomicity of the request/response pair, i.e., preventing an old
     28        response being used for a new request, there are two safeguards:
     29        1) In web process, each request to UI process is paired with an incremental ID, and therefore an old
     30        response from UI process would have a different ID than the current request, which will then be ignored.
     31        2) In UI process, all responses from authenticators will be piped to the main run loop for processing.
     32        Therefore, when the new request comes in, the old response is either processed or waiting in the pipe.
     33        To prevent the latter being processed, the new request will immediately destroy any authenticators bound
     34        to the old response in the current run loop. Hence, in the next run loop when dealing the old response,
     35        the lambda will have no where to hand the response over.
     36
     37        * UIProcess/WebAuthentication/AuthenticatorManager.cpp:
     38        (WebKit::AuthenticatorManager::makeCredential):
     39        (WebKit::AuthenticatorManager::getAssertion):
     40        (WebKit::AuthenticatorManager::clearStateAsync):
     41        (WebKit::AuthenticatorManager::clearState):
     42        (WebKit::AuthenticatorManager::timeOutTimerFired):
     43        * UIProcess/WebAuthentication/AuthenticatorManager.h:
     44        * UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp:
     45        (WebKit::WebAuthenticatorCoordinatorProxy::makeCredential):
     46        (WebKit::WebAuthenticatorCoordinatorProxy::getAssertion):
     47        (WebKit::WebAuthenticatorCoordinatorProxy::requestReply):
     48        * UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.h:
     49        * UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.messages.in:
     50        * WebProcess/WebAuthentication/WebAuthenticatorCoordinator.cpp:
     51        (WebKit::WebAuthenticatorCoordinator::makeCredential):
     52        (WebKit::WebAuthenticatorCoordinator::getAssertion):
     53        * WebProcess/WebAuthentication/WebAuthenticatorCoordinator.messages.in:
     54
    1552019-05-07  Per Arne Vollan  <pvollan@apple.com>
    256
  • trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp

    r239852 r245043  
    130130
    131131    if (m_pendingCompletionHandler) {
    132         callback(ExceptionData { NotAllowedError, "A request is pending."_s });
    133         return;
     132        m_pendingCompletionHandler(ExceptionData { NotAllowedError, "This request has been cancelled by a new request."_s });
     133        clearState();
     134        m_requestTimeOutTimer.stop();
    134135    }
    135136
     
    148149
    149150    if (m_pendingCompletionHandler) {
    150         callback(ExceptionData { NotAllowedError, "A request is pending."_s });
    151         return;
     151        m_pendingCompletionHandler(ExceptionData { NotAllowedError, "This request has been cancelled by a new request."_s });
     152        clearState();
     153        m_requestTimeOutTimer.stop();
    152154    }
    153155
     
    167169        if (!weakThis)
    168170            return;
    169         weakThis->m_pendingRequestData = { };
    170         ASSERT(!weakThis->m_pendingCompletionHandler);
    171         weakThis->m_services.clear();
    172         weakThis->m_authenticators.clear();
     171        weakThis->clearState();
    173172    });
     173}
     174
     175void AuthenticatorManager::clearState()
     176{
     177    m_pendingRequestData = { };
     178    ASSERT(!m_pendingCompletionHandler);
     179    m_services.clear();
     180    m_authenticators.clear();
    174181}
    175182
     
    232239    ASSERT(m_requestTimeOutTimer.isActive());
    233240    m_pendingCompletionHandler((ExceptionData { NotAllowedError, "Operation timed out."_s }));
    234     clearStateAsync();
     241    clearState();
    235242}
    236243
  • trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h

    r239427 r245043  
    6363    RunLoop::Timer<AuthenticatorManager>& requestTimeOutTimer() { return m_requestTimeOutTimer; }
    6464    void clearStateAsync(); // To void cyclic dependence.
     65    void clearState();
    6566
    6667private:
     
    8081    void timeOutTimerFired();
    8182
    82     // Request: We only allow one request per time.
     83    // Request: We only allow one request per time. A new request will cancel any pending ones.
    8384    WebAuthenticationRequestData m_pendingRequestData;
    8485    Callback m_pendingCompletionHandler;
  • trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp

    r238221 r245043  
    5454}
    5555
    56 void WebAuthenticatorCoordinatorProxy::makeCredential(const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialCreationOptions& options)
     56void WebAuthenticatorCoordinatorProxy::makeCredential(uint64_t messageId, const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialCreationOptions& options)
    5757{
    58     auto callback = [weakThis = makeWeakPtr(*this)] (Variant<WebCore::PublicKeyCredentialData, WebCore::ExceptionData>&& result) {
     58    auto callback = [messageId, weakThis = makeWeakPtr(*this)] (Variant<WebCore::PublicKeyCredentialData, WebCore::ExceptionData>&& result) {
    5959        ASSERT(RunLoop::isMain());
    6060        if (!weakThis)
     
    6262
    6363        WTF::switchOn(result, [&](const WebCore::PublicKeyCredentialData& data) {
    64             weakThis->requestReply(data, { });
     64            weakThis->requestReply(messageId, data, { });
    6565        }, [&](const  WebCore::ExceptionData& exception) {
    66             weakThis->requestReply({ }, exception);
     66            weakThis->requestReply(messageId, { }, exception);
    6767        });
    6868    };
     
    7070}
    7171
    72 void WebAuthenticatorCoordinatorProxy::getAssertion(const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialRequestOptions& options)
     72void WebAuthenticatorCoordinatorProxy::getAssertion(uint64_t messageId, const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialRequestOptions& options)
    7373{
    74     auto callback = [weakThis = makeWeakPtr(*this)] (Variant<WebCore::PublicKeyCredentialData, WebCore::ExceptionData>&& result) {
     74    auto callback = [messageId, weakThis = makeWeakPtr(*this)] (Variant<WebCore::PublicKeyCredentialData, WebCore::ExceptionData>&& result) {
    7575        ASSERT(RunLoop::isMain());
    7676        if (!weakThis)
     
    7878
    7979        WTF::switchOn(result, [&](const WebCore::PublicKeyCredentialData& data) {
    80             weakThis->requestReply(data, { });
     80            weakThis->requestReply(messageId, data, { });
    8181        }, [&](const  WebCore::ExceptionData& exception) {
    82             weakThis->requestReply({ }, exception);
     82            weakThis->requestReply(messageId, { }, exception);
    8383        });
    8484    };
     
    9191}
    9292
    93 void WebAuthenticatorCoordinatorProxy::requestReply(const WebCore::PublicKeyCredentialData& data, const WebCore::ExceptionData& exception)
     93void WebAuthenticatorCoordinatorProxy::requestReply(uint64_t messageId, const WebCore::PublicKeyCredentialData& data, const WebCore::ExceptionData& exception)
    9494{
    95     m_webPageProxy.send(Messages::WebAuthenticatorCoordinator::RequestReply(data, exception));
     95    m_webPageProxy.send(Messages::WebAuthenticatorCoordinator::RequestReply(messageId, data, exception));
    9696}
    9797
  • trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.h

    r236481 r245043  
    5555
    5656    // Receivers.
    57     void makeCredential(const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialCreationOptions&);
    58     void getAssertion(const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialRequestOptions&);
     57    void makeCredential(uint64_t messageId, const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialCreationOptions&);
     58    void getAssertion(uint64_t messageId, const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialRequestOptions&);
    5959    void isUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId);
    6060
    6161    // Senders.
    62     void requestReply(const WebCore::PublicKeyCredentialData&, const WebCore::ExceptionData&);
     62    void requestReply(uint64_t messageId, const WebCore::PublicKeyCredentialData&, const WebCore::ExceptionData&);
    6363
    6464    WebPageProxy& m_webPageProxy;
  • trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.messages.in

    r235888 r245043  
    2727messages -> WebAuthenticatorCoordinatorProxy {
    2828
    29     MakeCredential(Vector<uint8_t> hash, struct WebCore::PublicKeyCredentialCreationOptions options);
    30     GetAssertion(Vector<uint8_t> hash, struct WebCore::PublicKeyCredentialRequestOptions options);
     29    MakeCredential(uint64_t messageId, Vector<uint8_t> hash, struct WebCore::PublicKeyCredentialCreationOptions options);
     30    GetAssertion(uint64_t messageId, Vector<uint8_t> hash, struct WebCore::PublicKeyCredentialRequestOptions options);
    3131    IsUserVerifyingPlatformAuthenticatorAvailable(uint64_t messageId);
    3232}
  • trunk/Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.cpp

    r235888 r245043  
    5151void WebAuthenticatorCoordinator::makeCredential(const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialCreationOptions& options, WebCore::RequestCompletionHandler&& handler)
    5252{
    53     if (!setRequestCompletionHandler(WTFMove(handler)))
    54         return;
    55 
    56     m_webPage.send(Messages::WebAuthenticatorCoordinatorProxy::MakeCredential(hash, options));
     53    auto messageId = setRequestCompletionHandler(WTFMove(handler));
     54    m_webPage.send(Messages::WebAuthenticatorCoordinatorProxy::MakeCredential(messageId, hash, options));
    5755}
    5856
    5957void WebAuthenticatorCoordinator::getAssertion(const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialRequestOptions& options, WebCore::RequestCompletionHandler&& handler)
    6058{
    61     if (!setRequestCompletionHandler(WTFMove(handler)))
    62         return;
    63 
    64     m_webPage.send(Messages::WebAuthenticatorCoordinatorProxy::GetAssertion(hash, options));
     59    auto messageId = setRequestCompletionHandler(WTFMove(handler));
     60    m_webPage.send(Messages::WebAuthenticatorCoordinatorProxy::GetAssertion(messageId, hash, options));
    6561}
    6662
  • trunk/Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.messages.in

    r235888 r245043  
    2727messages -> WebAuthenticatorCoordinator {
    2828
    29     RequestReply(struct WebCore::PublicKeyCredentialData data, struct WebCore::ExceptionData exception);
     29    RequestReply(uint64_t messageId, struct WebCore::PublicKeyCredentialData data, struct WebCore::ExceptionData exception);
    3030    IsUserVerifyingPlatformAuthenticatorAvailableReply(uint64_t messageId, bool result);
    3131}
Note: See TracChangeset for help on using the changeset viewer.