// Copyright 2018 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 "media/gpu/windows/d3d11_decryptor.h"

#include <initguid.h>

#include <array>

#include "base/bind.h"
#include "base/containers/span.h"
#include "base/stl_util.h"
#include "media/base/decoder_buffer.h"
#include "media/base/subsample_entry.h"
#include "media/base/win/d3d11_mocks.h"
#include "media/cdm/cdm_proxy_context.h"

using ::testing::_;
using ::testing::AtLeast;
using ::testing::DoAll;
using ::testing::ElementsAreArray;
using ::testing::Invoke;
using ::testing::IsNull;
using ::testing::Mock;
using ::testing::Pointee;
using ::testing::Return;
using ::testing::SetArgPointee;

template <class T>
using ComPtr = Microsoft::WRL::ComPtr<T>;

namespace media {

namespace {
// clang-format off
// The value doesn't matter this is just a GUID.
DEFINE_GUID(TEST_GUID,
            0x01020304, 0xffee, 0xefba,
            0x93, 0xaa, 0x47, 0x77, 0x43, 0xb1, 0x22, 0x98);
// clang-format on

// Should be non-0 so that it's different from the default TimeDelta.
constexpr base::TimeDelta kTestTimestamp =
    base::TimeDelta::FromMilliseconds(33);

const uint8_t kAnyKeyBlob[] = {3, 5, 38, 19};
const char kKeyId[] = "some 16 byte id.";
const char kIv[] = "some 16 byte iv.";

// For tests where the input doesn't matter.
const uint8_t kAnyInput[] = {
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
};

const SubsampleEntry kAnyInputSubsample(0, base::size(kAnyInput));

scoped_refptr<DecoderBuffer> TestDecoderBuffer(
    const uint8_t* input,
    size_t data_size,
    const std::string& key_id,
    const std::string& iv,
    const std::vector<SubsampleEntry>& subsamples) {
  scoped_refptr<DecoderBuffer> encrypted_buffer =
      DecoderBuffer::CopyFrom(input, data_size);

  encrypted_buffer->set_decrypt_config(
      DecryptConfig::CreateCencConfig(key_id, iv, subsamples));
  encrypted_buffer->set_timestamp(kTestTimestamp);
  return encrypted_buffer;
}

CdmProxyContext::D3D11DecryptContext TestDecryptContext(
    ComPtr<D3D11CryptoSessionMock> crypto_session_mock) {
  CdmProxyContext::D3D11DecryptContext decrypt_context = {};
  decrypt_context.crypto_session = crypto_session_mock.Get();
  decrypt_context.key_blob = kAnyKeyBlob;
  decrypt_context.key_blob_size = base::size(kAnyKeyBlob);
  decrypt_context.key_info_guid = TEST_GUID;
  return decrypt_context;
}

class CallbackMock {
 public:
  MOCK_METHOD2(DecryptCallback, Decryptor::DecryptCB::RunType);
};

class CdmProxyContextMock : public CdmProxyContext {
 public:
  MOCK_METHOD2(GetD3D11DecryptContext,
               base::Optional<D3D11DecryptContext>(CdmProxy::KeyType key_type,
                                                   const std::string& key_id));
};

// Checks that BUFFER_DESC has these fields match.
// Flags are ORed values, so this only checks that the expected flags are set.
// The other fields are ignored.
MATCHER_P3(BufferDescHas, usage, bind_flags, cpu_access, "") {
  const D3D11_BUFFER_DESC& buffer_desc = *arg;
  if (buffer_desc.Usage != usage)
    return false;

  // Because the flags are enums the compiler infers that the input flags are
  // signed ints. And the compiler rejects comparing signed int and unsigned
  // int, so they are cast here.
  const UINT unsigned_bind_flags = bind_flags;
  const UINT unsigned_cpu_access_flags = cpu_access;

  if ((buffer_desc.BindFlags & unsigned_bind_flags) != unsigned_bind_flags)
    return false;

  return (buffer_desc.CPUAccessFlags & unsigned_cpu_access_flags) ==
         unsigned_cpu_access_flags;
}

// NumEncryptedBytesAtBeginning must be greater than or equal to the size of the
// encrypted data, and also a multiple of 16.
MATCHER_P(NumEncryptedBytesAtBeginningGreaterOrEq, value, "") {
  const D3D11_ENCRYPTED_BLOCK_INFO& block_info = *arg;
  if (block_info.NumEncryptedBytesAtBeginning < value) {
    *result_listener << block_info.NumEncryptedBytesAtBeginning
                     << " is not less than " << value;
    return false;
  }
  return block_info.NumEncryptedBytesAtBeginning % 16 == 0;
}

ACTION_P(SetBufferDescSize, size) {
  arg0->ByteWidth = size;
}

MATCHER_P2(OutputDataEquals, data, size, "") {
  scoped_refptr<DecoderBuffer> buffer = arg;
  if (size != buffer->data_size()) {
    return false;
  }
  if (buffer->timestamp() != kTestTimestamp) {
    return false;
  }

  std::vector<uint8_t> expected(data, data + size);
  std::vector<uint8_t> actual(buffer->data(),
                              buffer->data() + buffer->data_size());
  return actual == expected;
}

}  // namespace

class D3D11DecryptorTest : public ::testing::Test {
 protected:
  void SetUp() override {
    decryptor_ = std::make_unique<D3D11Decryptor>(&mock_proxy_);

    device_mock_ = CreateD3D11Mock<D3D11DeviceMock>();
    device_context_mock_ = CreateD3D11Mock<D3D11DeviceContextMock>();
    video_context_mock_ = CreateD3D11Mock<D3D11VideoContextMock>();
    staging_buffer1_ = CreateD3D11Mock<D3D11BufferMock>();
    staging_buffer2_ = CreateD3D11Mock<D3D11BufferMock>();
    gpu_buffer_ = CreateD3D11Mock<D3D11BufferMock>();
  }

