tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WMFClearKeyCDM.h (9443B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifndef DOM_MEDIA_PLATFORM_WMF_CLEARKEY_WMFCLEARKEYCDM_H
      6 #define DOM_MEDIA_PLATFORM_WMF_CLEARKEY_WMFCLEARKEYCDM_H
      7 
      8 #include <mfidl.h>
      9 #include <unordered_map>
     10 #include <variant>
     11 #include <windows.h>
     12 #include <windows.media.protection.h>
     13 #include <wrl.h>
     14 #include <wrl/client.h>
     15 
     16 #include "ClearKeySessionManager.h"
     17 #include "MFCDMExtra.h"
     18 #include "WMFClearKeyUtils.h"
     19 #include "content_decryption_module.h"
     20 
     21 namespace mozilla {
     22 
     23 class SessionManagerWrapper;
     24 class WMFClearKeySession;
     25 
     26 // This our customized MFCDM for supporting clearkey in our testing. It would
     27 // use ClearKeySessionManager via SessionManagerWrapper to perform decryption.
     28 class WMFClearKeyCDM final
     29    : public Microsoft::WRL::RuntimeClass<
     30          Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
     31          IMFContentDecryptionModule, IMFGetService, IMFShutdown,
     32          Microsoft::WRL::FtmBase> {
     33 public:
     34  WMFClearKeyCDM() = default;
     35  ~WMFClearKeyCDM();
     36  WMFClearKeyCDM(const WMFClearKeyCDM&) = delete;
     37  WMFClearKeyCDM& operator=(const WMFClearKeyCDM&) = delete;
     38 
     39  HRESULT RuntimeClassInitialize(IPropertyStore* aProperties);
     40 
     41  // IMFContentDecryptionModule
     42  STDMETHODIMP SetContentEnabler(IMFContentEnabler* aContentEnabler,
     43                                 IMFAsyncResult* aResult) override;
     44  STDMETHODIMP GetSuspendNotify(IMFCdmSuspendNotify** aNotify) override;
     45  STDMETHODIMP SetPMPHostApp(IMFPMPHostApp* aPmpHostApp) override;
     46  STDMETHODIMP CreateSession(
     47      MF_MEDIAKEYSESSION_TYPE aSessionType,
     48      IMFContentDecryptionModuleSessionCallbacks* aCallbacks,
     49      IMFContentDecryptionModuleSession** aSession) override;
     50  STDMETHODIMP SetServerCertificate(const BYTE* aCertificate,
     51                                    DWORD aCertificateSize) override;
     52  STDMETHODIMP CreateTrustedInput(const BYTE* aContentInitData,
     53                                  DWORD aContentInitDataSize,
     54                                  IMFTrustedInput** aTrustedInput) override;
     55  STDMETHODIMP GetProtectionSystemIds(GUID** aSystemIds,
     56                                      DWORD* aCount) override;
     57  // IMFGetService
     58  STDMETHODIMP GetService(REFGUID aGuidService, REFIID aRiid,
     59                          LPVOID* aPpvObject) override;
     60 
     61  // IMFShutdown
     62  STDMETHODIMP Shutdown() override;
     63  STDMETHODIMP GetShutdownStatus(MFSHUTDOWN_STATUS* aStatus) override;
     64 
     65 private:
     66  RefPtr<SessionManagerWrapper> mSessionManager;
     67  Microsoft::WRL::ComPtr<
     68      ABI::Windows::Media::Protection::IMediaProtectionPMPServer>
     69      mPMPServer;
     70 };
     71 
     72 // In order to reuse existing Gecko clearkey implementation, we need to
     73 // inherit the class `cdm::Host_11`.
     74 // TODO : add a way to assert thread usage. It would be used on MF thread pool
     75 // and the media supervisor thread pool.
     76 class SessionManagerWrapper final : public RefCounted, private cdm::Host_11 {
     77 public:
     78  explicit SessionManagerWrapper(WMFClearKeyCDM* aCDM);
     79 
     80  HRESULT GenerateRequest(cdm::InitDataType aInitDataType,
     81                          const BYTE* aInitData, DWORD aInitDataSize,
     82                          cdm::SessionType aSessionType,
     83                          WMFClearKeySession* aSession,
     84                          std::string& aSessionIdOut);
     85  HRESULT UpdateSession(const std::string& aSessionId, const BYTE* aResponse,
     86                        DWORD aResponseSize);
     87  HRESULT CloseSession(const std::string& aSessionId);
     88  HRESULT RemoveSession(const std::string& aSessionId);
     89  HRESULT Decrypt(const cdm::InputBuffer_2& aBuffer,
     90                  cdm::DecryptedBlock* aDecryptedBlock);
     91 
     92  void Shutdown();
     93  bool IsShutdown();
     94 
     95 private:
     96  ~SessionManagerWrapper();
     97  // cdm::Host_11
     98  void OnInitialized(bool aSuccess) override {}
     99  void OnResolveKeyStatusPromise(uint32_t aPromiseId,
    100                                 cdm::KeyStatus aKeyStatus) override {}
    101  void OnResolveNewSessionPromise(uint32_t aPromiseId, const char* aSessionId,
    102                                  uint32_t aSessionIdSize) override;
    103  void OnResolvePromise(uint32_t aPromiseId) override;
    104  void OnRejectPromise(uint32_t aPromiseId, cdm::Exception aException,
    105                       uint32_t aSystemCode, const char* aErrorMessage,
    106                       uint32_t aErrorMessageSize) override;
    107  void OnSessionMessage(const char* aSessionId, uint32_t aSessionIdSize,
    108                        cdm::MessageType aMessageType, const char* aMessage,
    109                        uint32_t aMessageSize) override;
    110  void OnSessionKeysChange(const char* aSessionId, uint32_t aSessionIdSize,
    111                           bool aHasAdditionalUsableKey,
    112                           const cdm::KeyInformation* aKeysInfo,
    113                           uint32_t aKeysInfoCount) override;
    114  void OnExpirationChange(const char* aSessionId, uint32_t aSessionIdSize,
    115                          cdm::Time aNewExpiryTime) override {
    116    // No need to implement this because the session would never expire in
    117    // testing.
    118  };
    119  void OnSessionClosed(const char* aSessionId,
    120                       uint32_t aSessionIdSize) override {
    121    // No need to implement this because session doesn't have close callback
    122    // or events.
    123  };
    124  cdm::FileIO* CreateFileIO(cdm::FileIOClient* aClient) override {
    125    // We don't support this because we only support temporary session.
    126    return nullptr;
    127  }
    128  void SendPlatformChallenge(const char* aServiceId, uint32_t aServiceIdSize,
    129                             const char* aChallenge,
    130                             uint32_t aChallengeSize) override {}
    131  void EnableOutputProtection(uint32_t aDesiredProtectionMask) override {}
    132  void QueryOutputProtectionStatus() override {};
    133  void OnDeferredInitializationDone(cdm::StreamType aStreamType,
    134                                    cdm::Status aDecoderStatus) override {}
    135  void RequestStorageId(uint32_t aVersion) override {}
    136  void ReportMetrics(cdm::MetricName aMetricName, uint64_t aValue) override {}
    137  cdm::Buffer* Allocate(uint32_t aCapacity) override;
    138  void SetTimer(int64_t aDelayMs, void* aContext) override {}
    139  cdm::Time GetCurrentWallTime() override { return 0.0; }
    140  friend class SessionManager;
    141 
    142  Microsoft::WRL::ComPtr<WMFClearKeyCDM> mOwnerCDM;
    143  RefPtr<ClearKeySessionManager> mSessionManager;
    144  std::unordered_map<std::string, Microsoft::WRL::ComPtr<WMFClearKeySession>>
    145      mSessions;
    146 
    147  // This is a RAII helper class to use ClearKeySessionManager::XXXSession
    148  // methods in a sync style, which is what MFCDM is required.
    149  // ClearKeySessionManager uses cdm::Host_11's OnResolve/RejectXXX as callback
    150  // to report whether those function calls relatd with specific promise id
    151  // succeed or not. As we only do temporary session for ClearKey testing, we
    152  // don't need to wait to setup the storage so calling those XXXsession
    153  // functions are actully a sync process. We guarantee that
    154  // ClearKeySessionManager will use OnResolve/Reject methods to notify us
    155  // result, right after we calling the session related method.
    156  // [How to to use this class, not thread-safe]
    157  //   1. create it on the stack
    158  //   2. use GetPromiseId() to generate a fake promise id for tracking
    159  //   3. in cdm::Host_11's callback function, check promise id to know what
    160  //      result needs to be set
    161  //   4. check result to see if the session method succeed or not
    162  class SyncResultChecker final {
    163   public:
    164    using ResultType = std::variant<const char*, bool>;
    165    explicit SyncResultChecker(SessionManagerWrapper& aOwner)
    166        : mOwner(aOwner), mIdx(sIdx++), mKeySession(nullptr) {
    167      mOwner.mActiveSyncResultChecker.insert({mIdx, this});
    168    }
    169    SyncResultChecker(SessionManagerWrapper& aOwner,
    170                      WMFClearKeySession* aKeySession)
    171        : mOwner(aOwner), mIdx(sIdx++), mKeySession(aKeySession) {
    172      mOwner.mActiveSyncResultChecker.insert({mIdx, this});
    173    }
    174    ~SyncResultChecker() { mOwner.mActiveSyncResultChecker.erase(mIdx); }
    175    uint32_t GetPromiseId() const { return mIdx; }
    176    const ResultType& GetResult() const { return mResult; }
    177    WMFClearKeySession* GetKeySession() const { return mKeySession; }
    178 
    179   private:
    180    // Only allow setting result from these callbacks.
    181    friend void SessionManagerWrapper::OnResolveNewSessionPromise(uint32_t,
    182                                                                  const char*,
    183                                                                  uint32_t);
    184    friend void SessionManagerWrapper::OnResolvePromise(uint32_t);
    185    friend void SessionManagerWrapper::OnRejectPromise(uint32_t, cdm::Exception,
    186                                                       uint32_t, const char*,
    187                                                       uint32_t);
    188    void SetResultConstChar(const char* aResult) {
    189      mResult.emplace<const char*>(aResult);
    190    }
    191    void SetResultBool(bool aResult) { mResult.emplace<bool>(aResult); }
    192 
    193    static inline uint32_t sIdx = 0;
    194    SessionManagerWrapper& mOwner;
    195    const uint32_t mIdx;
    196    ResultType mResult;
    197    WMFClearKeySession* const mKeySession;
    198  };
    199  std::unordered_map<uint32_t, SyncResultChecker*> mActiveSyncResultChecker;
    200 
    201  // Protect following members.
    202  std::mutex mMutex;
    203  bool mIsShutdown = false;
    204 };
    205 
    206 }  // namespace mozilla
    207 
    208 #endif  // DOM_MEDIA_PLATFORM_WMF_CLEARKEY_WMFCLEARKEYCDM_H