1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_WebAuthnManager_h
8 #define mozilla_dom_WebAuthnManager_h
10 #include "mozilla/Maybe.h"
11 #include "mozilla/MozPromise.h"
12 #include "mozilla/RandomNum.h"
13 #include "mozilla/dom/AbortSignal.h"
14 #include "mozilla/dom/PWebAuthnTransaction.h"
15 #include "mozilla/dom/WebAuthnManagerBase.h"
18 * Content process manager for the WebAuthn protocol. Created on calls to the
19 * WebAuthentication DOM object, this manager handles establishing IPC channels
20 * for WebAuthn transactions, as well as keeping track of JS Promise objects
21 * representing transactions in flight.
23 * The WebAuthn spec (https://www.w3.org/TR/webauthn/) allows for two different
24 * types of transactions: registration and signing. When either of these is
25 * requested via the DOM API, the following steps are executed in the
28 * - Validation of the request. Return a failed promise to js if request does
29 * not have correct parameters.
31 * - If request is valid, open a new IPC channel for running the transaction. If
32 * another transaction is already running in this content process, cancel it.
33 * Return a pending promise to js.
35 * - Send transaction information to parent process (by running the Start*
36 * functions of WebAuthnManager). Assuming another transaction is currently in
37 * flight in another content process, parent will handle canceling it.
39 * - On return of successful transaction information from parent process, turn
40 * information into DOM object format required by spec, and resolve promise
41 * (by running the Finish* functions of WebAuthnManager). On cancellation
42 * request from parent, reject promise with corresponding error code. Either
43 * outcome will also close the IPC channel.
47 namespace mozilla::dom
{
51 class WebAuthnTransaction
{
53 explicit WebAuthnTransaction(const RefPtr
<Promise
>& aPromise
)
54 : mPromise(aPromise
), mId(NextId()), mVisibilityChanged(false) {
58 // JS Promise representing the transaction status.
59 RefPtr
<Promise
> mPromise
;
61 // Unique transaction id.
64 // Whether or not visibility has changed for the window during this
66 bool mVisibilityChanged
;
69 // Generates a probabilistically unique ID for the new transaction. IDs are 53
70 // bits, as they are used in javascript. We use a random value if possible,
71 // otherwise a counter.
72 static uint64_t NextId() {
73 static uint64_t id
= 0;
74 Maybe
<uint64_t> rand
= mozilla::RandomUint64();
75 return rand
.valueOr(++id
) & UINT64_C(0x1fffffffffffff); // 2^53 - 1
79 class WebAuthnManager final
: public WebAuthnManagerBase
, public AbortFollower
{
81 NS_DECL_ISUPPORTS_INHERITED
82 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WebAuthnManager
, WebAuthnManagerBase
)
84 explicit WebAuthnManager(nsPIDOMWindowInner
* aParent
)
85 : WebAuthnManagerBase(aParent
) {}
87 already_AddRefed
<Promise
> MakeCredential(
88 const PublicKeyCredentialCreationOptions
& aOptions
,
89 const Optional
<OwningNonNull
<AbortSignal
>>& aSignal
, ErrorResult
& aError
);
91 already_AddRefed
<Promise
> GetAssertion(
92 const PublicKeyCredentialRequestOptions
& aOptions
,
93 const Optional
<OwningNonNull
<AbortSignal
>>& aSignal
, ErrorResult
& aError
);
95 already_AddRefed
<Promise
> Store(const Credential
& aCredential
,
98 // WebAuthnManagerBase
100 void FinishMakeCredential(
101 const uint64_t& aTransactionId
,
102 const WebAuthnMakeCredentialResult
& aResult
) override
;
104 void FinishGetAssertion(const uint64_t& aTransactionId
,
105 const WebAuthnGetAssertionResult
& aResult
) override
;
107 void RequestAborted(const uint64_t& aTransactionId
,
108 const nsresult
& aError
) override
;
112 void RunAbortAlgorithm() override
;
115 // Cancels the current transaction (by sending a Cancel message to the
116 // parent) and rejects it by calling RejectTransaction().
117 void CancelTransaction(const nsresult
& aError
);
118 // Upon a visibility change, makes note of it in the current transaction.
119 void HandleVisibilityChange() override
;
122 virtual ~WebAuthnManager();
124 // Rejects the current transaction and calls ClearTransaction().
125 void RejectTransaction(const nsresult
& aError
);
127 // Clears all information we have about the current transaction.
128 void ClearTransaction();
130 // The current transaction, if any.
131 Maybe
<WebAuthnTransaction
> mTransaction
;
134 inline void ImplCycleCollectionTraverse(
135 nsCycleCollectionTraversalCallback
& aCallback
,
136 WebAuthnTransaction
& aTransaction
, const char* aName
, uint32_t aFlags
= 0) {
137 ImplCycleCollectionTraverse(aCallback
, aTransaction
.mPromise
, aName
, aFlags
);
140 inline void ImplCycleCollectionUnlink(WebAuthnTransaction
& aTransaction
) {
141 ImplCycleCollectionUnlink(aTransaction
.mPromise
);
144 } // namespace mozilla::dom
146 #endif // mozilla_dom_WebAuthnManager_h