// Copyright 2020 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/cdm/win/media_foundation_cdm_factory.h"

#include <combaseapi.h>
#include <initguid.h>  // Needed for DEFINE_PROPERTYKEY to work properly.
#include <mferror.h>
#include <mfmediaengine.h>
#include <propkeydef.h>  // Needed for DEFINE_PROPERTYKEY.
#include <propvarutil.h>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/files/file_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/thread_pool.h"
#include "base/win/scoped_propvariant.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/cdm_config.h"
#include "media/base/win/mf_helpers.h"
#include "media/cdm/cdm_paths.h"
#include "media/cdm/win/media_foundation_cdm.h"
#include "media/cdm/win/media_foundation_cdm_module.h"

namespace media {

namespace {

using Microsoft::WRL::ComPtr;

// Key to the CDM Origin ID to be passed to the CDM for privacy purposes. The
// same value is also used in MediaFoundation CDMs. Do NOT change this value!
DEFINE_PROPERTYKEY(EME_CONTENTDECRYPTIONMODULE_ORIGIN_ID,
                   0x1218a3e2,
                   0xcfb0,
                   0x4c98,
                   0x90,
                   0xe5,
                   0x5f,
                   0x58,
                   0x18,
                   0xd4,
                   0xb6,
                   0x7e,
                   PID_FIRST_USABLE);

void SetBSTR(const wchar_t* str, PROPVARIANT* propvariant) {
  propvariant->vt = VT_BSTR;
  propvariant->bstrVal = SysAllocString(str);
}

// Returns a property store similar to EME MediaKeySystemMediaCapability.
HRESULT CreateVideoCapability(const CdmConfig& cdm_config,
                              ComPtr<IPropertyStore>& video_capability) {
  ComPtr<IPropertyStore> temp_video_capability;
  RETURN_IF_FAILED(
      PSCreateMemoryPropertyStore(IID_PPV_ARGS(&temp_video_capability)));

  base::win::ScopedPropVariant robustness;
  if (cdm_config.use_hw_secure_codecs) {
    // TODO(xhwang): Provide a way to support other robustness strings.
    SetBSTR(L"HW_SECURE_ALL", robustness.Receive());
    RETURN_IF_FAILED(
        temp_video_capability->SetValue(MF_EME_ROBUSTNESS, robustness.get()));
  }
  video_capability = temp_video_capability;
  return S_OK;
}

// Returns a property store similar to EME MediaKeySystemConfigurations.
// What really matters here are video robustness, persistent state and
// distinctive identifier.
HRESULT BuildCdmAccessConfigurations(const CdmConfig& cdm_config,
                                     ComPtr<IPropertyStore>& configurations) {
  ComPtr<IPropertyStore> temp_configurations;

  RETURN_IF_FAILED(
      PSCreateMemoryPropertyStore(IID_PPV_ARGS(&temp_configurations)));

  // Add an empty audio capability.
  base::win::ScopedPropVariant audio_capabilities;
  PROPVARIANT* var_to_set = audio_capabilities.Receive();
  var_to_set->vt = VT_VARIANT | VT_VECTOR;
  var_to_set->capropvar.cElems = 0;
  RETURN_IF_FAILED(temp_configurations->SetValue(MF_EME_AUDIOCAPABILITIES,
                                                 audio_capabilities.get()));

  // Add a video capability so we can pass the correct robustness level.
  ComPtr<IPropertyStore> video_capability;
  RETURN_IF_FAILED(CreateVideoCapability(cdm_config, video_capability));

  base::win::ScopedPropVariant video_config;
  auto* video_config_ptr = video_config.Receive();
  video_config_ptr->vt = VT_UNKNOWN;
  video_config_ptr->punkVal = video_capability.Detach();

  base::win::ScopedPropVariant video_capabilities;
  var_to_set = video_capabilities.Receive();
  var_to_set->vt = VT_VARIANT | VT_VECTOR;
  var_to_set->capropvar.cElems = 1;
  var_to_set->capropvar.pElems =
      reinterpret_cast<PROPVARIANT*>(CoTaskMemAlloc(sizeof(PROPVARIANT)));
  PropVariantCopy(var_to_set->capropvar.pElems, video_config.ptr());
  RETURN_IF_FAILED(temp_configurations->SetValue(MF_EME_VIDEOCAPABILITIES,
                                                 video_capabilities.get()));

  // Add persistent state.
  DCHECK(cdm_config.allow_persistent_state);
  base::win::ScopedPropVariant persisted_state;
  RETURN_IF_FAILED(InitPropVariantFromUInt32(MF_MEDIAKEYS_REQUIREMENT_REQUIRED,
                                             persisted_state.Receive()));
  RETURN_IF_FAILED(temp_configurations->SetValue(MF_EME_PERSISTEDSTATE,
                                                 persisted_state.get()));

  // Add distinctive identifier.
  DCHECK(cdm_config.allow_distinctive_identifier);
  base::win::ScopedPropVariant distinctive_identifier;
  RETURN_IF_FAILED(InitPropVariantFromUInt32(MF_MEDIAKEYS_REQUIREMENT_REQUIRED,
                                             distinctive_identifier.Receive()));
  RETURN_IF_FAILED(temp_configurations->SetValue(MF_EME_DISTINCTIVEID,
                                                 distinctive_identifier.get()));

  configurations = temp_configurations;
  return S_OK;
}

HRESULT BuildCdmProperties(
    const base::UnguessableToken& origin_id,
    const absl::optional<std::vector<uint8_t>>& client_token,
    const base::FilePath& store_path,
    ComPtr<IPropertyStore>& properties) {
  DCHECK(!origin_id.is_empty());

  ComPtr<IPropertyStore> temp_properties;
  RETURN_IF_FAILED(PSCreateMemoryPropertyStore(IID_PPV_ARGS(&temp_properties)));

  base::win::ScopedPropVariant origin_id_var;
  RETURN_IF_FAILED(InitPropVariantFromString(
      base::UTF8ToWide(origin_id.ToString()).c_str(), origin_id_var.Receive()));
  RETURN_IF_FAILED(temp_properties->SetValue(
      EME_CONTENTDECRYPTIONMODULE_ORIGIN_ID, origin_id_var.get()));

  if (client_token) {
    base::win::ScopedPropVariant client_token_var;
    PROPVARIANT* client_token_propvar = client_token_var.Receive();
    client_token_propvar->vt = VT_VECTOR | VT_UI1;
    client_token_propvar->caub.cElems = client_token->size();
    client_token_propvar->caub.pElems = reinterpret_cast<unsigned char*>(
        CoTaskMemAlloc(client_token->size() * sizeof(char)));
    memcpy(client_token_propvar->caub.pElems, client_token->data(),
           client_token->size());

    RETURN_IF_FAILED(temp_properties->SetValue(
        EME_CONTENTDECRYPTIONMODULE_CLIENT_TOKEN, client_token_var.get()));
  }

  base::win::ScopedPropVariant store_path_var;
  RETURN_IF_FAILED(InitPropVariantFromString(store_path.value().c_str(),
                                             store_path_var.Receive()));
  RETURN_IF_FAILED(temp_properties->SetValue(
      MF_CONTENTDECRYPTIONMODULE_STOREPATH, store_path_var.get()));

  properties = temp_properties;
  return S_OK;
}

bool IsTypeSupportedInternal(
    ComPtr<IMFContentDecryptionModuleFactory> cdm_factory,
    const std::string& key_system,
    const std::string& content_type) {
  return cdm_factory->IsTypeSupported(base::UTF8ToWide(key_system).c_str(),
                                      base::UTF8ToWide(content_type).c_str());
}

crash_reporter::CrashKeyString<256> g_origin_crash_key("cdm-origin");

}  // namespace

MediaFoundationCdmFactory::MediaFoundationCdmFactory(
    std::unique_ptr<CdmAuxiliaryHelper> helper)
    : helper_(std::move(helper)),
      cdm_origin_crash_key_(&g_origin_crash_key,
                            helper_->GetCdmOrigin().Serialize()) {}

MediaFoundationCdmFactory::~MediaFoundationCdmFactory() = default;

void MediaFoundationCdmFactory::SetCreateCdmFactoryCallbackForTesting(
    const std::string& key_system,
    CreateCdmFactoryCB create_cdm_factory_cb) {
  DCHECK(!create_cdm_factory_cbs_for_testing_.count(key_system));
  create_cdm_factory_cbs_for_testing_[key_system] =
      std::move(create_cdm_factory_cb);
}

void MediaFoundationCdmFactory::Create(
    const std::string& key_system,
    const CdmConfig& cdm_config,
    const SessionMessageCB& session_message_cb,
    const SessionClosedCB& session_closed_cb,
    const SessionKeysChangeCB& session_keys_change_cb,
    const SessionExpirationUpdateCB& session_expiration_update_cb,
    CdmCreatedCB cdm_created_cb) {
  DVLOG_FUNC(1) << "key_system=" << key_system;

  // IMFContentDecryptionModule CDMs typically require persistent storage and
  // distinctive identifier and this should be guaranteed by key system support
  // code. Update this if there are new CDMs that doesn't require these.
  DCHECK(cdm_config.allow_persistent_state);
  DCHECK(cdm_config.allow_distinctive_identifier);

  // Don't cache `cdm_origin_id` in this class since user can clear it any time.
  helper_->GetMediaFoundationCdmData(base::BindOnce(
      &MediaFoundationCdmFactory::OnCdmOriginIdObtained,
      weak_factory_.GetWeakPtr(), key_system, cdm_config, session_message_cb,
      session_closed_cb, session_keys_change_cb, session_expiration_update_cb,
      std::move(cdm_created_cb)));
}

void MediaFoundationCdmFactory::OnCdmOriginIdObtained(
    const std::string& key_system,
    const CdmConfig& cdm_config,
    const SessionMessageCB& session_message_cb,
    const SessionClosedCB& session_closed_cb,
    const SessionKeysChangeCB& session_keys_change_cb,
    const SessionExpirationUpdateCB& session_expiration_update_cb,
    CdmCreatedCB cdm_created_cb,
    const std::unique_ptr<MediaFoundationCdmData> media_foundation_cdm_data) {
  if (!media_foundation_cdm_data) {
    std::move(cdm_created_cb)
        .Run(nullptr, "Failed to get the CDM preference data.");
    return;
  }

  if (media_foundation_cdm_data->origin_id.is_empty()) {
    std::move(cdm_created_cb).Run(nullptr, "Failed to get the CDM origin ID.");
    return;
  }

  auto cdm = base::MakeRefCounted<MediaFoundationCdm>(
      base::BindRepeating(&MediaFoundationCdmFactory::CreateMfCdm,
                          weak_factory_.GetWeakPtr(), key_system, cdm_config,
                          media_foundation_cdm_data->origin_id,
                          media_foundation_cdm_data->client_token,
                          media_foundation_cdm_data->cdm_store_path_root),
      base::BindRepeating(&MediaFoundationCdmFactory::IsTypeSupported,
                          weak_factory_.GetWeakPtr(), key_system),
      base::BindRepeating(&MediaFoundationCdmFactory::StoreClientToken,
                          weak_factory_.GetWeakPtr()),
      session_message_cb, session_closed_cb, session_keys_change_cb,
      session_expiration_update_cb);

  // `cdm_created_cb` should always be run asynchronously.
  auto bound_cdm_created_cb = BindToCurrentLoop(std::move(cdm_created_cb));

  if (FAILED(cdm->Initialize())) {
    std::move(bound_cdm_created_cb).Run(nullptr, "Failed to create CDM");
    return;
  }

  std::move(bound_cdm_created_cb).Run(cdm, "");
}

HRESULT MediaFoundationCdmFactory::GetCdmFactory(
    const std::string& key_system,
    Microsoft::WRL::ComPtr<IMFContentDecryptionModuleFactory>& cdm_factory) {
  // Use key system specific `create_cdm_factory_cb` if there's one registered.
  auto itr = create_cdm_factory_cbs_for_testing_.find(key_system);
  if (itr != create_cdm_factory_cbs_for_testing_.end()) {
    auto& create_cdm_factory_cb = itr->second;
    if (!create_cdm_factory_cb)
      return E_FAIL;

    RETURN_IF_FAILED(create_cdm_factory_cb.Run(cdm_factory));
    return S_OK;
  }

  // Otherwise, use the one in MediaFoundationCdmModule.
  RETURN_IF_FAILED(MediaFoundationCdmModule::GetInstance()->GetCdmFactory(
      key_system, cdm_factory));
  return S_OK;
}

void MediaFoundationCdmFactory::IsTypeSupported(
    const std::string& key_system,
    const std::string& content_type,
    IsTypeSupportedResultCB is_type_supported_result_cb) {
  ComPtr<IMFContentDecryptionModuleFactory> cdm_factory;
  HRESULT hr = GetCdmFactory(key_system, cdm_factory);
  if (FAILED(hr)) {
    DLOG(ERROR) << "Failed to GetCdmFactory. hr=" << hr;
    std::move(is_type_supported_result_cb).Run(false);
    return;
  }

  // Note that IsTypeSupported may take up to 10s, so run it on a separate
  // thread to unblock the main thread.
  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE,
      base::BindOnce(&IsTypeSupportedInternal, cdm_factory, key_system,
                     content_type),
      std::move(is_type_supported_result_cb));
}

