// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "modules/credentialmanager/CredentialManagerTypeConverters.h"

#include <algorithm>
#include <utility>

#include "bindings/core/v8/array_buffer_or_array_buffer_view.h"
#include "modules/credentialmanager/Credential.h"
#include "modules/credentialmanager/FederatedCredential.h"
#include "modules/credentialmanager/MakePublicKeyCredentialOptions.h"
#include "modules/credentialmanager/PasswordCredential.h"
#include "modules/credentialmanager/PublicKeyCredential.h"
#include "modules/credentialmanager/PublicKeyCredentialDescriptor.h"
#include "modules/credentialmanager/PublicKeyCredentialParameters.h"
#include "modules/credentialmanager/PublicKeyCredentialRequestOptions.h"
#include "modules/credentialmanager/PublicKeyCredentialRpEntity.h"
#include "modules/credentialmanager/PublicKeyCredentialUserEntity.h"
#include "platform/wtf/Time.h"

namespace {
// Time to wait for an authenticator to successfully complete an operation.
constexpr TimeDelta kAdjustedTimeoutLower = TimeDelta::FromSeconds(1);
constexpr TimeDelta kAdjustedTimeoutUpper = TimeDelta::FromMinutes(1);

WTF::TimeDelta AdjustTimeout(uint32_t timeout) {
  WTF::TimeDelta adjusted_timeout;
  adjusted_timeout = WTF::TimeDelta::FromMilliseconds(timeout);
  return std::max(kAdjustedTimeoutLower,
                  std::min(kAdjustedTimeoutUpper, adjusted_timeout));
}
}  // namespace