  // Only sets mock expectations to the objects. Use this for the case where the
  // buffers are expected to be created from |device_mock_|, that's accessible
  // through |crypto_session_mock|'s GetDevice() function.
  void SetExpectationsForSuccessfulBufferInitialization(
      D3D11CryptoSessionMock* crypto_session_mock,
      CdmProxyContext::D3D11DecryptContext* decrypt_context) {
    // As noted in the function comment, the device is accessible from the
    // crypto session.
    EXPECT_CALL(*crypto_session_mock, GetDevice(_))
        .Times(AtLeast(1))
        .WillRepeatedly(SetComPointee<0>(device_mock_.Get()));

    // The other components accessible (directly or indirectly) from the device.
    COM_EXPECT_CALL(device_mock_, GetImmediateContext(_))
        .Times(AtLeast(1))
        .WillRepeatedly(SetComPointee<0>(device_context_mock_.Get()));
    COM_EXPECT_CALL(device_context_mock_,
                    QueryInterface(IID_ID3D11VideoContext, _))
        .Times(AtLeast(1))
        .WillRepeatedly(SetComPointeeAndReturnOk<1>(video_context_mock_.Get()));

    EXPECT_CALL(mock_proxy_,
                GetD3D11DecryptContext(CdmProxy::KeyType::kDecryptOnly, kKeyId))
        .WillOnce(Return(*decrypt_context));

    // These return big enough size.
    COM_ON_CALL(staging_buffer1_, GetDesc(_))
        .WillByDefault(SetBufferDescSize(20000));
    COM_ON_CALL(staging_buffer2_, GetDesc(_))
        .WillByDefault(SetBufferDescSize(20000));
    COM_ON_CALL(gpu_buffer_, GetDesc(_))
        .WillByDefault(SetBufferDescSize(20000));

    // It should be requesting for 2 staging buffers one for writing the data to
    // a GPU buffer and one for reading from the a GPU buffer.
    COM_EXPECT_CALL(device_mock_,
                    CreateBuffer(BufferDescHas(D3D11_USAGE_STAGING, 0u,
                                               D3D11_CPU_ACCESS_READ |
                                                   D3D11_CPU_ACCESS_WRITE),
                                 nullptr, _))
        .WillOnce(SetComPointeeAndReturnOk<2>(staging_buffer1_.Get()))
        .WillOnce(SetComPointeeAndReturnOk<2>(staging_buffer2_.Get()));

    // It should be requesting a GPU only accessible buffer to the decrypted
    // output.
    COM_EXPECT_CALL(device_mock_,
                    CreateBuffer(BufferDescHas(D3D11_USAGE_DEFAULT,
                                               D3D11_BIND_RENDER_TARGET, 0u),
                                 nullptr, _))
        .WillOnce(SetComPointeeAndReturnOk<2>(gpu_buffer_.Get()));
  }

