1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129

media / cdm / library_cdm / clear_key_cdm / clear_key_persistent_session_cdm.h [blame]

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

#ifndef MEDIA_CDM_LIBRARY_CDM_CLEAR_KEY_CDM_CLEAR_KEY_PERSISTENT_SESSION_CDM_H_
#define MEDIA_CDM_LIBRARY_CDM_CLEAR_KEY_CDM_CLEAR_KEY_PERSISTENT_SESSION_CDM_H_

#include <stdint.h>

#include <memory>
#include <set>
#include <string>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "media/base/content_decryption_module.h"
#include "media/cdm/aes_decryptor.h"
#include "media/cdm/library_cdm/cdm_host_proxy.h"
#include "media/cdm/library_cdm/clear_key_cdm/cdm_file_adapter.h"

namespace media {

// This class is a wrapper on top of AesDecryptor that supports persistent
// sessions. LoadSession(), UpdateSession(), and RemoveSession() have
// special handling.
class ClearKeyPersistentSessionCdm : public ContentDecryptionModule {
 public:
  ClearKeyPersistentSessionCdm(
      CdmHostProxy* cdm_host_proxy,
      const SessionMessageCB& session_message_cb,
      const SessionClosedCB& session_closed_cb,
      const SessionKeysChangeCB& session_keys_change_cb,
      const SessionExpirationUpdateCB& session_expiration_update_cb);

  ClearKeyPersistentSessionCdm(const ClearKeyPersistentSessionCdm&) = delete;
  ClearKeyPersistentSessionCdm& operator=(const ClearKeyPersistentSessionCdm&) =
      delete;

  // ContentDecryptionModule implementation.
  void SetServerCertificate(const std::vector<uint8_t>& certificate,
                            std::unique_ptr<SimpleCdmPromise> promise) override;
  void CreateSessionAndGenerateRequest(
      CdmSessionType session_type,
      EmeInitDataType init_data_type,
      const std::vector<uint8_t>& init_data,
      std::unique_ptr<NewSessionCdmPromise> promise) override;
  void LoadSession(CdmSessionType session_type,
                   const std::string& session_id,
                   std::unique_ptr<NewSessionCdmPromise> promise) override;
  void UpdateSession(const std::string& session_id,
                     const std::vector<uint8_t>& response,
                     std::unique_ptr<SimpleCdmPromise> promise) override;
  void CloseSession(const std::string& session_id,
                    std::unique_ptr<SimpleCdmPromise> promise) override;
  void RemoveSession(const std::string& session_id,
                     std::unique_ptr<SimpleCdmPromise> promise) override;
  CdmContext* GetCdmContext() override;

 private:
  ~ClearKeyPersistentSessionCdm() override;

  // When LoadSession() is called, first open and read the session state.
  // Then call |cdm_| to create the session with the state provided.
  void OnFileOpenedForLoadSession(const std::string& session_id,
                                  std::unique_ptr<CdmFileAdapter> file,
                                  std::unique_ptr<NewSessionCdmPromise> promise,
                                  CdmFileAdapter::Status status);
  void OnFileReadForLoadSession(const std::string& session_id,
                                std::unique_ptr<CdmFileAdapter> file,
                                std::unique_ptr<NewSessionCdmPromise> promise,
                                bool success,
                                const std::vector<uint8_t>& data);

  // When UpdateSession() is called (on a persistent session), save the
  // current session state after it's been updated.
  void OnFileOpenedForUpdateSession(const std::string& session_id,
                                    bool key_added,
                                    std::unique_ptr<CdmFileAdapter> file,
                                    std::unique_ptr<SimpleCdmPromise> promise,
                                    CdmFileAdapter::Status status);
  void OnFileWrittenForUpdateSession(const std::string& session_id,
                                     bool key_added,
                                     std::unique_ptr<CdmFileAdapter> file,
                                     std::unique_ptr<SimpleCdmPromise> promise,
                                     bool success);

  // When RemoveSession() is called (on a persistent session), delete the
  // file (by writing 0 bytes) and then call |cdm_| to actually remove the
  // session from memory.
  void OnFileOpenedForRemoveSession(const std::string& session_id,
                                    std::unique_ptr<CdmFileAdapter> file,
                                    std::unique_ptr<SimpleCdmPromise> promise,
                                    CdmFileAdapter::Status status);
  void OnFileWrittenForRemoveSession(const std::string& session_id,
                                     std::unique_ptr<CdmFileAdapter> file,
                                     std::unique_ptr<SimpleCdmPromise> promise,
                                     bool success);

  // Add |session_id| to the list of open persistent sessions.
  void AddPersistentSession(const std::string& session_id);

  // When the session is closed, remove it from the list of open persistent
  // sessions if it was a persistent session.
  void OnSessionClosed(const std::string& session_id,
                       CdmSessionClosedReason reason);

  void OnSessionMessage(const std::string& session_id,
                        CdmMessageType message_type,
                        const std::vector<uint8_t>& message);

  scoped_refptr<AesDecryptor> cdm_;
  const raw_ptr<CdmHostProxy> cdm_host_proxy_ = nullptr;

  // Callbacks for firing session events. Other events aren't intercepted.
  SessionMessageCB session_message_cb_;
  SessionClosedCB session_closed_cb_;

  // Keep track of current open persistent sessions.
  std::set<std::string> persistent_sessions_;

  // NOTE: Weak pointers must be invalidated before all other member variables.
  base::WeakPtrFactory<ClearKeyPersistentSessionCdm> weak_factory_{this};
};

}  // namespace media

#endif  // MEDIA_CDM_LIBRARY_CDM_CLEAR_KEY_CDM_CLEAR_KEY_PERSISTENT_SESSION_CDM_H_