namespace mojo {

using password_manager::mojom::blink::CredentialInfo;
using password_manager::mojom::blink::CredentialInfoPtr;
using password_manager::mojom::blink::CredentialType;
using password_manager::mojom::blink::CredentialManagerError;
using webauth::mojom::blink::AuthenticatorStatus;
using webauth::mojom::blink::MakePublicKeyCredentialOptionsPtr;
using webauth::mojom::blink::PublicKeyCredentialDescriptor;
using webauth::mojom::blink::PublicKeyCredentialDescriptorPtr;
using webauth::mojom::blink::PublicKeyCredentialRpEntity;
using webauth::mojom::blink::PublicKeyCredentialRpEntityPtr;
using webauth::mojom::blink::PublicKeyCredentialUserEntity;
using webauth::mojom::blink::PublicKeyCredentialUserEntityPtr;
using webauth::mojom::blink::PublicKeyCredentialParameters;
using webauth::mojom::blink::PublicKeyCredentialParametersPtr;
using webauth::mojom::blink::PublicKeyCredentialRequestOptionsPtr;
using webauth::mojom::blink::PublicKeyCredentialType;
using webauth::mojom::blink::AuthenticatorTransport;

// static
CredentialInfoPtr TypeConverter<CredentialInfoPtr, blink::Credential*>::Convert(
    blink::Credential* credential) {
  auto info = CredentialInfo::New();
  info->id = credential->id();
  if (credential->IsPasswordCredential()) {
    ::blink::PasswordCredential* password_credential =
        static_cast<::blink::PasswordCredential*>(credential);
    info->type = CredentialType::PASSWORD;
    info->password = password_credential->password();
    info->name = password_credential->name();
    info->icon = password_credential->iconURL();
    info->federation = blink::SecurityOrigin::CreateUnique();
  } else {
    DCHECK(credential->IsFederatedCredential());
    ::blink::FederatedCredential* federated_credential =
        static_cast<::blink::FederatedCredential*>(credential);
    info->type = CredentialType::FEDERATED;
    info->password = g_empty_string;
    info->federation = federated_credential->GetProviderAsOrigin();
    info->name = federated_credential->name();
    info->icon = federated_credential->iconURL();
  }
  return info;
}

// static
blink::Credential*
TypeConverter<blink::Credential*, CredentialInfoPtr>::Convert(
    const CredentialInfoPtr& info) {
  switch (info->type) {
    case CredentialType::FEDERATED:
      return blink::FederatedCredential::Create(info->id, info->federation,
                                                info->name, info->icon);
    case CredentialType::PASSWORD:
      return blink::PasswordCredential::Create(info->id, info->password,
                                               info->name, info->icon);
    case CredentialType::EMPTY:
      return nullptr;
  }
  NOTREACHED();
  return nullptr;
}

// static
CredentialManagerError
TypeConverter<CredentialManagerError, AuthenticatorStatus>::Convert(
    const AuthenticatorStatus& status) {
  switch (status) {
    case webauth::mojom::blink::AuthenticatorStatus::NOT_SUPPORTED_ERROR:
      return CredentialManagerError::NOT_SUPPORTED;
    case webauth::mojom::blink::AuthenticatorStatus::NOT_ALLOWED_ERROR:
      return CredentialManagerError::NOT_ALLOWED;
    case webauth::mojom::blink::AuthenticatorStatus::UNKNOWN_ERROR:
      return CredentialManagerError::UNKNOWN;
    case webauth::mojom::blink::AuthenticatorStatus::PENDING_REQUEST:
      return CredentialManagerError::PENDING_REQUEST;
    case webauth::mojom::blink::AuthenticatorStatus::INVALID_DOMAIN:
      return CredentialManagerError::INVALID_DOMAIN;
    case webauth::mojom::blink::AuthenticatorStatus::TIMED_OUT:
      return CredentialManagerError::TIMED_OUT;
    case webauth::mojom::blink::AuthenticatorStatus::NOT_IMPLEMENTED:
      return CredentialManagerError::NOT_IMPLEMENTED;
    case webauth::mojom::blink::AuthenticatorStatus::SUCCESS:
      NOTREACHED();
      break;
  }

  NOTREACHED();
  return CredentialManagerError::UNKNOWN;
}

// static
Vector<uint8_t>
TypeConverter<Vector<uint8_t>, blink::ArrayBufferOrArrayBufferView>::Convert(
    const blink::ArrayBufferOrArrayBufferView& buffer) {
  DCHECK(!buffer.IsNull());
  Vector<uint8_t> vector;
  if (buffer.IsArrayBuffer()) {
    vector.Append(static_cast<uint8_t*>(buffer.GetAsArrayBuffer()->Data()),
                  buffer.GetAsArrayBuffer()->ByteLength());
  } else {
    DCHECK(buffer.IsArrayBufferView());
    vector.Append(static_cast<uint8_t*>(
                      buffer.GetAsArrayBufferView().View()->BaseAddress()),
                  buffer.GetAsArrayBufferView().View()->byteLength());
  }
  return vector;
}

// static
PublicKeyCredentialType TypeConverter<PublicKeyCredentialType, String>::Convert(
    const String& type) {
  if (type == "public-key")
    return PublicKeyCredentialType::PUBLIC_KEY;
  NOTREACHED();
  return PublicKeyCredentialType::PUBLIC_KEY;
}

// static
AuthenticatorTransport TypeConverter<AuthenticatorTransport, String>::Convert(
    const String& transport) {
  if (transport == "usb")
    return AuthenticatorTransport::USB;
  if (transport == "nfc")
    return AuthenticatorTransport::NFC;
  if (transport == "ble")
    return AuthenticatorTransport::BLE;
  NOTREACHED();
  return AuthenticatorTransport::USB;
}

// static
PublicKeyCredentialUserEntityPtr
TypeConverter<PublicKeyCredentialUserEntityPtr,
              blink::PublicKeyCredentialUserEntity>::
    Convert(const blink::PublicKeyCredentialUserEntity& user) {
  auto entity = webauth::mojom::blink::PublicKeyCredentialUserEntity::New();
  entity->id = ConvertTo<Vector<uint8_t>>(user.id());
  entity->name = user.name();
  if (user.hasIcon()) {
    entity->icon = blink::KURL(blink::KURL(), user.icon());
  }
  entity->display_name = user.displayName();
  return entity;
}

// static
PublicKeyCredentialRpEntityPtr
TypeConverter<PublicKeyCredentialRpEntityPtr,
              blink::PublicKeyCredentialRpEntity>::
    Convert(const blink::PublicKeyCredentialRpEntity& rp) {
  auto entity = webauth::mojom::blink::PublicKeyCredentialRpEntity::New();
  if (rp.hasId()) {
    entity->id = rp.id();
  }
  entity->name = rp.name();
  if (rp.hasIcon()) {
    entity->icon = blink::KURL(blink::KURL(), rp.icon());
  }
  return entity;
}

// static
PublicKeyCredentialDescriptorPtr
TypeConverter<PublicKeyCredentialDescriptorPtr,
              blink::PublicKeyCredentialDescriptor>::
    Convert(const blink::PublicKeyCredentialDescriptor& descriptor) {
  auto mojo_descriptor =
      webauth::mojom::blink::PublicKeyCredentialDescriptor::New();

  mojo_descriptor->type = ConvertTo<PublicKeyCredentialType>(descriptor.type());
  mojo_descriptor->id = ConvertTo<Vector<uint8_t>>(descriptor.id());
  if (descriptor.hasTransports()) {
    for (const auto& transport : descriptor.transports()) {
      mojo_descriptor->transports.push_back(
          ConvertTo<AuthenticatorTransport>(transport));
    }
  }
  return mojo_descriptor;
}

// static
PublicKeyCredentialParametersPtr
TypeConverter<PublicKeyCredentialParametersPtr,
              blink::PublicKeyCredentialParameters>::
    Convert(const blink::PublicKeyCredentialParameters& parameter) {
  auto mojo_parameter =
      webauth::mojom::blink::PublicKeyCredentialParameters::New();
  mojo_parameter->type = ConvertTo<PublicKeyCredentialType>(parameter.type());

  // A COSEAlgorithmIdentifier's value is a number identifying a cryptographic
  // algorithm. Values are registered in the IANA COSE Algorithms registry.
  // https://www.iana.org/assignments/cose/cose.xhtml#algorithms
  mojo_parameter->algorithm_identifier = parameter.alg();
  return mojo_parameter;
}

// static
MakePublicKeyCredentialOptionsPtr
TypeConverter<MakePublicKeyCredentialOptionsPtr,
              blink::MakePublicKeyCredentialOptions>::
    Convert(const blink::MakePublicKeyCredentialOptions& options) {
  auto mojo_options =
      webauth::mojom::blink::MakePublicKeyCredentialOptions::New();
  mojo_options->relying_party = PublicKeyCredentialRpEntity::From(options.rp());
  mojo_options->user = PublicKeyCredentialUserEntity::From(options.user());
  if (!mojo_options->relying_party | !mojo_options->user) {
    return nullptr;
  }
  mojo_options->challenge = ConvertTo<Vector<uint8_t>>(options.challenge());

  // Step 4 of https://w3c.github.io/webauthn/#createCredential
  if (options.hasTimeout()) {
    mojo_options->adjusted_timeout = AdjustTimeout(options.timeout());
  } else {
    mojo_options->adjusted_timeout = kAdjustedTimeoutUpper;
  }

  // Steps 8 and 9 of
  // https://www.w3.org/TR/2017/WD-webauthn-20170505/#createCredential
  Vector<PublicKeyCredentialParametersPtr> parameters;
  for (const auto& parameter : options.pubKeyCredParams()) {
    PublicKeyCredentialParametersPtr normalized_parameter =
        PublicKeyCredentialParameters::From(parameter);
    if (normalized_parameter) {
      parameters.push_back(std::move(normalized_parameter));
    }
  }

  if (parameters.IsEmpty() && options.hasPubKeyCredParams()) {
    return nullptr;
  }

  mojo_options->public_key_parameters = std::move(parameters);

  if (options.hasExcludeCredentials()) {
    // Adds the excludeCredentials members
    for (const auto descriptor : options.excludeCredentials()) {
      PublicKeyCredentialDescriptorPtr mojo_descriptor =
          PublicKeyCredentialDescriptor::From(descriptor);
      if (mojo_descriptor) {
        mojo_options->exclude_credentials.push_back(std::move(mojo_descriptor));
      }
    }
  }
  return mojo_options;
}

// static
PublicKeyCredentialRequestOptionsPtr
TypeConverter<PublicKeyCredentialRequestOptionsPtr,
              blink::PublicKeyCredentialRequestOptions>::
    Convert(const blink::PublicKeyCredentialRequestOptions& options) {
  auto mojo_options =
      webauth::mojom::blink::PublicKeyCredentialRequestOptions::New();
  mojo_options->challenge = ConvertTo<Vector<uint8_t>>(options.challenge());

  if (options.hasTimeout()) {
    mojo_options->adjusted_timeout = AdjustTimeout(options.timeout());
  } else {
    mojo_options->adjusted_timeout = kAdjustedTimeoutUpper;
  }

  mojo_options->relying_party_id = options.rpId();

  if (options.hasAllowCredentials()) {
    // Adds the allowList members
    for (auto descriptor : options.allowCredentials()) {
      PublicKeyCredentialDescriptorPtr mojo_descriptor =
          PublicKeyCredentialDescriptor::From(descriptor);
      if (mojo_descriptor) {
        mojo_options->allow_credentials.push_back(std::move(mojo_descriptor));
      }
    }
  }
  return mojo_options;
}

}  // namespace mojo