  // |input| is the input to the Decrypt() function, the subsample information
  // is in |subsamples| therefore |input| may not be entirely encrypted. The
  // data that is encrypted in |input| should be |encrypted_input|.
  // |whole_output| is the expected output from the Decrypt() call, reported by
  // the callback. The decrypted result of |encrypted_input| should be
  // |decrypted_output|.
  void ExpectSuccessfulDecryption(D3D11CryptoSessionMock* crypto_session_mock,
                                  base::span<const uint8_t> input,
                                  base::span<const uint8_t> encrypted_input,
                                  base::span<const uint8_t> whole_output,
                                  base::span<const uint8_t> decrypted_output,
                                  const std::vector<SubsampleEntry>& subsamples,
                                  D3D11Decryptor* decryptor) {
    D3D11_MAPPED_SUBRESOURCE staging_buffer1_subresource = {};
    auto staging_buffer1_subresource_buffer =
        std::make_unique<uint8_t[]>(20000);
    staging_buffer1_subresource.pData =
        staging_buffer1_subresource_buffer.get();

    // It should be requesting for a memory mapped buffer, from the staging
    // buffer, to pass the encrypted data to the GPU.
    COM_EXPECT_CALL(device_context_mock_,
                    Map(staging_buffer1_.Get(), 0, D3D11_MAP_WRITE, _, _))
        .WillOnce(
            DoAll(SetArgPointee<4>(staging_buffer1_subresource), Return(S_OK)));
    COM_EXPECT_CALL(device_context_mock_, Unmap(staging_buffer1_.Get(), 0));

    COM_EXPECT_CALL(
        video_context_mock_,
        DecryptionBlt(
            crypto_session_mock,
            reinterpret_cast<ID3D11Texture2D*>(staging_buffer1_.Get()),
            reinterpret_cast<ID3D11Texture2D*>(gpu_buffer_.Get()),
            NumEncryptedBytesAtBeginningGreaterOrEq(encrypted_input.size()),
            sizeof(kAnyKeyBlob), kAnyKeyBlob, _, _));
    COM_EXPECT_CALL(device_context_mock_,
                    CopyResource(staging_buffer2_.Get(), gpu_buffer_.Get()));

    D3D11_MAPPED_SUBRESOURCE staging_buffer2_subresource = {};

    // pData field is non-const void* so make a copy of kFakeDecryptedData that
    // can be cast to void*.
    std::unique_ptr<uint8_t[]> decrypted_data =
        std::make_unique<uint8_t[]>(decrypted_output.size());
    memcpy(decrypted_data.get(), decrypted_output.data(),
           decrypted_output.size());
    staging_buffer2_subresource.pData = decrypted_data.get();

    // Tt should be requesting for a memory mapped buffer, from the staging
    // buffer, to read the decrypted data out from the GPU buffer.
    COM_EXPECT_CALL(device_context_mock_,
                    Map(staging_buffer2_.Get(), 0, D3D11_MAP_READ, _, _))
        .WillOnce(
            DoAll(SetArgPointee<4>(staging_buffer2_subresource), Return(S_OK)));
    COM_EXPECT_CALL(device_context_mock_, Unmap(staging_buffer2_.Get(), 0));

    CallbackMock callbacks;
    EXPECT_CALL(callbacks,
                DecryptCallback(Decryptor::kSuccess,
                                OutputDataEquals(whole_output.data(),
                                                 whole_output.size())));

    scoped_refptr<DecoderBuffer> encrypted_buffer =
        TestDecoderBuffer(input.data(), input.size(), kKeyId, kIv, subsamples);
    decryptor->Decrypt(Decryptor::kAudio, encrypted_buffer,
                       base::BindRepeating(&CallbackMock::DecryptCallback,
                                           base::Unretained(&callbacks)));

    // Verify that the data copied to the GPU buffer is the encrypted portion.
    EXPECT_TRUE(std::equal(encrypted_input.begin(), encrypted_input.end(),
                           staging_buffer1_subresource_buffer.get()));
  }