void MediaFoundationCdmFactory::StoreClientToken(
    const std::vector<uint8_t>& client_token) {
  helper_->SetCdmClientToken(client_token);
}

HRESULT MediaFoundationCdmFactory::CreateMfCdmInternal(
    const std::string& key_system,
    const CdmConfig& cdm_config,
    const base::UnguessableToken& cdm_origin_id,
    const absl::optional<std::vector<uint8_t>>& cdm_client_token,
    const base::FilePath& cdm_store_path_root,
    ComPtr<IMFContentDecryptionModule>& mf_cdm) {
  ComPtr<IMFContentDecryptionModuleFactory> cdm_factory;
  RETURN_IF_FAILED(GetCdmFactory(key_system, cdm_factory));

  DCHECK(!cdm_origin_id.is_empty());

  auto key_system_str = base::UTF8ToWide(key_system);
  if (!cdm_factory->IsTypeSupported(key_system_str.c_str(), nullptr)) {
    DLOG(ERROR) << key_system << " not supported by MF CdmFactory";
    return MF_NOT_SUPPORTED_ERR;
  }

  ComPtr<IPropertyStore> property_store;
  RETURN_IF_FAILED(BuildCdmAccessConfigurations(cdm_config, property_store));

  IPropertyStore* configurations[] = {property_store.Get()};
  ComPtr<IMFContentDecryptionModuleAccess> cdm_access;
  RETURN_IF_FAILED(cdm_factory->CreateContentDecryptionModuleAccess(
      key_system_str.c_str(), configurations, ARRAYSIZE(configurations),
      &cdm_access));

  // Provide a per-user, per-arch, per-origin and per-key-system path.
  auto store_path =
      GetCdmStorePath(cdm_store_path_root, cdm_origin_id, key_system);
  DVLOG(1) << "store_path=" << store_path;

  // Ensure the path exists. If it already exists, this call will do nothing.
  base::File::Error file_error;
  if (!base::CreateDirectoryAndGetError(store_path, &file_error)) {
    DLOG(ERROR) << "Create CDM store path failed with " << file_error;
    return E_FAIL;
  }

  ComPtr<IPropertyStore> cdm_properties;
  ComPtr<IMFContentDecryptionModule> cdm;
  RETURN_IF_FAILED(BuildCdmProperties(cdm_origin_id, cdm_client_token,
                                      store_path, cdm_properties));
  RETURN_IF_FAILED(
      cdm_access->CreateContentDecryptionModule(cdm_properties.Get(), &cdm));

  mf_cdm.Swap(cdm);
  return S_OK;
}

void MediaFoundationCdmFactory::CreateMfCdm(
    const std::string& key_system,
    const CdmConfig& cdm_config,
    const base::UnguessableToken& cdm_origin_id,
    const absl::optional<std::vector<uint8_t>>& cdm_client_token,
    const base::FilePath& cdm_store_path_root,
    HRESULT& hresult,
    Microsoft::WRL::ComPtr<IMFContentDecryptionModule>& mf_cdm) {
  hresult = CreateMfCdmInternal(key_system, cdm_config, cdm_origin_id,
                                cdm_client_token, cdm_store_path_root, mf_cdm);
}

}  // namespace media
