Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(540)

Unified Diff: third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp

Issue 2788823002: Add the Mojo implementation of authenticator.mojom's MakeCredential. (Closed)
Patch Set: Added webauth browser feature. Corrected optional mojom struct params. Blink rename. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
diff --git a/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp b/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
index 0dafa12e467085e578112a977fb7b3d8f15a3cae..22fe79ccc6205a398ad795eb0673dda0ce299f17 100644
--- a/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
+++ b/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
@@ -17,27 +17,30 @@
namespace {
const char kNoAuthenticatorError[] = "Authenticator unavailable.";
+// Time to wait for an authenticator to successfully complete an operation.
+static const double adjustedTimeoutLower = 60;
+static const double adjustedTimeoutUpper = 120;
} // anonymous namespace
namespace mojo {
-
+using webauth::mojom::blink::AuthenticatorStatus;
+using webauth::mojom::blink::ScopedCredentialDescriptor;
using webauth::mojom::blink::ScopedCredentialOptions;
using webauth::mojom::blink::ScopedCredentialOptionsPtr;
using webauth::mojom::blink::ScopedCredentialParameters;
using webauth::mojom::blink::ScopedCredentialParametersPtr;
-using webauth::mojom::blink::ScopedCredentialDescriptor;
using webauth::mojom::blink::ScopedCredentialType;
using webauth::mojom::blink::Transport;
Vector<uint8_t> convertBufferSource(const blink::BufferSource& buffer) {
- DCHECK(buffer.isNull());
+ DCHECK(!buffer.isNull());
Vector<uint8_t> vector;
if (buffer.isArrayBuffer()) {
- vector.append(static_cast<uint8_t*>(buffer.getAsArrayBuffer()->data()),
- buffer.getAsArrayBuffer()->byteLength());
+ vector.Append(static_cast<uint8_t*>(buffer.getAsArrayBuffer()->Data()),
+ buffer.getAsArrayBuffer()->ByteLength());
} else {
- vector.append(
- static_cast<uint8_t*>(buffer.getAsArrayBufferView()->baseAddress()),
+ vector.Append(
+ static_cast<uint8_t*>(buffer.getAsArrayBufferView()->BaseAddress()),
buffer.getAsArrayBufferView()->byteLength());
}
return vector;
@@ -65,17 +68,33 @@ ScopedCredentialOptionsPtr convertScopedCredentialOptions(
const blink::ScopedCredentialOptions options,
blink::ScriptPromiseResolver* resolver) {
auto mojoOptions = ScopedCredentialOptions::New();
- mojoOptions->timeout_seconds = options.timeoutSeconds();
- mojoOptions->rp_id = options.rpId();
-
- // Adds the excludeList members (which are ScopedCredentialDescriptors)
- for (const auto& descriptor : options.excludeList()) {
- auto mojoDescriptor = ScopedCredentialDescriptor::New();
- mojoDescriptor->type = convertScopedCredentialType(descriptor.type());
- mojoDescriptor->id = convertBufferSource(descriptor.id());
- for (const auto& transport : descriptor.transports())
- mojoDescriptor->transports.push_back(convertTransport(transport));
- mojoOptions->exclude_list.push_back(std::move(mojoDescriptor));
+ if (options.hasRpId()) {
+ mojoOptions->rp_id = options.rpId();
+ }
+
+ // Step 1 of https://w3c.github.io/webauthn/#makeCredential
+ if (options.hasTimeoutSeconds()) {
+ mojoOptions->adjusted_timeout =
+ static_cast<double>(options.timeoutSeconds());
+ if (mojoOptions->adjusted_timeout > adjustedTimeoutUpper) {
+ mojoOptions->adjusted_timeout = adjustedTimeoutUpper;
+ } else if (mojoOptions->adjusted_timeout < adjustedTimeoutLower) {
+ mojoOptions->adjusted_timeout = adjustedTimeoutLower;
+ }
+ } else {
+ mojoOptions->adjusted_timeout = adjustedTimeoutLower;
+ }
+
+ if (options.hasExcludeList()) {
+ // Adds the excludeList members (which are ScopedCredentialDescriptors)
+ for (const auto& descriptor : options.excludeList()) {
+ auto mojoDescriptor = ScopedCredentialDescriptor::New();
+ mojoDescriptor->type = convertScopedCredentialType(descriptor.type());
+ mojoDescriptor->id = convertBufferSource(descriptor.id());
+ for (const auto& transport : descriptor.transports())
+ mojoDescriptor->transports.push_back(convertTransport(transport));
+ mojoOptions->exclude_list.push_back(std::move(mojoDescriptor));
+ }
}
// TODO (kpaulhamus) add AuthenticationExtensions;
return mojoOptions;
@@ -89,64 +108,77 @@ ScopedCredentialParametersPtr convertScopedCredentialParameter(
// TODO (kpaulhamus) add AlgorithmIdentifier
return mojoParameter;
}
+
+blink::DOMException* createExceptionFromStatus(AuthenticatorStatus status) {
+ switch (status) {
+ case AuthenticatorStatus::NOT_ALLOWED_ERROR:
+ return blink::DOMException::Create(blink::kNotAllowedError,
+ "Not allowed.");
+ case AuthenticatorStatus::NOT_SUPPORTED_ERROR:
+ return blink::DOMException::Create(
+ blink::kNotSupportedError,
+ "Parameters for this operation are not supported.");
+ case AuthenticatorStatus::SECURITY_ERROR:
+ return blink::DOMException::Create(blink::kSecurityError,
+ "The operation was not allowed.");
+ case AuthenticatorStatus::UNKNOWN_ERROR:
+ return blink::DOMException::Create(blink::kUnknownError,
+ "Request failed.");
+ case AuthenticatorStatus::CANCELLED:
+ return blink::DOMException::Create(blink::kNotAllowedError,
+ "User canceled the operation.");
+ case AuthenticatorStatus::SUCCESS:
+ return nullptr;
+ default:
+ NOTREACHED();
+ return nullptr;
+ }
+}
} // namespace mojo
namespace blink {
WebAuthentication::WebAuthentication(LocalFrame& frame)
- : ContextLifecycleObserver(frame.document()) {
- frame.interfaceProvider()->getInterface(mojo::MakeRequest(&m_authenticator));
- m_authenticator.set_connection_error_handler(convertToBaseCallback(
- WTF::bind(&WebAuthentication::onAuthenticatorConnectionError,
- wrapWeakPersistent(this))));
-}
+ : ContextLifecycleObserver(frame.GetDocument()) {}
WebAuthentication::~WebAuthentication() {
// |m_authenticator| may still be valid but there should be no more
// outstanding requests because each holds a persistent handle to this object.
- DCHECK(m_authenticatorRequests.isEmpty());
+ DCHECK(m_authenticatorRequests.IsEmpty());
}
void WebAuthentication::Dispose() {}
+// With options
ScriptPromise WebAuthentication::makeCredential(
ScriptState* script_state,
const RelyingPartyAccount& account_information,
const HeapVector<ScopedCredentialParameters> crypto_parameters,
const BufferSource& attestation_challenge,
ScopedCredentialOptions& options) {
- ExecutionContext* executionContext = scriptState->getExecutionContext();
+ ScriptPromise promise = rejectIfNotSupported(script_state);
+ if (!promise.IsEmpty())
+ return promise;
- if (!m_authenticator) {
- return ScriptPromise::rejectWithDOMException(
- scriptState, DOMException::create(NotSupportedError));
- }
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- String errorMessage;
- if (!executionContext->isSecureContext(errorMessage)) {
- return ScriptPromise::rejectWithDOMException(
- scriptState, DOMException::create(SecurityError, errorMessage));
- }
-
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
- ScriptPromise promise = resolver->promise();
-
- // TODO(kpaulhamus) validate parameters according to spec
- Vector<uint8_t> buffer = mojo::convertBufferSource(attestationChallenge);
+ Vector<uint8_t> buffer = mojo::convertBufferSource(attestation_challenge);
auto opts = mojo::convertScopedCredentialOptions(options, resolver);
Vector<webauth::mojom::blink::ScopedCredentialParametersPtr> parameters;
- for (const auto& parameter : cryptoParameters) {
- parameters.push_back(
- mojo::convertScopedCredentialParameter(parameter, resolver));
+ for (const auto& parameter : crypto_parameters) {
+ if (parameter.hasType()) { // TODO add algorithm
+ parameters.push_back(
+ mojo::convertScopedCredentialParameter(parameter, resolver));
+ }
}
m_authenticatorRequests.insert(resolver);
- m_authenticator->makeCredential(
- accountInformation, std::move(parameters), buffer, std::move(opts),
- convertToBaseCallback(WTF::bind(&WebAuthentication::onMakeCredential,
- wrapPersistent(this),
- wrapPersistent(resolver))));
- return promise;
+ m_authenticator->MakeCredential(
+ account_information, std::move(parameters), buffer, std::move(opts),
+ ConvertToBaseCallback(WTF::Bind(&WebAuthentication::onMakeCredential,
+ WrapPersistent(this),
+ WrapPersistent(resolver))));
+ return resolver->Promise();
}
ScriptPromise WebAuthentication::getAssertion(
@@ -157,59 +189,97 @@ ScriptPromise WebAuthentication::getAssertion(
return ScriptPromise();
}
-void WebAuthentication::contextDestroyed(ExecutionContext*) {
- m_authenticator.reset();
- m_authenticatorRequests.clear();
-}
-
-void WebAuthentication::onAuthenticatorConnectionError() {
- m_authenticator.reset();
- for (ScriptPromiseResolver* resolver : m_authenticatorRequests) {
- resolver->reject(
- DOMException::create(NotFoundError, kNoAuthenticatorError));
- }
- m_authenticatorRequests.clear();
+void WebAuthentication::ContextDestroyed(ExecutionContext*) {
+ cleanup();
}
+// Step 11 of https://w3c.github.io/webauthn/#makeCredential
void WebAuthentication::onMakeCredential(
ScriptPromiseResolver* resolver,
- Vector<webauth::mojom::blink::ScopedCredentialInfoPtr> credentials) {
+ webauth::mojom::blink::AuthenticatorStatus status,
+ webauth::mojom::blink::ScopedCredentialInfoPtr credential) {
if (!markRequestComplete(resolver))
return;
- HeapVector<Member<ScopedCredentialInfo>> scopedCredentials;
- for (auto& credential : credentials) {
- if (credential->client_data.isEmpty() ||
- credential->attestation.isEmpty()) {
- resolver->reject(
- DOMException::create(NotFoundError, "No credentials returned."));
+ DOMException* error = mojo::createExceptionFromStatus(status);
+ if (error) {
+ for (ScriptPromiseResolver* resolver : m_authenticatorRequests) {
+ resolver->Reject(error);
+ }
+ cleanup();
Zhiqiang Zhang (Slow) 2017/04/11 19:42:50 Actually, the issue is unrelated to mojo. I checke
+ return;
+ }
+
+ if (credential->client_data.IsEmpty() || credential->attestation.IsEmpty()) {
+ resolver->Reject(
+ DOMException::Create(kNotFoundError, "No credential returned."));
+ return;
+ }
+
+ DOMArrayBuffer* clientDataBuffer = DOMArrayBuffer::Create(
+ static_cast<void*>(&credential->client_data.front()),
+ credential->client_data.size());
+
+ DOMArrayBuffer* attestationBuffer = DOMArrayBuffer::Create(
+ static_cast<void*>(&credential->attestation.front()),
+ credential->attestation.size());
+
+ ScopedCredentialInfo* scopedCredential =
+ ScopedCredentialInfo::Create(clientDataBuffer, attestationBuffer);
+ resolver->Resolve(scopedCredential);
+}
+
+ScriptPromise WebAuthentication::rejectIfNotSupported(
+ ScriptState* script_state) {
+ ExecutionContext* executionContext = script_state->GetExecutionContext();
+
+ if (!m_authenticator) {
+ if (!GetFrame()) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, DOMException::Create(kNotSupportedError));
}
- DOMArrayBuffer* clientDataBuffer = DOMArrayBuffer::create(
- static_cast<void*>(&credential->client_data.front()),
- credential->client_data.size());
+ GetFrame()->GetInterfaceProvider()->GetInterface(
+ mojo::MakeRequest(&m_authenticator));
- DOMArrayBuffer* attestationBuffer = DOMArrayBuffer::create(
- static_cast<void*>(&credential->attestation.front()),
- credential->attestation.size());
+ m_authenticator.set_connection_error_handler(ConvertToBaseCallback(
+ WTF::Bind(&WebAuthentication::onAuthenticatorConnectionError,
+ WrapWeakPersistent(this))));
+ }
- scopedCredentials.push_back(
- ScopedCredentialInfo::create(clientDataBuffer, attestationBuffer));
+ String errorMessage;
+ if (!executionContext->IsSecureContext(errorMessage)) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, DOMException::Create(kSecurityError, errorMessage));
}
- resolver->resolve(scopedCredentials);
- m_authenticatorRequests.erase(resolver);
+
+ return ScriptPromise();
+}
+
+void WebAuthentication::onAuthenticatorConnectionError() {
+ for (ScriptPromiseResolver* resolver : m_authenticatorRequests) {
+ resolver->Reject(
+ DOMException::Create(kNotFoundError, kNoAuthenticatorError));
+ }
+ cleanup();
}
bool WebAuthentication::markRequestComplete(ScriptPromiseResolver* resolver) {
- auto requestEntry = m_authenticatorRequests.find(resolver);
+ auto requestEntry = m_authenticatorRequests.Find(resolver);
if (requestEntry == m_authenticatorRequests.end())
return false;
m_authenticatorRequests.erase(requestEntry);
return true;
}
+// Clears the promise resolver and closes the Mojo connection.
+void WebAuthentication::cleanup() {
+ m_authenticator.reset();
+ m_authenticatorRequests.Clear();
+}
+
DEFINE_TRACE(WebAuthentication) {
- visitor->trace(m_authenticatorRequests);
- ContextLifecycleObserver::trace(visitor);
+ visitor->Trace(m_authenticatorRequests);
+ ContextLifecycleObserver::Trace(visitor);
}
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/modules/webauth/WebAuthentication.h ('k') | third_party/WebKit/Source/web/WebRuntimeFeatures.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698