  std::unique_ptr<D3D11Decryptor> decryptor_;
  CdmProxyContextMock mock_proxy_;

  ComPtr<D3D11DeviceMock> device_mock_;
  ComPtr<D3D11DeviceContextMock> device_context_mock_;
  ComPtr<D3D11VideoContextMock> video_context_mock_;

 private:
  ComPtr<D3D11BufferMock> staging_buffer1_;
  ComPtr<D3D11BufferMock> staging_buffer2_;
  ComPtr<D3D11BufferMock> gpu_buffer_;
};

// Verify that full sample encrypted sample works.
TEST_F(D3D11DecryptorTest, FullSampleCtrDecrypt) {
  const uint8_t kInput[] = {
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  };
  const SubsampleEntry kSubsample(0, base::size(kInput));
  // This is arbitrary. Just used to check that this value is output from the
  // method.
  const uint8_t kFakeDecryptedData[] = {
      15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
  };
  static_assert(base::size(kFakeDecryptedData) == base::size(kInput),
                "Fake input and output data size must match.");

  ComPtr<D3D11CryptoSessionMock> crypto_session_mock =
      CreateD3D11Mock<D3D11CryptoSessionMock>();
  CdmProxyContext::D3D11DecryptContext decrypt_context =
      TestDecryptContext(crypto_session_mock);
  SetExpectationsForSuccessfulBufferInitialization(crypto_session_mock.Get(),
                                                   &decrypt_context);

  // The entire sample is encrypted so the encrypted/decrypted portions are the
  // input/output.
  ExpectSuccessfulDecryption(crypto_session_mock.Get(), kInput, kInput,
                             kFakeDecryptedData, kFakeDecryptedData,
                             {kSubsample}, decryptor_.get());
}

// Verify that it works for encrypted input that's not a multiple of 16.
TEST_F(D3D11DecryptorTest, InputSizeNotMultipleOf16) {
  const uint8_t kInput[] = {
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
  };
  const SubsampleEntry kSubsample(0, base::size(kInput));
  // This is arbitrary. Just used to check that this value is output from the
  // method.
  const uint8_t kFakeDecryptedData[] = {
      20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
  };
  static_assert(base::size(kFakeDecryptedData) == base::size(kInput),
                "Fake input and output data size must match.");

  ComPtr<D3D11CryptoSessionMock> crypto_session_mock =
      CreateD3D11Mock<D3D11CryptoSessionMock>();
  CdmProxyContext::D3D11DecryptContext decrypt_context =
      TestDecryptContext(crypto_session_mock);

  SetExpectationsForSuccessfulBufferInitialization(crypto_session_mock.Get(),
                                                   &decrypt_context);

  // The entire sample is encrypted so the encrypted/decrypted portions are the
  // input/output.
  ExpectSuccessfulDecryption(crypto_session_mock.Get(), kInput, kInput,
                             kFakeDecryptedData, kFakeDecryptedData,
                             {kSubsample}, decryptor_.get());
}

// Verify subsample decryption works.
TEST_F(D3D11DecryptorTest, SubsampleCtrDecrypt) {
  // clang-format off
  const uint8_t kInput[] = {
      // clear 16 bytes.
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
      // encrypted 16 bytes.
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
      // clear 5 bytes.
      0, 1, 2, 3, 4,
      // encrypted 16 bytes.
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  };
  // Encrypted parts of the input
  const uint8_t kInputEncrypted[] = {
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  };
  // This is arbitrary. Just used to check that this value is output from the
  // method.
  const uint8_t kFakeOutputData[] = {
      // clear 16 bytes.
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
      // decrypted 16 bytes.
      15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
      // clear 5 bytes.
      0, 1, 2, 3, 4,
      // decrypted 16 bytes.
      15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
  };
  const uint8_t kFakeDecryptedData[] = {
      15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
      15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
  };
  // clang-format on
  static_assert(base::size(kFakeOutputData) == base::size(kInput),
                "Fake input and output data size must match.");
  const std::vector<SubsampleEntry> subsamples = {SubsampleEntry(16, 16),
                                                  SubsampleEntry(5, 16)};

  ComPtr<D3D11CryptoSessionMock> crypto_session_mock =
      CreateD3D11Mock<D3D11CryptoSessionMock>();
  CdmProxyContext::D3D11DecryptContext decrypt_context =
      TestDecryptContext(crypto_session_mock);

  SetExpectationsForSuccessfulBufferInitialization(crypto_session_mock.Get(),
                                                   &decrypt_context);
  ExpectSuccessfulDecryption(crypto_session_mock.Get(), kInput, kInputEncrypted,
                             kFakeOutputData, kFakeDecryptedData, subsamples,
                             decryptor_.get());
}

// Verify that if the input is too big, it fails. This may be removed if the
// implementation supports big input.
TEST_F(D3D11DecryptorTest, DecryptInputTooBig) {
  // Something pretty big to be an audio frame. The actual data size doesn't
  // matter.
  std::array<uint8_t, 1000000> kInput;
  const SubsampleEntry kSubsample(0, base::size(kInput));

  ComPtr<D3D11CryptoSessionMock> crypto_session_mock =
      CreateD3D11Mock<D3D11CryptoSessionMock>();
  CdmProxyContext::D3D11DecryptContext decrypt_context =
      TestDecryptContext(crypto_session_mock);

  SetExpectationsForSuccessfulBufferInitialization(crypto_session_mock.Get(),
                                                   &decrypt_context);
  CallbackMock callbacks;
  EXPECT_CALL(callbacks, DecryptCallback(Decryptor::kError, IsNull()));

  scoped_refptr<DecoderBuffer> encrypted_buffer = TestDecoderBuffer(
      kInput.data(), base::size(kInput), kKeyId, kIv, {kSubsample});
  decryptor_->Decrypt(Decryptor::kAudio, encrypted_buffer,
                      base::BindRepeating(&CallbackMock::DecryptCallback,
                                          base::Unretained(&callbacks)));
}

// If there is no decrypt config, it must be in the clear, so it shouldn't
// change the output.
TEST_F(D3D11DecryptorTest, NoDecryptConfig) {
  scoped_refptr<DecoderBuffer> clear_buffer =
      DecoderBuffer::CopyFrom(kAnyInput, base::size(kAnyInput));
  clear_buffer->set_timestamp(kTestTimestamp);
  CallbackMock callbacks;
  EXPECT_CALL(
      callbacks,
      DecryptCallback(Decryptor::kSuccess,
                      OutputDataEquals(kAnyInput, base::size(kAnyInput))));
  decryptor_->Decrypt(Decryptor::kAudio, clear_buffer,
                      base::BindRepeating(&CallbackMock::DecryptCallback,
                                          base::Unretained(&callbacks)));
}

// The current decryptor cannot deal with pattern encryption.
TEST_F(D3D11DecryptorTest, PatternDecryption) {
  scoped_refptr<DecoderBuffer> encrypted_buffer =
      DecoderBuffer::CopyFrom(kAnyInput, base::size(kAnyInput));
  encrypted_buffer->set_decrypt_config(DecryptConfig::CreateCbcsConfig(
      kKeyId, kIv, {kAnyInputSubsample}, EncryptionPattern(1, 9)));

  CallbackMock callbacks;
  EXPECT_CALL(callbacks, DecryptCallback(Decryptor::kError, IsNull()));
  decryptor_->Decrypt(Decryptor::kAudio, encrypted_buffer,
                      base::BindRepeating(&CallbackMock::DecryptCallback,
                                          base::Unretained(&callbacks)));
}

// If there is no decrypt context, it's missing a key.
TEST_F(D3D11DecryptorTest, NoDecryptContext) {
  scoped_refptr<DecoderBuffer> encrypted_buffer = TestDecoderBuffer(
      kAnyInput, base::size(kAnyInput), kKeyId, kIv, {kAnyInputSubsample});

  EXPECT_CALL(mock_proxy_,
              GetD3D11DecryptContext(CdmProxy::KeyType::kDecryptOnly, kKeyId))
      .WillOnce(Return(base::nullopt));

  CallbackMock callbacks;
  EXPECT_CALL(callbacks, DecryptCallback(Decryptor::kNoKey, IsNull()));
  decryptor_->Decrypt(Decryptor::kAudio, encrypted_buffer,
                      base::BindRepeating(&CallbackMock::DecryptCallback,
                                          base::Unretained(&callbacks)));
}

// Verify that if the crypto session's device is the same as the previous call,
// the buffers aren't recreated.
TEST_F(D3D11DecryptorTest, ReuseBuffers) {
  ComPtr<D3D11CryptoSessionMock> crypto_session_mock =
      CreateD3D11Mock<D3D11CryptoSessionMock>();
  CdmProxyContext::D3D11DecryptContext decrypt_context =
      TestDecryptContext(crypto_session_mock);

  SetExpectationsForSuccessfulBufferInitialization(crypto_session_mock.Get(),
                                                   &decrypt_context);

  // This test doesn't require checking the output or the correctness of the
  // decyrption, so just pass the input buffer for output.
  ExpectSuccessfulDecryption(crypto_session_mock.Get(), kAnyInput, kAnyInput,
                             kAnyInput, kAnyInput, {kAnyInputSubsample},
                             decryptor_.get());
  Mock::VerifyAndClearExpectations(crypto_session_mock.Get());
  Mock::VerifyAndClearExpectations(device_mock_.Get());
  Mock::VerifyAndClearExpectations(video_context_mock_.Get());
  Mock::VerifyAndClearExpectations(device_context_mock_.Get());
  Mock::VerifyAndClearExpectations(&mock_proxy_);

  COM_EXPECT_CALL(crypto_session_mock, GetDevice(_))
      .Times(AtLeast(1))
      .WillRepeatedly(SetComPointee<0>(device_mock_.Get()));
  EXPECT_CALL(mock_proxy_,
              GetD3D11DecryptContext(CdmProxy::KeyType::kDecryptOnly, kKeyId))
      .WillOnce(Return(decrypt_context));

  // Buffers should not be (re)initialized on the next call to decrypt because
  // it's the same device as the previous call.
  COM_EXPECT_CALL(device_mock_, CreateBuffer(_, _, _)).Times(0);

  // This calls Decrypt() so that the expectations above are triggered.
  ExpectSuccessfulDecryption(crypto_session_mock.Get(), kAnyInput, kAnyInput,
                             kAnyInput, kAnyInput, {kAnyInputSubsample},
                             decryptor_.get());
}

}  // namespace media
