| 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 1274dcf6c690975e947e853361836ae62d97788a..06cba2c2be2f6b4296dedf8ac97fc645435b2f85 100644
|
| --- a/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
|
| +++ b/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
|
| @@ -4,13 +4,133 @@
|
|
|
| #include "modules/webauth/WebAuthentication.h"
|
|
|
| +#include <stdint.h>
|
| +
|
| #include "bindings/core/v8/ScriptPromise.h"
|
| +#include "bindings/core/v8/ScriptPromiseResolver.h"
|
| +#include "core/dom/DOMException.h"
|
| +#include "core/dom/Document.h"
|
| +#include "core/dom/ExceptionCode.h"
|
| +#include "core/frame/LocalFrame.h"
|
| +#include "modules/webauth/RelyingPartyAccount.h"
|
| +#include "modules/webauth/ScopedCredential.h"
|
| +#include "modules/webauth/ScopedCredentialOptions.h"
|
| +#include "modules/webauth/ScopedCredentialParameters.h"
|
| +#include "public/platform/InterfaceProvider.h"
|
| +
|
| +namespace {
|
| +const char kNoAuthenticatorError[] = "Authenticator unavailable.";
|
| +} // anonymous namespace
|
| +
|
| +namespace mojo {
|
| +
|
| +using webauth::mojom::blink::RelyingPartyAccount;
|
| +using webauth::mojom::blink::RelyingPartyAccountPtr;
|
| +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;
|
| +
|
| +// TODO(kpaulhamus): Make this a TypeConverter
|
| +Vector<uint8_t> ConvertBufferSource(const blink::BufferSource& buffer) {
|
| + DCHECK(buffer.isNull());
|
| + Vector<uint8_t> vector;
|
| + if (buffer.isArrayBuffer()) {
|
| + vector.Append(static_cast<uint8_t*>(buffer.getAsArrayBuffer()->Data()),
|
| + buffer.getAsArrayBuffer()->ByteLength());
|
| + } else {
|
| + vector.Append(static_cast<uint8_t*>(
|
| + buffer.getAsArrayBufferView().View()->BaseAddress()),
|
| + buffer.getAsArrayBufferView().View()->byteLength());
|
| + }
|
| + return vector;
|
| +}
|
| +
|
| +// TODO(kpaulhamus): Make this a TypeConverter
|
| +ScopedCredentialType ConvertScopedCredentialType(const String& cred_type) {
|
| + if (cred_type == "ScopedCred")
|
| + return ScopedCredentialType::SCOPEDCRED;
|
| + NOTREACHED();
|
| + return ScopedCredentialType::SCOPEDCRED;
|
| +}
|
| +
|
| +// TODO(kpaulhamus): Make this a TypeConverter
|
| +Transport ConvertTransport(const String& transport) {
|
| + if (transport == "usb")
|
| + return Transport::USB;
|
| + if (transport == "nfc")
|
| + return Transport::NFC;
|
| + if (transport == "ble")
|
| + return Transport::BLE;
|
| + NOTREACHED();
|
| + return Transport::USB;
|
| +}
|
| +
|
| +RelyingPartyAccountPtr ConvertRelyingPartyAccount(
|
| + const blink::RelyingPartyAccount& account_information,
|
| + blink::ScriptPromiseResolver* resolver) {
|
| + auto mojo_account = RelyingPartyAccount::New();
|
| +
|
| + mojo_account->relying_party_display_name =
|
| + account_information.rpDisplayName();
|
| + mojo_account->display_name = account_information.displayName();
|
| + mojo_account->id = account_information.id();
|
| + mojo_account->name = account_information.name();
|
| + mojo_account->image_url = account_information.imageURL();
|
| + return mojo_account;
|
| +}
|
| +
|
| +// TODO(kpaulhamus): Make this a TypeConverter
|
| +ScopedCredentialOptionsPtr ConvertScopedCredentialOptions(
|
| + const blink::ScopedCredentialOptions options,
|
| + blink::ScriptPromiseResolver* resolver) {
|
| + auto mojo_options = ScopedCredentialOptions::New();
|
| + mojo_options->timeout_seconds = options.timeoutSeconds();
|
| + mojo_options->relying_party_id = options.rpId();
|
| +
|
| + // Adds the excludeList members (which are ScopedCredentialDescriptors)
|
| + for (const auto& descriptor : options.excludeList()) {
|
| + auto mojo_descriptor = ScopedCredentialDescriptor::New();
|
| + mojo_descriptor->type = ConvertScopedCredentialType(descriptor.type());
|
| + mojo_descriptor->id = ConvertBufferSource(descriptor.id());
|
| + for (const auto& transport : descriptor.transports())
|
| + mojo_descriptor->transports.push_back(ConvertTransport(transport));
|
| + mojo_options->exclude_list.push_back(std::move(mojo_descriptor));
|
| + }
|
| + // TODO(kpaulhamus): add AuthenticationExtensions;
|
| + return mojo_options;
|
| +}
|
| +
|
| +// TODO(kpaulhamus): Make this a TypeConverter
|
| +ScopedCredentialParametersPtr ConvertScopedCredentialParameter(
|
| + const blink::ScopedCredentialParameters parameter,
|
| + blink::ScriptPromiseResolver* resolver) {
|
| + auto mojo_parameter = ScopedCredentialParameters::New();
|
| + mojo_parameter->type = ConvertScopedCredentialType(parameter.type());
|
| + // TODO(kpaulhamus): add AlgorithmIdentifier
|
| + return mojo_parameter;
|
| +}
|
| +} // namespace mojo
|
|
|
| namespace blink {
|
|
|
| -WebAuthentication::WebAuthentication(LocalFrame& frame) {}
|
| +WebAuthentication::WebAuthentication(LocalFrame& frame)
|
| + : ContextLifecycleObserver(frame.GetDocument()) {
|
| + frame.GetInterfaceProvider()->GetInterface(
|
| + mojo::MakeRequest(&authenticator_));
|
| + authenticator_.set_connection_error_handler(ConvertToBaseCallback(
|
| + WTF::Bind(&WebAuthentication::OnAuthenticatorConnectionError,
|
| + WrapWeakPersistent(this))));
|
| +}
|
|
|
| -WebAuthentication::~WebAuthentication() {}
|
| +WebAuthentication::~WebAuthentication() {
|
| + // |authenticator_| may still be valid but there should be no more
|
| + // outstanding requests because each holds a persistent handle to this object.
|
| + DCHECK(authenticator_requests_.IsEmpty());
|
| +}
|
|
|
| void WebAuthentication::Dispose() {}
|
|
|
| @@ -20,8 +140,32 @@ ScriptPromise WebAuthentication::makeCredential(
|
| const HeapVector<ScopedCredentialParameters> crypto_parameters,
|
| const BufferSource& attestation_challenge,
|
| ScopedCredentialOptions& options) {
|
| - NOTREACHED();
|
| - return ScriptPromise();
|
| + if (!authenticator_) {
|
| + return ScriptPromise::RejectWithDOMException(
|
| + script_state, DOMException::Create(kNotSupportedError));
|
| + }
|
| +
|
| + ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
|
| + ScriptPromise promise = resolver->Promise();
|
| +
|
| + // TODO(kpaulhamus) validate parameters according to spec
|
| + auto account =
|
| + mojo::ConvertRelyingPartyAccount(account_information, resolver);
|
| + Vector<uint8_t> buffer = mojo::ConvertBufferSource(attestation_challenge);
|
| + auto opts = mojo::ConvertScopedCredentialOptions(options, resolver);
|
| + Vector<webauth::mojom::blink::ScopedCredentialParametersPtr> parameters;
|
| + for (const auto& parameter : crypto_parameters) {
|
| + parameters.push_back(
|
| + mojo::ConvertScopedCredentialParameter(parameter, resolver));
|
| + }
|
| +
|
| + authenticator_requests_.insert(resolver);
|
| + authenticator_->MakeCredential(
|
| + std::move(account), std::move(parameters), buffer, std::move(opts),
|
| + ConvertToBaseCallback(Bind(&WebAuthentication::OnMakeCredential,
|
| + WrapPersistent(this),
|
| + WrapPersistent(resolver))));
|
| + return promise;
|
| }
|
|
|
| ScriptPromise WebAuthentication::getAssertion(
|
| @@ -32,4 +176,58 @@ ScriptPromise WebAuthentication::getAssertion(
|
| return ScriptPromise();
|
| }
|
|
|
| +void WebAuthentication::ContextDestroyed(ExecutionContext*) {
|
| + authenticator_.reset();
|
| + authenticator_requests_.clear();
|
| +}
|
| +
|
| +void WebAuthentication::OnAuthenticatorConnectionError() {
|
| + authenticator_.reset();
|
| + for (ScriptPromiseResolver* resolver : authenticator_requests_) {
|
| + resolver->Reject(
|
| + DOMException::Create(kNotFoundError, kNoAuthenticatorError));
|
| + }
|
| + authenticator_requests_.clear();
|
| +}
|
| +
|
| +void WebAuthentication::OnMakeCredential(
|
| + ScriptPromiseResolver* resolver,
|
| + Vector<webauth::mojom::blink::ScopedCredentialInfoPtr> credentials) {
|
| + if (!MarkRequestComplete(resolver))
|
| + return;
|
| +
|
| + HeapVector<Member<ScopedCredentialInfo>> scoped_credentials;
|
| + for (auto& credential : credentials) {
|
| + if (credential->client_data.IsEmpty() ||
|
| + credential->attestation.IsEmpty()) {
|
| + resolver->Reject(
|
| + DOMException::Create(kNotFoundError, "No credentials returned."));
|
| + }
|
| + DOMArrayBuffer* client_data_buffer = DOMArrayBuffer::Create(
|
| + static_cast<void*>(&credential->client_data.front()),
|
| + credential->client_data.size());
|
| +
|
| + DOMArrayBuffer* attestation_buffer = DOMArrayBuffer::Create(
|
| + static_cast<void*>(&credential->attestation.front()),
|
| + credential->attestation.size());
|
| +
|
| + scoped_credentials.push_back(
|
| + ScopedCredentialInfo::Create(client_data_buffer, attestation_buffer));
|
| + }
|
| + resolver->Resolve();
|
| +}
|
| +
|
| +bool WebAuthentication::MarkRequestComplete(ScriptPromiseResolver* resolver) {
|
| + auto request_entry = authenticator_requests_.find(resolver);
|
| + if (request_entry == authenticator_requests_.end())
|
| + return false;
|
| + authenticator_requests_.erase(request_entry);
|
| + return true;
|
| +}
|
| +
|
| +DEFINE_TRACE(WebAuthentication) {
|
| + visitor->Trace(authenticator_requests_);
|
| + ContextLifecycleObserver::Trace(visitor);
|
| +}
|
| +
|
| } // namespace blink
|
|
|