// Copyright 2016 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 "third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h"

#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-blink.h"
#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_crypto.h"
#include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
#include "third_party/blink/renderer/bindings/modules/v8/serialization/web_crypto_sub_tags.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/crypto/crypto_key.h"
#include "third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h"
#include "third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h"
#include "third_party/blink/renderer/modules/filesystem/dom_file_system.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_certificate.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame_delegate.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame_delegate.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame_attachment.h"

namespace blink {

ScriptWrappable* V8ScriptValueDeserializerForModules::ReadDOMObject(
    SerializationTag tag,
    ExceptionState& exception_state) {
  // Give the core/ implementation a chance to try first.
  // If it didn't recognize the kind of wrapper, try the modules types.
  if (ScriptWrappable* wrappable =
          V8ScriptValueDeserializer::ReadDOMObject(tag, exception_state))
    return wrappable;

  switch (tag) {
    case kCryptoKeyTag:
      return ReadCryptoKey();
    case kDOMFileSystemTag: {
      uint32_t raw_type;
      String name;
      String root_url;
      if (!ReadUint32(&raw_type) ||
          raw_type >
              static_cast<int32_t>(mojom::blink::FileSystemType::kMaxValue) ||
          !ReadUTF8String(&name) || !ReadUTF8String(&root_url))
        return nullptr;
      return MakeGarbageCollected<DOMFileSystem>(
          ExecutionContext::From(GetScriptState()), name,
          static_cast<mojom::blink::FileSystemType>(raw_type), KURL(root_url));
    }
    case kFileSystemFileHandleTag:
    case kFileSystemDirectoryHandleTag:
      return ReadFileSystemHandle(tag);
    case kRTCCertificateTag: {
      String pem_private_key;
      String pem_certificate;
      if (!ReadUTF8String(&pem_private_key) ||
          !ReadUTF8String(&pem_certificate))
        return nullptr;
      std::unique_ptr<RTCCertificateGenerator> certificate_generator =
          std::make_unique<RTCCertificateGenerator>();
      if (!certificate_generator)
        return nullptr;
      rtc::scoped_refptr<rtc::RTCCertificate> certificate =
          certificate_generator->FromPEM(pem_private_key, pem_certificate);
      if (!certificate)
        return nullptr;
      return MakeGarbageCollected<RTCCertificate>(std::move(certificate));
    }
    case kRTCEncodedAudioFrameTag:
      return ReadRTCEncodedAudioFrame();
    case kRTCEncodedVideoFrameTag:
      return ReadRTCEncodedVideoFrame();
    case kVideoFrameTag:
      return ReadVideoFrame();
    default:
      break;
  }
  return nullptr;
}

namespace {

bool AlgorithmIdFromWireFormat(uint32_t raw_id, WebCryptoAlgorithmId* id) {
  switch (static_cast<CryptoKeyAlgorithmTag>(raw_id)) {
    case kAesCbcTag:
      *id = kWebCryptoAlgorithmIdAesCbc;
      return true;
    case kHmacTag:
      *id = kWebCryptoAlgorithmIdHmac;
      return true;
    case kRsaSsaPkcs1v1_5Tag:
      *id = kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
      return true;
    case kSha1Tag:
      *id = kWebCryptoAlgorithmIdSha1;
      return true;
    case kSha256Tag:
      *id = kWebCryptoAlgorithmIdSha256;
      return true;
    case kSha384Tag:
      *id = kWebCryptoAlgorithmIdSha384;
      return true;
    case kSha512Tag:
      *id = kWebCryptoAlgorithmIdSha512;
      return true;
    case kAesGcmTag:
      *id = kWebCryptoAlgorithmIdAesGcm;
      return true;
    case kRsaOaepTag:
      *id = kWebCryptoAlgorithmIdRsaOaep;
      return true;
    case kAesCtrTag:
      *id = kWebCryptoAlgorithmIdAesCtr;
      return true;
    case kAesKwTag:
      *id = kWebCryptoAlgorithmIdAesKw;
      return true;
    case kRsaPssTag:
      *id = kWebCryptoAlgorithmIdRsaPss;
      return true;
    case kEcdsaTag:
      *id = kWebCryptoAlgorithmIdEcdsa;
      return true;
    case kEcdhTag:
      *id = kWebCryptoAlgorithmIdEcdh;
      return true;
    case kHkdfTag:
      *id = kWebCryptoAlgorithmIdHkdf;
      return true;
    case kPbkdf2Tag:
      *id = kWebCryptoAlgorithmIdPbkdf2;
      return true;
  }
  return false;
}

bool AsymmetricKeyTypeFromWireFormat(uint32_t raw_key_type,
                                     WebCryptoKeyType* key_type) {
  switch (static_cast<AsymmetricCryptoKeyType>(raw_key_type)) {
    case kPublicKeyType:
      *key_type = kWebCryptoKeyTypePublic;
      return true;
    case kPrivateKeyType:
      *key_type = kWebCryptoKeyTypePrivate;
      return true;
  }
  return false;
}

bool NamedCurveFromWireFormat(uint32_t raw_named_curve,
                              WebCryptoNamedCurve* named_curve) {
  switch (static_cast<NamedCurveTag>(raw_named_curve)) {
    case kP256Tag:
      *named_curve = kWebCryptoNamedCurveP256;
      return true;
    case kP384Tag:
      *named_curve = kWebCryptoNamedCurveP384;
      return true;
    case kP521Tag:
      *named_curve = kWebCryptoNamedCurveP521;
      return true;
  }
  return false;
}

bool KeyUsagesFromWireFormat(uint32_t raw_usages,
                             WebCryptoKeyUsageMask* usages,
                             bool* extractable) {
  // Reminder to update this when adding new key usages.
  static_assert(kEndOfWebCryptoKeyUsage == (1 << 7) + 1,
                "update required when adding new key usages");
  const uint32_t kAllPossibleUsages =
      kExtractableUsage | kEncryptUsage | kDecryptUsage | kSignUsage |
      kVerifyUsage | kDeriveKeyUsage | kWrapKeyUsage | kUnwrapKeyUsage |
      kDeriveBitsUsage;
  if (raw_usages & ~kAllPossibleUsages)
    return false;

  *usages = 0;
  *extractable = raw_usages & kExtractableUsage;
  if (raw_usages & kEncryptUsage)
    *usages |= kWebCryptoKeyUsageEncrypt;
  if (raw_usages & kDecryptUsage)
    *usages |= kWebCryptoKeyUsageDecrypt;
  if (raw_usages & kSignUsage)
    *usages |= kWebCryptoKeyUsageSign;
  if (raw_usages & kVerifyUsage)
    *usages |= kWebCryptoKeyUsageVerify;
  if (raw_usages & kDeriveKeyUsage)
    *usages |= kWebCryptoKeyUsageDeriveKey;
  if (raw_usages & kWrapKeyUsage)
    *usages |= kWebCryptoKeyUsageWrapKey;
  if (raw_usages & kUnwrapKeyUsage)
    *usages |= kWebCryptoKeyUsageUnwrapKey;
  if (raw_usages & kDeriveBitsUsage)
    *usages |= kWebCryptoKeyUsageDeriveBits;
  return true;
}

}  // namespace

CryptoKey* V8ScriptValueDeserializerForModules::ReadCryptoKey() {
  // Read params.
  uint8_t raw_key_type;
  if (!ReadOneByte(&raw_key_type))
    return nullptr;
  WebCryptoKeyAlgorithm algorithm;
  WebCryptoKeyType key_type = kWebCryptoKeyTypeSecret;
  switch (raw_key_type) {
    case kAesKeyTag: {
      uint32_t raw_id;
      WebCryptoAlgorithmId id;
      uint32_t length_bytes;
      if (!ReadUint32(&raw_id) || !AlgorithmIdFromWireFormat(raw_id, &id) ||
          !ReadUint32(&length_bytes) ||
          length_bytes > std::numeric_limits<uint16_t>::max() / 8u)
        return nullptr;
      algorithm = WebCryptoKeyAlgorithm::CreateAes(id, length_bytes * 8);
      key_type = kWebCryptoKeyTypeSecret;
      break;
    }
    case kHmacKeyTag: {
      uint32_t length_bytes;
      uint32_t raw_hash;
      WebCryptoAlgorithmId hash;
      if (!ReadUint32(&length_bytes) ||
          length_bytes > std::numeric_limits<unsigned>::max() / 8 ||
          !ReadUint32(&raw_hash) || !AlgorithmIdFromWireFormat(raw_hash, &hash))
        return nullptr;
      algorithm = WebCryptoKeyAlgorithm::CreateHmac(hash, length_bytes * 8);
      key_type = kWebCryptoKeyTypeSecret;
      break;
    }
    case kRsaHashedKeyTag: {
      uint32_t raw_id;
      WebCryptoAlgorithmId id;
      uint32_t raw_key_type;
      uint32_t modulus_length_bits;
      uint32_t public_exponent_size;
      const void* public_exponent_bytes;
      uint32_t raw_hash;
      WebCryptoAlgorithmId hash;
      if (!ReadUint32(&raw_id) || !AlgorithmIdFromWireFormat(raw_id, &id) ||
          !ReadUint32(&raw_key_type) ||
          !AsymmetricKeyTypeFromWireFormat(raw_key_type, &key_type) ||
          !ReadUint32(&modulus_length_bits) ||
          !ReadUint32(&public_exponent_size) ||
          !ReadRawBytes(public_exponent_size, &public_exponent_bytes) ||
          !ReadUint32(&raw_hash) || !AlgorithmIdFromWireFormat(raw_hash, &hash))
        return nullptr;
      algorithm = WebCryptoKeyAlgorithm::CreateRsaHashed(
          id, modulus_length_bits,
          reinterpret_cast<const unsigned char*>(public_exponent_bytes),
          public_exponent_size, hash);
      break;
    }
    case kEcKeyTag: {
      uint32_t raw_id;
      WebCryptoAlgorithmId id;
      uint32_t raw_key_type;
      uint32_t raw_named_curve;
      WebCryptoNamedCurve named_curve;
      if (!ReadUint32(&raw_id) || !AlgorithmIdFromWireFormat(raw_id, &id) ||
          !ReadUint32(&raw_key_type) ||
          !AsymmetricKeyTypeFromWireFormat(raw_key_type, &key_type) ||
          !ReadUint32(&raw_named_curve) ||
          !NamedCurveFromWireFormat(raw_named_curve, &named_curve))
        return nullptr;
      algorithm = WebCryptoKeyAlgorithm::CreateEc(id, named_curve);
      break;
    }
    case kNoParamsKeyTag: {
      uint32_t raw_id;
      WebCryptoAlgorithmId id;
      if (!ReadUint32(&raw_id) || !AlgorithmIdFromWireFormat(raw_id, &id))
        return nullptr;
      algorithm = WebCryptoKeyAlgorithm::CreateWithoutParams(id);
      break;
    }
  }
  if (algorithm.IsNull())
    return nullptr;

  // Read key usages.
  uint32_t raw_usages;
  WebCryptoKeyUsageMask usages;
  bool extractable;
  if (!ReadUint32(&raw_usages) ||
      !KeyUsagesFromWireFormat(raw_usages, &usages, &extractable))
    return nullptr;

  // Read key data.
  uint32_t key_data_length;
  const void* key_data;
  if (!ReadUint32(&key_data_length) ||
      !ReadRawBytes(key_data_length, &key_data))
    return nullptr;

  WebCryptoKey key = WebCryptoKey::CreateNull();
  if (!Platform::Current()->Crypto()->DeserializeKeyForClone(
          algorithm, key_type, extractable, usages,
          reinterpret_cast<const unsigned char*>(key_data), key_data_length,
          key))
    return nullptr;

  return MakeGarbageCollected<CryptoKey>(key);
}

FileSystemHandle* V8ScriptValueDeserializerForModules::ReadFileSystemHandle(
    SerializationTag tag) {
  if (!RuntimeEnabledFeatures::FileSystemAccessEnabled(
          ExecutionContext::From(GetScriptState()))) {
    return nullptr;
  }

  String name;
  uint32_t token_index;
  if (!ReadUTF8String(&name) || !ReadUint32(&token_index)) {
    return nullptr;
  }

  // Find the FileSystemHandle's token.
  SerializedScriptValue::FileSystemAccessTokensArray& tokens_array =
      GetSerializedScriptValue()->FileSystemAccessTokens();
  if (token_index >= tokens_array.size()) {
    return nullptr;
  }

  // IndexedDB code assumes that deserializing a SSV is non-destructive. So
  // rather than consuming the token here instead we clone it.
  mojo::Remote<mojom::blink::FileSystemAccessTransferToken> token(
      std::move(tokens_array[token_index]));
  if (!token) {
    return nullptr;
  }

  mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> token_clone;
  token->Clone(token_clone.InitWithNewPipeAndPassReceiver());
  tokens_array[token_index] = std::move(token_clone);

  // Use the FileSystemAccessManager to redeem the token to clone the
  // FileSystemHandle.
  ExecutionContext* execution_context =
      ExecutionContext::From(GetScriptState());
  mojo::Remote<mojom::blink::FileSystemAccessManager>
      file_system_access_manager;
  execution_context->GetBrowserInterfaceBroker().GetInterface(
      file_system_access_manager.BindNewPipeAndPassReceiver());

  // Clone the FileSystemHandle object.
  switch (tag) {
    case kFileSystemFileHandleTag: {
      mojo::PendingRemote<mojom::blink::FileSystemAccessFileHandle> file_handle;

      file_system_access_manager->GetFileHandleFromToken(
          token.Unbind(), file_handle.InitWithNewPipeAndPassReceiver());

      return MakeGarbageCollected<FileSystemFileHandle>(execution_context, name,
                                                        std::move(file_handle));
    }
    case kFileSystemDirectoryHandleTag: {
      mojo::PendingRemote<mojom::blink::FileSystemAccessDirectoryHandle>
          directory_handle;

      file_system_access_manager->GetDirectoryHandleFromToken(
          token.Unbind(), directory_handle.InitWithNewPipeAndPassReceiver());

      return MakeGarbageCollected<FileSystemDirectoryHandle>(
          execution_context, name, std::move(directory_handle));
    }
    default: {
      NOTREACHED();
      return nullptr;
    }
  }
}

RTCEncodedAudioFrame*
V8ScriptValueDeserializerForModules::ReadRTCEncodedAudioFrame() {
  uint32_t index;
  if (!ReadUint32(&index))
    return nullptr;

  const auto* attachment =
      GetSerializedScriptValue()
          ->GetAttachmentIfExists<RTCEncodedAudioFramesAttachment>();
  if (!attachment)
    return nullptr;

  const auto& frames = attachment->EncodedAudioFrames();
  if (index >= frames.size())
    return nullptr;

  return MakeGarbageCollected<RTCEncodedAudioFrame>(frames[index]);
}

RTCEncodedVideoFrame*
V8ScriptValueDeserializerForModules::ReadRTCEncodedVideoFrame() {
  uint32_t index;
  if (!ReadUint32(&index))
    return nullptr;

  const auto* attachment =
      GetSerializedScriptValue()
          ->GetAttachmentIfExists<RTCEncodedVideoFramesAttachment>();
  if (!attachment)
    return nullptr;

  const auto& frames = attachment->EncodedVideoFrames();
  if (index >= frames.size())
    return nullptr;

  return MakeGarbageCollected<RTCEncodedVideoFrame>(frames[index]);
}

VideoFrame* V8ScriptValueDeserializerForModules::ReadVideoFrame() {
  if (!RuntimeEnabledFeatures::WebCodecsEnabled(
          ExecutionContext::From(GetScriptState()))) {
    return nullptr;
  }

  uint32_t index;
  if (!ReadUint32(&index))
    return nullptr;

  const auto* attachment =
      GetSerializedScriptValue()->GetAttachmentIfExists<VideoFrameAttachment>();
  if (!attachment)
    return nullptr;

  const auto& handles = attachment->Handles();
  if (index >= attachment->size())
    return nullptr;

  return MakeGarbageCollected<VideoFrame>(handles[index]);
}

}  // namespace blink
