icecat: update to upstream version 128.0.14-1gnu1
This commit is contained in:
parent
0cdda4f34e
commit
56c3deff60
77 changed files with 8997 additions and 3862 deletions
|
|
@ -7,7 +7,6 @@
|
|||
#include "GLContext.h"
|
||||
#include "ImageBitmapRenderingContext.h"
|
||||
#include "ImageEncoder.h"
|
||||
#include "mozilla/dom/BlobImpl.h"
|
||||
#include "mozilla/dom/CanvasRenderingContext2D.h"
|
||||
#include "mozilla/dom/OffscreenCanvasRenderingContext2D.h"
|
||||
#include "mozilla/GfxMessageUtils.h"
|
||||
|
|
@ -26,55 +25,6 @@ namespace mozilla::dom {
|
|||
CanvasRenderingContextHelper::CanvasRenderingContextHelper()
|
||||
: mCurrentContextType(CanvasContextType::NoContext) {}
|
||||
|
||||
void CanvasRenderingContextHelper::ToBlob(
|
||||
JSContext* aCx, nsIGlobalObject* aGlobal, BlobCallback& aCallback,
|
||||
const nsAString& aType, JS::Handle<JS::Value> aParams, bool aUsePlaceholder,
|
||||
ErrorResult& aRv) {
|
||||
// Encoder callback when encoding is complete.
|
||||
class EncodeCallback : public EncodeCompleteCallback {
|
||||
public:
|
||||
EncodeCallback(nsIGlobalObject* aGlobal, BlobCallback* aCallback)
|
||||
: mGlobal(aGlobal), mBlobCallback(aCallback) {}
|
||||
|
||||
// This is called on main thread.
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult ReceiveBlobImpl(already_AddRefed<BlobImpl> aBlobImpl) override {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<BlobImpl> blobImpl = aBlobImpl;
|
||||
|
||||
RefPtr<Blob> blob;
|
||||
|
||||
if (blobImpl) {
|
||||
blob = Blob::Create(mGlobal, blobImpl);
|
||||
}
|
||||
|
||||
RefPtr<BlobCallback> callback(std::move(mBlobCallback));
|
||||
ErrorResult rv;
|
||||
|
||||
callback->Call(blob, rv);
|
||||
|
||||
mGlobal = nullptr;
|
||||
MOZ_ASSERT(!mBlobCallback);
|
||||
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
bool CanBeDeletedOnAnyThread() override {
|
||||
// EncodeCallback is used from the main thread only.
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<BlobCallback> mBlobCallback;
|
||||
};
|
||||
|
||||
RefPtr<EncodeCompleteCallback> callback =
|
||||
new EncodeCallback(aGlobal, &aCallback);
|
||||
|
||||
ToBlob(aCx, callback, aType, aParams, aUsePlaceholder, aRv);
|
||||
}
|
||||
|
||||
void CanvasRenderingContextHelper::ToBlob(
|
||||
JSContext* aCx, EncodeCompleteCallback* aCallback, const nsAString& aType,
|
||||
JS::Handle<JS::Value> aParams, bool aUsePlaceholder, ErrorResult& aRv) {
|
||||
|
|
|
|||
|
|
@ -54,10 +54,6 @@ class CanvasRenderingContextHelper {
|
|||
nsAString& outParams,
|
||||
bool* const outCustomParseOptions);
|
||||
|
||||
void ToBlob(JSContext* aCx, nsIGlobalObject* global, BlobCallback& aCallback,
|
||||
const nsAString& aType, JS::Handle<JS::Value> aParams,
|
||||
bool aUsePlaceholder, ErrorResult& aRv);
|
||||
|
||||
void ToBlob(JSContext* aCx, EncodeCompleteCallback* aCallback,
|
||||
const nsAString& aType, JS::Handle<JS::Value> aParams,
|
||||
bool aUsePlaceholder, ErrorResult& aRv);
|
||||
|
|
|
|||
|
|
@ -570,6 +570,10 @@ void OffscreenCanvas::SetWriteOnly(RefPtr<nsIPrincipal>&& aExpandedReader) {
|
|||
mExpandedReader.forget());
|
||||
mExpandedReader = std::move(aExpandedReader);
|
||||
mIsWriteOnly = true;
|
||||
|
||||
if (mDisplay) {
|
||||
mDisplay->SetWriteOnly(mExpandedReader);
|
||||
}
|
||||
}
|
||||
|
||||
bool OffscreenCanvas::CallerCanRead(nsIPrincipal& aPrincipal) const {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,11 @@ OffscreenCanvasDisplayHelper::OffscreenCanvasDisplayHelper(
|
|||
mData.mSize.height = aHeight;
|
||||
}
|
||||
|
||||
OffscreenCanvasDisplayHelper::~OffscreenCanvasDisplayHelper() = default;
|
||||
OffscreenCanvasDisplayHelper::~OffscreenCanvasDisplayHelper() {
|
||||
MutexAutoLock lock(mMutex);
|
||||
NS_ReleaseOnMainThread("OffscreenCanvas::mExpandedReader",
|
||||
mExpandedReader.forget());
|
||||
}
|
||||
|
||||
void OffscreenCanvasDisplayHelper::DestroyElement() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
|
@ -61,6 +65,32 @@ void OffscreenCanvasDisplayHelper::DestroyCanvas() {
|
|||
mWorkerRef = nullptr;
|
||||
}
|
||||
|
||||
void OffscreenCanvasDisplayHelper::SetWriteOnly(nsIPrincipal* aExpandedReader) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
NS_ReleaseOnMainThread("OffscreenCanvasDisplayHelper::mExpandedReader",
|
||||
mExpandedReader.forget());
|
||||
mExpandedReader = aExpandedReader;
|
||||
mIsWriteOnly = true;
|
||||
}
|
||||
|
||||
bool OffscreenCanvasDisplayHelper::CallerCanRead(
|
||||
nsIPrincipal& aPrincipal) const {
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (!mIsWriteOnly) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If mExpandedReader is set, this canvas was tainted only by
|
||||
// mExpandedReader's resources. So allow reading if the subject
|
||||
// principal subsumes mExpandedReader.
|
||||
if (mExpandedReader && aPrincipal.Subsumes(mExpandedReader)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return nsContentUtils::PrincipalHasPermission(aPrincipal,
|
||||
nsGkAtoms::all_urlsPermission);
|
||||
}
|
||||
|
||||
bool OffscreenCanvasDisplayHelper::CanElementCaptureStream() const {
|
||||
MutexAutoLock lock(mMutex);
|
||||
return !!mWorkerRef;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,19 @@ class OffscreenCanvasDisplayHelper final {
|
|||
void DestroyCanvas();
|
||||
void DestroyElement();
|
||||
|
||||
bool IsWriteOnly() const {
|
||||
MutexAutoLock lock(mMutex);
|
||||
return mIsWriteOnly;
|
||||
}
|
||||
|
||||
bool HasWorkerRef() const {
|
||||
MutexAutoLock lock(mMutex);
|
||||
return !!mWorkerRef;
|
||||
}
|
||||
|
||||
void SetWriteOnly(nsIPrincipal* aExpandedReader = nullptr);
|
||||
bool CallerCanRead(nsIPrincipal& aPrincipal) const;
|
||||
|
||||
bool CanElementCaptureStream() const;
|
||||
bool UsingElementCaptureStream() const;
|
||||
|
||||
|
|
@ -90,6 +103,8 @@ class OffscreenCanvasDisplayHelper final {
|
|||
mozilla::layers::ImageContainer::FrameID mLastFrameID MOZ_GUARDED_BY(mMutex) =
|
||||
0;
|
||||
bool mPendingInvalidate MOZ_GUARDED_BY(mMutex) = false;
|
||||
bool mIsWriteOnly MOZ_GUARDED_BY(mMutex) = false;
|
||||
RefPtr<nsIPrincipal> mExpandedReader MOZ_GUARDED_BY(mMutex);
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/dom/BlobImpl.h"
|
||||
#include "mozilla/dom/CanvasCaptureMediaStream.h"
|
||||
#include "mozilla/dom/CanvasRenderingContext2D.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
|
|
@ -768,16 +769,26 @@ void HTMLCanvasElement::ToDataURL(JSContext* aCx, const nsAString& aType,
|
|||
nsAString& aDataURL,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv) {
|
||||
// mWriteOnly check is redundant, but optimizes for the common case.
|
||||
if (mWriteOnly && !CallerCanRead(aSubjectPrincipal)) {
|
||||
bool recheckCanRead = mOffscreenDisplay && mOffscreenDisplay->HasWorkerRef();
|
||||
|
||||
if (!CallerCanRead(aSubjectPrincipal)) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = ToDataURLImpl(aCx, aSubjectPrincipal, aType, aParams, aDataURL);
|
||||
if (NS_FAILED(rv)) {
|
||||
aDataURL.AssignLiteral("data:,");
|
||||
nsString dataURL;
|
||||
nsresult rv = ToDataURLImpl(aCx, aSubjectPrincipal, aType, aParams, dataURL);
|
||||
if (recheckCanRead && !CallerCanRead(aSubjectPrincipal)) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
aDataURL.Assign(u"data:,"_ns);
|
||||
return;
|
||||
}
|
||||
|
||||
aDataURL = std::move(dataURL);
|
||||
}
|
||||
|
||||
void HTMLCanvasElement::SetMozPrintCallback(PrintCallback* aCallback) {
|
||||
|
|
@ -993,8 +1004,9 @@ void HTMLCanvasElement::ToBlob(JSContext* aCx, BlobCallback& aCallback,
|
|||
JS::Handle<JS::Value> aParams,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv) {
|
||||
// mWriteOnly check is redundant, but optimizes for the common case.
|
||||
if (mWriteOnly && !CallerCanRead(aSubjectPrincipal)) {
|
||||
bool recheckCanRead = mOffscreenDisplay && mOffscreenDisplay->HasWorkerRef();
|
||||
|
||||
if (!CallerCanRead(aSubjectPrincipal)) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1019,7 +1031,59 @@ void HTMLCanvasElement::ToBlob(JSContext* aCx, BlobCallback& aCallback,
|
|||
// If no permission, return all-white, opaque image data.
|
||||
bool usePlaceholder = !CanvasUtils::IsImageExtractionAllowed(
|
||||
OwnerDoc(), aCx, aSubjectPrincipal);
|
||||
CanvasRenderingContextHelper::ToBlob(aCx, global, aCallback, aType, aParams,
|
||||
|
||||
// Encoder callback when encoding is complete.
|
||||
class EncodeCallback : public EncodeCompleteCallback {
|
||||
public:
|
||||
EncodeCallback(nsIGlobalObject* aGlobal, BlobCallback* aCallback,
|
||||
OffscreenCanvasDisplayHelper* aOffscreenDisplay,
|
||||
nsIPrincipal* aSubjectPrincipal)
|
||||
: mGlobal(aGlobal),
|
||||
mBlobCallback(aCallback),
|
||||
mOffscreenDisplay(aOffscreenDisplay),
|
||||
mSubjectPrincipal(aSubjectPrincipal) {}
|
||||
|
||||
// This is called on main thread.
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult ReceiveBlobImpl(already_AddRefed<BlobImpl> aBlobImpl) override {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<BlobImpl> blobImpl = aBlobImpl;
|
||||
|
||||
RefPtr<Blob> blob;
|
||||
|
||||
if (blobImpl && (!mOffscreenDisplay ||
|
||||
mOffscreenDisplay->CallerCanRead(*mSubjectPrincipal))) {
|
||||
blob = Blob::Create(mGlobal, blobImpl);
|
||||
}
|
||||
|
||||
RefPtr<BlobCallback> callback(std::move(mBlobCallback));
|
||||
ErrorResult rv;
|
||||
|
||||
callback->Call(blob, rv);
|
||||
|
||||
mGlobal = nullptr;
|
||||
MOZ_ASSERT(!mBlobCallback);
|
||||
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
bool CanBeDeletedOnAnyThread() override {
|
||||
// EncodeCallback is used from the main thread only.
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<BlobCallback> mBlobCallback;
|
||||
RefPtr<OffscreenCanvasDisplayHelper> mOffscreenDisplay;
|
||||
RefPtr<nsIPrincipal> mSubjectPrincipal;
|
||||
};
|
||||
|
||||
RefPtr<EncodeCompleteCallback> callback = new EncodeCallback(
|
||||
global, &aCallback, recheckCanRead ? mOffscreenDisplay.get() : nullptr,
|
||||
recheckCanRead ? &aSubjectPrincipal : nullptr);
|
||||
|
||||
CanvasRenderingContextHelper::ToBlob(aCx, callback, aType, aParams,
|
||||
usePlaceholder, aRv);
|
||||
}
|
||||
|
||||
|
|
@ -1090,7 +1154,12 @@ already_AddRefed<nsISupports> HTMLCanvasElement::GetContext(
|
|||
|
||||
nsIntSize HTMLCanvasElement::GetSize() { return GetWidthHeight(); }
|
||||
|
||||
bool HTMLCanvasElement::IsWriteOnly() const { return mWriteOnly; }
|
||||
bool HTMLCanvasElement::IsWriteOnly() const {
|
||||
if (mOffscreenDisplay && mOffscreenDisplay->IsWriteOnly()) {
|
||||
return true;
|
||||
}
|
||||
return mWriteOnly;
|
||||
}
|
||||
|
||||
void HTMLCanvasElement::SetWriteOnly(
|
||||
nsIPrincipal* aExpandedReader /* = nullptr */) {
|
||||
|
|
@ -1102,6 +1171,10 @@ void HTMLCanvasElement::SetWriteOnly(
|
|||
}
|
||||
|
||||
bool HTMLCanvasElement::CallerCanRead(nsIPrincipal& aPrincipal) const {
|
||||
if (mOffscreenDisplay && !mOffscreenDisplay->CallerCanRead(aPrincipal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mWriteOnly) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -372,13 +372,13 @@ class HTMLCanvasElement final : public nsGenericHTMLElement,
|
|||
RefPtr<layers::ImageContainer> mImageContainer;
|
||||
RefPtr<HTMLCanvasElementObserver> mContextObserver;
|
||||
|
||||
public:
|
||||
// Record whether this canvas should be write-only or not.
|
||||
// We set this when script paints an image from a different origin.
|
||||
// We also transitively set it when script paints a canvas which
|
||||
// is itself write-only.
|
||||
bool mWriteOnly;
|
||||
|
||||
public:
|
||||
// When this canvas is (only) tainted by an image from an extension
|
||||
// content script, allow reads from the same extension afterwards.
|
||||
RefPtr<nsIPrincipal> mExpandedReader;
|
||||
|
|
|
|||
|
|
@ -96,9 +96,7 @@ void ClearKeyPersistence::WriteIndex() {
|
|||
std::move(onIndexFail));
|
||||
}
|
||||
|
||||
ClearKeyPersistence::ClearKeyPersistence(Host_10* aHost) {
|
||||
this->mHost = aHost;
|
||||
}
|
||||
ClearKeyPersistence::ClearKeyPersistence(Host_11* aHost) : mHost(aHost) {}
|
||||
|
||||
void ClearKeyPersistence::EnsureInitialized(bool aPersistentStateAllowed,
|
||||
function<void()>&& aOnInitialized) {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ enum PersistentKeyState { UNINITIALIZED, LOADING, LOADED };
|
|||
|
||||
class ClearKeyPersistence : public RefCounted {
|
||||
public:
|
||||
explicit ClearKeyPersistence(cdm::Host_10* aHost);
|
||||
explicit ClearKeyPersistence(cdm::Host_11* aHost);
|
||||
|
||||
void EnsureInitialized(bool aPersistentStateAllowed,
|
||||
std::function<void()>&& aOnInitialized);
|
||||
|
|
@ -51,7 +51,7 @@ class ClearKeyPersistence : public RefCounted {
|
|||
void PersistentSessionRemoved(std::string& aSid);
|
||||
|
||||
private:
|
||||
cdm::Host_10* mHost = nullptr;
|
||||
cdm::Host_11* mHost = nullptr;
|
||||
|
||||
PersistentKeyState mPersistentKeyState = PersistentKeyState::UNINITIALIZED;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ using std::function;
|
|||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
ClearKeySessionManager::ClearKeySessionManager(Host_10* aHost)
|
||||
ClearKeySessionManager::ClearKeySessionManager(Host_11* aHost)
|
||||
: mDecryptionManager(ClearKeyDecryptionManager::Get()) {
|
||||
CK_LOGD("ClearKeySessionManager ctor %p", this);
|
||||
AddRef();
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
class ClearKeySessionManager final : public RefCounted {
|
||||
public:
|
||||
explicit ClearKeySessionManager(cdm::Host_10* aHost);
|
||||
explicit ClearKeySessionManager(cdm::Host_11* aHost);
|
||||
|
||||
void Init(bool aDistinctiveIdentifierAllowed, bool aPersistentStateAllowed);
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ class ClearKeySessionManager final : public RefCounted {
|
|||
RefPtr<ClearKeyDecryptionManager> mDecryptionManager;
|
||||
RefPtr<ClearKeyPersistence> mPersistence;
|
||||
|
||||
cdm::Host_10* mHost = nullptr;
|
||||
cdm::Host_11* mHost = nullptr;
|
||||
|
||||
std::set<KeyId> mKeyIds;
|
||||
std::map<std::string, ClearKeySession*> mSessions;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class WriteRecordClient : public FileIOClient {
|
|||
* This function will take the memory ownership of the parameters and
|
||||
* delete them when done.
|
||||
*/
|
||||
static void Write(Host_10* aHost, string& aRecordName,
|
||||
static void Write(Host_11* aHost, string& aRecordName,
|
||||
const vector<uint8_t>& aData, function<void()>&& aOnSuccess,
|
||||
function<void()>&& aOnFailure) {
|
||||
WriteRecordClient* client = new WriteRecordClient(
|
||||
|
|
@ -75,7 +75,7 @@ class WriteRecordClient : public FileIOClient {
|
|||
mOnFailure(std::move(aOnFailure)),
|
||||
mData(aData) {}
|
||||
|
||||
void Do(const string& aName, Host_10* aHost) {
|
||||
void Do(const string& aName, Host_11* aHost) {
|
||||
// Initialize the FileIO.
|
||||
mFileIO = aHost->CreateFileIO(this);
|
||||
mFileIO->Open(aName.c_str(), aName.size());
|
||||
|
|
@ -108,7 +108,7 @@ class WriteRecordClient : public FileIOClient {
|
|||
const vector<uint8_t> mData;
|
||||
};
|
||||
|
||||
void WriteData(Host_10* aHost, string& aRecordName,
|
||||
void WriteData(Host_11* aHost, string& aRecordName,
|
||||
const vector<uint8_t>& aData, function<void()>&& aOnSuccess,
|
||||
function<void()>&& aOnFailure) {
|
||||
WriteRecordClient::Write(aHost, aRecordName, aData, std::move(aOnSuccess),
|
||||
|
|
@ -121,7 +121,7 @@ class ReadRecordClient : public FileIOClient {
|
|||
* This function will take the memory ownership of the parameters and
|
||||
* delete them when done.
|
||||
*/
|
||||
static void Read(Host_10* aHost, string& aRecordName,
|
||||
static void Read(Host_11* aHost, string& aRecordName,
|
||||
function<void(const uint8_t*, uint32_t)>&& aOnSuccess,
|
||||
function<void()>&& aOnFailure) {
|
||||
(new ReadRecordClient(std::move(aOnSuccess), std::move(aOnFailure)))
|
||||
|
|
@ -155,7 +155,7 @@ class ReadRecordClient : public FileIOClient {
|
|||
mOnSuccess(std::move(aOnSuccess)),
|
||||
mOnFailure(std::move(aOnFailure)) {}
|
||||
|
||||
void Do(const string& aName, Host_10* aHost) {
|
||||
void Do(const string& aName, Host_11* aHost) {
|
||||
mFileIO = aHost->CreateFileIO(this);
|
||||
mFileIO->Open(aName.c_str(), aName.size());
|
||||
}
|
||||
|
|
@ -186,7 +186,7 @@ class ReadRecordClient : public FileIOClient {
|
|||
function<void()> mOnFailure;
|
||||
};
|
||||
|
||||
void ReadData(Host_10* aHost, string& aRecordName,
|
||||
void ReadData(Host_11* aHost, string& aRecordName,
|
||||
function<void(const uint8_t*, uint32_t)>&& aOnSuccess,
|
||||
function<void()>&& aOnFailure) {
|
||||
ReadRecordClient::Read(aHost, aRecordName, std::move(aOnSuccess),
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@
|
|||
#define IO_FAILED(x) ((x) != cdm::FileIOClient::Status::kSuccess)
|
||||
|
||||
// Writes data to a file and fires the appropriate callback when complete.
|
||||
void WriteData(cdm::Host_10* aHost, std::string& aRecordName,
|
||||
void WriteData(cdm::Host_11* aHost, std::string& aRecordName,
|
||||
const std::vector<uint8_t>& aData,
|
||||
std::function<void()>&& aOnSuccess,
|
||||
std::function<void()>&& aOnFailure);
|
||||
|
||||
// Reads data from a file and fires the appropriate callback when complete.
|
||||
void ReadData(cdm::Host_10* aHost, std::string& aRecordName,
|
||||
void ReadData(cdm::Host_11* aHost, std::string& aRecordName,
|
||||
std::function<void(const uint8_t*, uint32_t)>&& aOnSuccess,
|
||||
std::function<void()>&& aOnFailure);
|
||||
|
||||
|
|
|
|||
|
|
@ -46,11 +46,11 @@ CDM_API
|
|||
void* CreateCdmInstance(int cdm_interface_version, const char* key_system,
|
||||
uint32_t key_system_size,
|
||||
GetCdmHostFunc get_cdm_host_func, void* user_data) {
|
||||
if (cdm_interface_version != cdm::ContentDecryptionModule_10::kVersion) {
|
||||
// Only support CDM version 10 currently.
|
||||
if (cdm_interface_version != cdm::ContentDecryptionModule_11::kVersion) {
|
||||
// Only support CDM version 11 currently.
|
||||
return nullptr;
|
||||
}
|
||||
cdm::Host_10* host = static_cast<cdm::Host_10*>(
|
||||
cdm::Host_11* host = static_cast<cdm::Host_11*>(
|
||||
get_cdm_host_func(cdm_interface_version, user_data));
|
||||
return new FakeDecryptor(host);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class TestManager {
|
|||
std::set<std::string> mTestIDs;
|
||||
};
|
||||
|
||||
FakeDecryptor::FakeDecryptor(cdm::Host_10* aHost) : mHost(aHost) {
|
||||
FakeDecryptor::FakeDecryptor(cdm::Host_11* aHost) : mHost(aHost) {
|
||||
MOZ_ASSERT(!sInstance);
|
||||
sInstance = this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
class FakeDecryptor : public cdm::ContentDecryptionModule_10 {
|
||||
public:
|
||||
explicit FakeDecryptor(cdm::Host_10* aHost);
|
||||
explicit FakeDecryptor(cdm::Host_11* aHost);
|
||||
|
||||
void Initialize(bool aAllowDistinctiveIdentifier, bool aAllowPersistentState,
|
||||
bool aUseHardwareSecureCodecs) override {
|
||||
|
|
@ -93,7 +93,7 @@ class FakeDecryptor : public cdm::ContentDecryptionModule_10 {
|
|||
|
||||
static void Message(const std::string& aMessage);
|
||||
|
||||
cdm::Host_10* mHost;
|
||||
cdm::Host_11* mHost;
|
||||
|
||||
static FakeDecryptor* sInstance;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class WriteRecordClient : public FileIOClient {
|
|||
|
||||
void OnWriteComplete(Status aStatus) override { Done(aStatus); }
|
||||
|
||||
void Do(const std::string& aName, Host_10* aHost) {
|
||||
void Do(const std::string& aName, Host_11* aHost) {
|
||||
// Initialize the FileIO.
|
||||
mFileIO = aHost->CreateFileIO(this);
|
||||
mFileIO->Open(aName.c_str(), aName.size());
|
||||
|
|
@ -64,7 +64,7 @@ class WriteRecordClient : public FileIOClient {
|
|||
std::vector<uint8_t> mData;
|
||||
};
|
||||
|
||||
void WriteRecord(Host_10* aHost, const std::string& aRecordName,
|
||||
void WriteRecord(Host_11* aHost, const std::string& aRecordName,
|
||||
const uint8_t* aData, uint32_t aNumBytes,
|
||||
std::function<void()>&& aOnSuccess,
|
||||
std::function<void()>&& aOnFailure) {
|
||||
|
|
@ -74,7 +74,7 @@ void WriteRecord(Host_10* aHost, const std::string& aRecordName,
|
|||
client->Do(aRecordName, aHost);
|
||||
}
|
||||
|
||||
void WriteRecord(Host_10* aHost, const std::string& aRecordName,
|
||||
void WriteRecord(Host_11* aHost, const std::string& aRecordName,
|
||||
const std::string& aData, std::function<void()>&& aOnSuccess,
|
||||
std::function<void()>&& aOnFailure) {
|
||||
return WriteRecord(aHost, aRecordName, (const uint8_t*)aData.c_str(),
|
||||
|
|
@ -104,7 +104,7 @@ class ReadRecordClient : public FileIOClient {
|
|||
|
||||
void OnWriteComplete(Status aStatus) override {}
|
||||
|
||||
void Do(const std::string& aName, Host_10* aHost) {
|
||||
void Do(const std::string& aName, Host_11* aHost) {
|
||||
mFileIO = aHost->CreateFileIO(this);
|
||||
mFileIO->Open(aName.c_str(), aName.size());
|
||||
}
|
||||
|
|
@ -136,7 +136,7 @@ class ReadRecordClient : public FileIOClient {
|
|||
};
|
||||
|
||||
void ReadRecord(
|
||||
Host_10* aHost, const std::string& aRecordName,
|
||||
Host_11* aHost, const std::string& aRecordName,
|
||||
std::function<void(bool, const uint8_t*, uint32_t)>&& aOnReadComplete) {
|
||||
// client will be delete in ReadRecordClient::Done
|
||||
ReadRecordClient* client = new ReadRecordClient(std::move(aOnReadComplete));
|
||||
|
|
@ -155,7 +155,7 @@ class OpenRecordClient : public FileIOClient {
|
|||
|
||||
void OnWriteComplete(Status aStatus) override {}
|
||||
|
||||
void Do(const std::string& aName, Host_10* aHost) {
|
||||
void Do(const std::string& aName, Host_11* aHost) {
|
||||
// Initialize the FileIO.
|
||||
mFileIO = aHost->CreateFileIO(this);
|
||||
mFileIO->Open(aName.c_str(), aName.size());
|
||||
|
|
@ -186,7 +186,7 @@ class OpenRecordClient : public FileIOClient {
|
|||
std::function<void(bool)> mOpenComplete;
|
||||
};
|
||||
|
||||
void OpenRecord(Host_10* aHost, const std::string& aRecordName,
|
||||
void OpenRecord(Host_11* aHost, const std::string& aRecordName,
|
||||
std::function<void(bool)>&& aOpenComplete) {
|
||||
// client will be delete in OpenRecordClient::Done
|
||||
OpenRecordClient* client = new OpenRecordClient(std::move(aOpenComplete));
|
||||
|
|
|
|||
|
|
@ -21,17 +21,17 @@ class ReadContinuation {
|
|||
uint32_t aDataSize) = 0;
|
||||
};
|
||||
|
||||
void WriteRecord(cdm::Host_10* aHost, const std::string& aRecordName,
|
||||
void WriteRecord(cdm::Host_11* aHost, const std::string& aRecordName,
|
||||
const std::string& aData, std::function<void()>&& aOnSuccess,
|
||||
std::function<void()>&& aOnFailure);
|
||||
|
||||
void WriteRecord(cdm::Host_10* aHost, const std::string& aRecordName,
|
||||
void WriteRecord(cdm::Host_11* aHost, const std::string& aRecordName,
|
||||
const uint8_t* aData, uint32_t aNumBytes,
|
||||
std::function<void()>&& aOnSuccess,
|
||||
std::function<void()>&& aOnFailure);
|
||||
|
||||
void ReadRecord(
|
||||
cdm::Host_10* aHost, const std::string& aRecordName,
|
||||
cdm::Host_11* aHost, const std::string& aRecordName,
|
||||
std::function<void(bool, const uint8_t*, uint32_t)>&& aOnReadComplete);
|
||||
|
||||
class OpenContinuation {
|
||||
|
|
@ -40,6 +40,6 @@ class OpenContinuation {
|
|||
virtual void operator()(bool aSuccess) = 0;
|
||||
};
|
||||
|
||||
void OpenRecord(cdm::Host_10* aHost, const std::string& aRecordName,
|
||||
void OpenRecord(cdm::Host_11* aHost, const std::string& aRecordName,
|
||||
std::function<void(bool)>&& aOpenComplete);
|
||||
#endif // TEST_CDM_STORAGE_H__
|
||||
|
|
|
|||
|
|
@ -52,6 +52,15 @@ void ChromiumCDMAdapter::SetAdaptee(PRLibrary* aLib) { mLib = aLib; }
|
|||
void* ChromiumCdmHost(int aHostInterfaceVersion, void* aUserData) {
|
||||
GMP_LOG_DEBUG("ChromiumCdmHostFunc(%d, %p)", aHostInterfaceVersion,
|
||||
aUserData);
|
||||
if (aHostInterfaceVersion != cdm::Host_11::kVersion) {
|
||||
return nullptr;
|
||||
}
|
||||
return aUserData;
|
||||
}
|
||||
|
||||
void* ChromiumCdmHostCompat(int aHostInterfaceVersion, void* aUserData) {
|
||||
GMP_LOG_DEBUG("ChromiumCdmHostCompatFunc(%d, %p)", aHostInterfaceVersion,
|
||||
aUserData);
|
||||
if (aHostInterfaceVersion != cdm::Host_10::kVersion) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -116,16 +125,24 @@ GMPErr ChromiumCDMAdapter::GMPGetAPI(const char* aAPIName, void* aHostAPI,
|
|||
GMP_LOG_DEBUG("ChromiumCDMAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %s) this=0x%p",
|
||||
aAPIName, aHostAPI, aPluginAPI,
|
||||
PromiseFlatCString(aKeySystem).get(), this);
|
||||
bool isCdm10 = !strcmp(aAPIName, CHROMIUM_CDM_API);
|
||||
|
||||
if (!isCdm10) {
|
||||
MOZ_ASSERT_UNREACHABLE("We only support and expect cdm10!");
|
||||
int version;
|
||||
GetCdmHostFunc getCdmHostFunc;
|
||||
if (!strcmp(aAPIName, CHROMIUM_CDM_API)) {
|
||||
version = cdm::ContentDecryptionModule_11::kVersion;
|
||||
getCdmHostFunc = &ChromiumCdmHost;
|
||||
} else if (!strcmp(aAPIName, CHROMIUM_CDM_API_BACKWARD_COMPAT)) {
|
||||
version = cdm::ContentDecryptionModule_10::kVersion;
|
||||
getCdmHostFunc = &ChromiumCdmHostCompat;
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE("We only support and expect cdm10/11!");
|
||||
GMP_LOG_DEBUG(
|
||||
"ChromiumCDMAdapter::GMPGetAPI(%s, 0x%p, 0x%p) this=0x%p got "
|
||||
"unsupported CDM version!",
|
||||
aAPIName, aHostAPI, aPluginAPI, this);
|
||||
return GMPGenericErr;
|
||||
}
|
||||
|
||||
auto create = reinterpret_cast<decltype(::CreateCdmInstance)*>(
|
||||
PR_FindFunctionSymbol(mLib, "CreateCdmInstance"));
|
||||
if (!create) {
|
||||
|
|
@ -136,9 +153,8 @@ GMPErr ChromiumCDMAdapter::GMPGetAPI(const char* aAPIName, void* aHostAPI,
|
|||
return GMPGenericErr;
|
||||
}
|
||||
|
||||
const int version = cdm::ContentDecryptionModule_10::kVersion;
|
||||
void* cdm = create(version, aKeySystem.BeginReading(), aKeySystem.Length(),
|
||||
&ChromiumCdmHost, aHostAPI);
|
||||
getCdmHostFunc, aHostAPI);
|
||||
if (!cdm) {
|
||||
GMP_LOG_DEBUG(
|
||||
"ChromiumCDMAdapter::GMPGetAPI(%s, 0x%p, 0x%p) this=0x%p "
|
||||
|
|
@ -169,8 +185,10 @@ bool ChromiumCDMAdapter::Supports(int32_t aModuleVersion,
|
|||
int32_t aInterfaceVersion,
|
||||
int32_t aHostVersion) {
|
||||
return aModuleVersion == CDM_MODULE_VERSION &&
|
||||
aInterfaceVersion == cdm::ContentDecryptionModule_10::kVersion &&
|
||||
aHostVersion == cdm::Host_10::kVersion;
|
||||
((aInterfaceVersion == cdm::ContentDecryptionModule_11::kVersion &&
|
||||
aHostVersion == cdm::Host_11::kVersion) ||
|
||||
(aInterfaceVersion == cdm::ContentDecryptionModule_10::kVersion &&
|
||||
aHostVersion == cdm::Host_10::kVersion));
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ ChromiumCDMChild::ChromiumCDMChild(GMPContentChild* aPlugin)
|
|||
GMP_LOG_DEBUG("ChromiumCDMChild:: ctor this=%p", this);
|
||||
}
|
||||
|
||||
void ChromiumCDMChild::Init(cdm::ContentDecryptionModule_10* aCDM,
|
||||
void ChromiumCDMChild::Init(cdm::ContentDecryptionModule_11* aCDM,
|
||||
const nsACString& aStorageId) {
|
||||
MOZ_ASSERT(IsOnMessageLoopThread());
|
||||
mCDM = aCDM;
|
||||
|
|
@ -367,6 +367,13 @@ void ChromiumCDMChild::RequestStorageId(uint32_t aVersion) {
|
|||
mStorageId.Length());
|
||||
}
|
||||
|
||||
void ChromiumCDMChild::ReportMetrics(cdm::MetricName aMetricName,
|
||||
uint64_t aValue) {
|
||||
GMP_LOG_DEBUG("ChromiumCDMChild::ReportMetrics() aMetricName=%" PRIu32
|
||||
", aValue=%" PRIu64,
|
||||
aMetricName, aValue);
|
||||
}
|
||||
|
||||
ChromiumCDMChild::~ChromiumCDMChild() {
|
||||
GMP_LOG_DEBUG("ChromiumCDMChild:: dtor this=%p", this);
|
||||
}
|
||||
|
|
@ -637,25 +644,32 @@ mozilla::ipc::IPCResult ChromiumCDMChild::RecvDecrypt(
|
|||
cdm::Status status = mCDM->Decrypt(input, &output);
|
||||
|
||||
// CDM should have allocated a cdm::Buffer for output.
|
||||
CDMShmemBuffer* buffer =
|
||||
output.DecryptedBuffer()
|
||||
? static_cast<CDMShmemBuffer*>(output.DecryptedBuffer())
|
||||
: nullptr;
|
||||
MOZ_ASSERT_IF(buffer, buffer->AsShmemBuffer());
|
||||
if (status != cdm::kSuccess || !buffer) {
|
||||
if (status != cdm::kSuccess || !output.DecryptedBuffer()) {
|
||||
Unused << SendDecryptFailed(aId, status);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// Success! Return the decrypted sample to parent.
|
||||
MOZ_ASSERT(!HasShmemOfSize(outputShmemSize));
|
||||
ipc::Shmem shmem = buffer->ExtractShmem();
|
||||
if (SendDecrypted(aId, cdm::kSuccess, std::move(shmem))) {
|
||||
// No need to deallocate the output shmem; it should have been returned
|
||||
// to the content process.
|
||||
autoDeallocateOutputShmem.release();
|
||||
auto* buffer = static_cast<CDMBuffer*>(output.DecryptedBuffer());
|
||||
if (auto* shmemBuffer = buffer->AsShmemBuffer()) {
|
||||
MOZ_ASSERT(!HasShmemOfSize(outputShmemSize));
|
||||
ipc::Shmem shmem = shmemBuffer->ExtractShmem();
|
||||
if (SendDecryptedShmem(aId, cdm::kSuccess, std::move(shmem))) {
|
||||
// No need to deallocate the output shmem; it should have been returned
|
||||
// to the content process.
|
||||
autoDeallocateOutputShmem.release();
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
if (auto* arrayBuffer = buffer->AsArrayBuffer()) {
|
||||
Unused << SendDecryptedData(aId, cdm::kSuccess,
|
||||
arrayBuffer->ExtractBuffer());
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected CDMBuffer type!");
|
||||
GMP_LOG_DEBUG("ChromiumCDMChild::RecvDecrypt() unexpected CDMBuffer type");
|
||||
Unused << SendDecryptFailed(aId, cdm::kDecryptError);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
@ -783,12 +797,12 @@ void ChromiumCDMChild::ReturnOutput(WidevineVideoFrame& aFrame) {
|
|||
output.mFormat() = static_cast<cdm::VideoFormat>(aFrame.Format());
|
||||
output.mImageWidth() = aFrame.Size().width;
|
||||
output.mImageHeight() = aFrame.Size().height;
|
||||
output.mYPlane() = {aFrame.PlaneOffset(cdm::VideoPlane::kYPlane),
|
||||
aFrame.Stride(cdm::VideoPlane::kYPlane)};
|
||||
output.mUPlane() = {aFrame.PlaneOffset(cdm::VideoPlane::kUPlane),
|
||||
aFrame.Stride(cdm::VideoPlane::kUPlane)};
|
||||
output.mVPlane() = {aFrame.PlaneOffset(cdm::VideoPlane::kVPlane),
|
||||
aFrame.Stride(cdm::VideoPlane::kVPlane)};
|
||||
output.mYPlane() = {aFrame.PlaneOffset(cdm::kYPlane),
|
||||
aFrame.Stride(cdm::kYPlane)};
|
||||
output.mUPlane() = {aFrame.PlaneOffset(cdm::kUPlane),
|
||||
aFrame.Stride(cdm::kUPlane)};
|
||||
output.mVPlane() = {aFrame.PlaneOffset(cdm::kVPlane),
|
||||
aFrame.Stride(cdm::kVPlane)};
|
||||
output.mTimestamp() = aFrame.Timestamp();
|
||||
|
||||
uint64_t duration = 0;
|
||||
|
|
@ -797,13 +811,18 @@ void ChromiumCDMChild::ReturnOutput(WidevineVideoFrame& aFrame) {
|
|||
}
|
||||
|
||||
CDMBuffer* base = reinterpret_cast<CDMBuffer*>(aFrame.FrameBuffer());
|
||||
if (base->AsShmemBuffer()) {
|
||||
ipc::Shmem shmem = base->AsShmemBuffer()->ExtractShmem();
|
||||
if (auto* shmemBase = base->AsShmemBuffer()) {
|
||||
ipc::Shmem shmem = shmemBase->ExtractShmem();
|
||||
Unused << SendDecodedShmem(output, std::move(shmem));
|
||||
} else {
|
||||
MOZ_ASSERT(base->AsArrayBuffer());
|
||||
Unused << SendDecodedData(output, base->AsArrayBuffer()->ExtractBuffer());
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto* arrayBase = base->AsArrayBuffer()) {
|
||||
Unused << SendDecodedData(output, arrayBase->ExtractBuffer());
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected CDMBuffer type!");
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ChromiumCDMChild::RecvDrain() {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ namespace mozilla::gmp {
|
|||
|
||||
class GMPContentChild;
|
||||
|
||||
class ChromiumCDMChild : public PChromiumCDMChild, public cdm::Host_10 {
|
||||
class ChromiumCDMChild final : public PChromiumCDMChild,
|
||||
public cdm::Host_10,
|
||||
public cdm::Host_11 {
|
||||
public:
|
||||
// Mark AddRef and Release as `final`, as they overload pure virtual
|
||||
// implementations in PChromiumCDMChild.
|
||||
|
|
@ -23,12 +25,12 @@ class ChromiumCDMChild : public PChromiumCDMChild, public cdm::Host_10 {
|
|||
|
||||
explicit ChromiumCDMChild(GMPContentChild* aPlugin);
|
||||
|
||||
void Init(cdm::ContentDecryptionModule_10* aCDM,
|
||||
void Init(cdm::ContentDecryptionModule_11* aCDM,
|
||||
const nsACString& aStorageId);
|
||||
|
||||
void TimerExpired(void* aContext);
|
||||
|
||||
// cdm::Host_10 implementation
|
||||
// cdm::Host_10/cdm::Host_11 implementation
|
||||
cdm::Buffer* Allocate(uint32_t aCapacity) override;
|
||||
void SetTimer(int64_t aDelayMs, void* aContext) override;
|
||||
cdm::Time GetCurrentWallTime() override;
|
||||
|
|
@ -59,9 +61,10 @@ class ChromiumCDMChild : public PChromiumCDMChild, public cdm::Host_10 {
|
|||
void OnDeferredInitializationDone(cdm::StreamType aStreamType,
|
||||
cdm::Status aDecoderStatus) override {}
|
||||
void RequestStorageId(uint32_t aVersion) override;
|
||||
void ReportMetrics(cdm::MetricName aMetricName, uint64_t aValue) override;
|
||||
cdm::FileIO* CreateFileIO(cdm::FileIOClient* aClient) override;
|
||||
void OnInitialized(bool aSuccess) override;
|
||||
// end cdm::Host_10 specific methods
|
||||
// end cdm::Host_10/cdm::Host_11 specific methods
|
||||
|
||||
void GiveBuffer(ipc::Shmem&& aBuffer);
|
||||
|
||||
|
|
@ -123,7 +126,7 @@ class ChromiumCDMChild : public PChromiumCDMChild, public cdm::Host_10 {
|
|||
void CallOnMessageLoopThread(const char* const, MethodType, ParamType&&...);
|
||||
|
||||
GMPContentChild* mPlugin = nullptr;
|
||||
cdm::ContentDecryptionModule_10* mCDM = nullptr;
|
||||
cdm::ContentDecryptionModule_11* mCDM = nullptr;
|
||||
|
||||
typedef SimpleMap<int64_t, uint64_t, ThreadSafePolicy> DurationMap;
|
||||
DurationMap mFrameDurations;
|
||||
|
|
|
|||
134
icecat/dom/media/gmp/ChromiumCDMCompat.h
Normal file
134
icecat/dom/media/gmp/ChromiumCDMCompat.h
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef ChromiumCDMCompat_h_
|
||||
#define ChromiumCDMCompat_h_
|
||||
|
||||
#include "content_decryption_module.h"
|
||||
|
||||
namespace mozilla::gmp {
|
||||
|
||||
class ChromiumCDMCompat final : public cdm::ContentDecryptionModule_11 {
|
||||
public:
|
||||
explicit ChromiumCDMCompat(cdm::ContentDecryptionModule_10* aCDM)
|
||||
: mCDM(aCDM) {}
|
||||
|
||||
void Initialize(bool aAllowDistinctiveIdentifier, bool aAllowPersistentState,
|
||||
bool aUseHwSecureCodecs) override {
|
||||
mCDM->Initialize(aAllowDistinctiveIdentifier, aAllowPersistentState,
|
||||
aUseHwSecureCodecs);
|
||||
}
|
||||
|
||||
void GetStatusForPolicy(uint32_t aPromiseId,
|
||||
const cdm::Policy& aPolicy) override {
|
||||
mCDM->GetStatusForPolicy(aPromiseId, aPolicy);
|
||||
}
|
||||
|
||||
void SetServerCertificate(uint32_t aPromiseId,
|
||||
const uint8_t* aServerCertificateData,
|
||||
uint32_t aServerCertificateDataSize) override {
|
||||
mCDM->SetServerCertificate(aPromiseId, aServerCertificateData,
|
||||
aServerCertificateDataSize);
|
||||
}
|
||||
|
||||
void CreateSessionAndGenerateRequest(uint32_t aPromiseId,
|
||||
cdm::SessionType aSessionType,
|
||||
cdm::InitDataType aInitDataType,
|
||||
const uint8_t* aInitData,
|
||||
uint32_t aInitDataSize) override {
|
||||
mCDM->CreateSessionAndGenerateRequest(aPromiseId, aSessionType,
|
||||
aInitDataType, aInitData, aInitDataSize);
|
||||
};
|
||||
|
||||
void LoadSession(uint32_t aPromiseId, cdm::SessionType aSessionType,
|
||||
const char* aSessionId, uint32_t aSessionIdSize) override {
|
||||
mCDM->LoadSession(aPromiseId, aSessionType, aSessionId, aSessionIdSize);
|
||||
};
|
||||
|
||||
void UpdateSession(uint32_t aPromiseId, const char* aSessionId,
|
||||
uint32_t aSessionIdSize, const uint8_t* aResponse,
|
||||
uint32_t aResponseSize) override {
|
||||
mCDM->UpdateSession(aPromiseId, aSessionId, aSessionIdSize, aResponse,
|
||||
aResponseSize);
|
||||
};
|
||||
|
||||
void CloseSession(uint32_t aPromiseId, const char* aSessionId,
|
||||
uint32_t aSessionIdSize) override {
|
||||
mCDM->CloseSession(aPromiseId, aSessionId, aSessionIdSize);
|
||||
};
|
||||
|
||||
void RemoveSession(uint32_t aPromiseId, const char* aSessionId,
|
||||
uint32_t aSessionIdSize) override {
|
||||
mCDM->RemoveSession(aPromiseId, aSessionId, aSessionIdSize);
|
||||
};
|
||||
|
||||
void TimerExpired(void* aContext) override { mCDM->TimerExpired(aContext); };
|
||||
|
||||
cdm::Status Decrypt(const cdm::InputBuffer_2& aEncryptedBuffer,
|
||||
cdm::DecryptedBlock* aDecryptedBuffer) override {
|
||||
return mCDM->Decrypt(aEncryptedBuffer, aDecryptedBuffer);
|
||||
};
|
||||
|
||||
cdm::Status InitializeAudioDecoder(
|
||||
const cdm::AudioDecoderConfig_2& aAudioDecoderConfig) override {
|
||||
return mCDM->InitializeAudioDecoder(aAudioDecoderConfig);
|
||||
};
|
||||
|
||||
cdm::Status InitializeVideoDecoder(
|
||||
const cdm::VideoDecoderConfig_2& aVideoDecoderConfig) override {
|
||||
return mCDM->InitializeVideoDecoder(aVideoDecoderConfig);
|
||||
};
|
||||
|
||||
void DeinitializeDecoder(cdm::StreamType aDecoderType) override {
|
||||
mCDM->DeinitializeDecoder(aDecoderType);
|
||||
};
|
||||
|
||||
void ResetDecoder(cdm::StreamType aDecoderType) override {
|
||||
mCDM->ResetDecoder(aDecoderType);
|
||||
};
|
||||
|
||||
cdm::Status DecryptAndDecodeFrame(const cdm::InputBuffer_2& aEncryptedBuffer,
|
||||
cdm::VideoFrame* aVideoFrame) override {
|
||||
return mCDM->DecryptAndDecodeFrame(aEncryptedBuffer, aVideoFrame);
|
||||
};
|
||||
|
||||
cdm::Status DecryptAndDecodeSamples(
|
||||
const cdm::InputBuffer_2& aEncryptedBuffer,
|
||||
cdm::AudioFrames* aAudioFrames) override {
|
||||
return mCDM->DecryptAndDecodeSamples(aEncryptedBuffer, aAudioFrames);
|
||||
};
|
||||
|
||||
void OnPlatformChallengeResponse(
|
||||
const cdm::PlatformChallengeResponse& aResponse) override {
|
||||
mCDM->OnPlatformChallengeResponse(aResponse);
|
||||
};
|
||||
|
||||
void OnQueryOutputProtectionStatus(cdm::QueryResult aResult,
|
||||
uint32_t aLinkMask,
|
||||
uint32_t aOutputProtectionMask) override {
|
||||
mCDM->OnQueryOutputProtectionStatus(aResult, aLinkMask,
|
||||
aOutputProtectionMask);
|
||||
};
|
||||
|
||||
void OnStorageId(uint32_t aVersion, const uint8_t* aStorageId,
|
||||
uint32_t aStorageIdSize) override {
|
||||
mCDM->OnStorageId(aVersion, aStorageId, aStorageIdSize);
|
||||
}
|
||||
|
||||
// Destroys the object in the same aContext as it was created.
|
||||
void Destroy() override {
|
||||
mCDM->Destroy();
|
||||
delete this;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~ChromiumCDMCompat() = default;
|
||||
|
||||
cdm::ContentDecryptionModule_10* mCDM;
|
||||
};
|
||||
|
||||
} // namespace mozilla::gmp
|
||||
|
||||
#endif // ChromiumCDMCompat_h_
|
||||
|
|
@ -686,11 +686,11 @@ ipc::IPCResult ChromiumCDMParent::RecvDecryptFailed(const uint32_t& aId,
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
ipc::IPCResult ChromiumCDMParent::RecvDecrypted(const uint32_t& aId,
|
||||
const uint32_t& aStatus,
|
||||
ipc::Shmem&& aShmem) {
|
||||
ipc::IPCResult ChromiumCDMParent::RecvDecryptedShmem(const uint32_t& aId,
|
||||
const uint32_t& aStatus,
|
||||
ipc::Shmem&& aShmem) {
|
||||
MOZ_ASSERT(mGMPThread->IsOnCurrentThread());
|
||||
GMP_LOG_DEBUG("ChromiumCDMParent::RecvDecrypted(this=%p, id=%" PRIu32
|
||||
GMP_LOG_DEBUG("ChromiumCDMParent::RecvDecryptedShmem(this=%p, id=%" PRIu32
|
||||
", status=%" PRIu32 ")",
|
||||
this, aId, aStatus);
|
||||
|
||||
|
|
@ -704,9 +704,33 @@ ipc::IPCResult ChromiumCDMParent::RecvDecrypted(const uint32_t& aId,
|
|||
}
|
||||
for (size_t i = 0; i < mDecrypts.Length(); i++) {
|
||||
if (mDecrypts[i]->mId == aId) {
|
||||
mDecrypts[i]->PostResult(
|
||||
ToDecryptStatus(aStatus),
|
||||
Span<const uint8_t>(aShmem.get<uint8_t>(), aShmem.Size<uint8_t>()));
|
||||
mDecrypts[i]->PostResult(ToDecryptStatus(aStatus),
|
||||
aShmem.IsReadable()
|
||||
? Span<const uint8_t>(aShmem.get<uint8_t>(),
|
||||
aShmem.Size<uint8_t>())
|
||||
: Span<const uint8_t>());
|
||||
mDecrypts.RemoveElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
ipc::IPCResult ChromiumCDMParent::RecvDecryptedData(const uint32_t& aId,
|
||||
const uint32_t& aStatus,
|
||||
nsTArray<uint8_t>&& aData) {
|
||||
MOZ_ASSERT(mGMPThread->IsOnCurrentThread());
|
||||
GMP_LOG_DEBUG("ChromiumCDMParent::RecvDecryptedData(this=%p, id=%" PRIu32
|
||||
", status=%" PRIu32 ")",
|
||||
this, aId, aStatus);
|
||||
|
||||
if (mIsShutdown) {
|
||||
MOZ_ASSERT(mDecrypts.IsEmpty());
|
||||
return IPC_OK();
|
||||
}
|
||||
for (size_t i = 0; i < mDecrypts.Length(); i++) {
|
||||
if (mDecrypts[i]->mId == aId) {
|
||||
mDecrypts[i]->PostResult(ToDecryptStatus(aStatus), aData);
|
||||
mDecrypts.RemoveElementAt(i);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,8 +126,11 @@ class ChromiumCDMParent final : public PChromiumCDMParent,
|
|||
const double& aSecondsSinceEpoch);
|
||||
ipc::IPCResult RecvOnSessionClosed(const nsCString& aSessionId);
|
||||
ipc::IPCResult RecvOnQueryOutputProtectionStatus();
|
||||
ipc::IPCResult RecvDecrypted(const uint32_t& aId, const uint32_t& aStatus,
|
||||
ipc::Shmem&& aData);
|
||||
ipc::IPCResult RecvDecryptedShmem(const uint32_t& aId,
|
||||
const uint32_t& aStatus,
|
||||
ipc::Shmem&& aData);
|
||||
ipc::IPCResult RecvDecryptedData(const uint32_t& aId, const uint32_t& aStatus,
|
||||
nsTArray<uint8_t>&& aData);
|
||||
ipc::IPCResult RecvDecryptFailed(const uint32_t& aId,
|
||||
const uint32_t& aStatus);
|
||||
ipc::IPCResult RecvOnDecoderInitDone(const uint32_t& aStatus);
|
||||
|
|
|
|||
|
|
@ -27,11 +27,13 @@ void DecryptJob::PostResult(DecryptStatus aResult,
|
|||
if (aDecryptedData.Length() != mSample->Size()) {
|
||||
NS_WARNING("CDM returned incorrect number of decrypted bytes");
|
||||
}
|
||||
if (aResult == eme::Ok) {
|
||||
if (aResult == DecryptStatus::Ok) {
|
||||
UniquePtr<MediaRawDataWriter> writer(mSample->CreateWriter());
|
||||
PodCopy(writer->Data(), aDecryptedData.Elements(),
|
||||
std::min<size_t>(aDecryptedData.Length(), mSample->Size()));
|
||||
} else if (aResult == eme::NoKeyErr) {
|
||||
if (NS_WARN_IF(!writer->Replace(aDecryptedData.Elements(),
|
||||
aDecryptedData.Length()))) {
|
||||
aResult = DecryptStatus::GenericErr;
|
||||
}
|
||||
} else if (aResult == DecryptStatus::NoKeyErr) {
|
||||
NS_WARNING("CDM returned NoKeyErr");
|
||||
// We still have the encrypted sample, so we can re-enqueue it to be
|
||||
// decrypted again once the key is usable again.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "GMPVideoDecoderChild.h"
|
||||
#include "GMPVideoEncoderChild.h"
|
||||
#include "ChromiumCDMChild.h"
|
||||
#include "ChromiumCDMCompat.h"
|
||||
#include "base/task.h"
|
||||
#include "GMPUtils.h"
|
||||
|
||||
|
|
@ -88,15 +89,23 @@ mozilla::ipc::IPCResult GMPContentChild::RecvPGMPVideoEncoderConstructor(
|
|||
mozilla::ipc::IPCResult GMPContentChild::RecvPChromiumCDMConstructor(
|
||||
PChromiumCDMChild* aActor, const nsACString& aKeySystem) {
|
||||
ChromiumCDMChild* child = static_cast<ChromiumCDMChild*>(aActor);
|
||||
cdm::Host_10* host10 = child;
|
||||
|
||||
void* cdm = nullptr;
|
||||
GMPErr err = mGMPChild->GetAPI(CHROMIUM_CDM_API, host10, &cdm, aKeySystem);
|
||||
GMPErr err = mGMPChild->GetAPI(
|
||||
CHROMIUM_CDM_API, static_cast<cdm::Host_11*>(child), &cdm, aKeySystem);
|
||||
if (err != GMPNoErr || !cdm) {
|
||||
return IPC_FAIL(this, "GMPGetAPI call failed trying to get CDM.");
|
||||
err =
|
||||
mGMPChild->GetAPI(CHROMIUM_CDM_API_BACKWARD_COMPAT,
|
||||
static_cast<cdm::Host_10*>(child), &cdm, aKeySystem);
|
||||
if (err != GMPNoErr || !cdm) {
|
||||
return IPC_FAIL(this, "GMPGetAPI call failed trying to get CDM.");
|
||||
}
|
||||
|
||||
cdm = new ChromiumCDMCompat(
|
||||
static_cast<cdm::ContentDecryptionModule_10*>(cdm));
|
||||
}
|
||||
|
||||
child->Init(static_cast<cdm::ContentDecryptionModule_10*>(cdm),
|
||||
child->Init(static_cast<cdm::ContentDecryptionModule_11*>(cdm),
|
||||
mGMPChild->mStorageId);
|
||||
|
||||
return IPC_OK();
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
#include "nsStringFwd.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#define CHROMIUM_CDM_API_BACKWARD_COMPAT "chromium-cdm9-host4"
|
||||
#define CHROMIUM_CDM_API "chromium-cdm10-host4"
|
||||
#define CHROMIUM_CDM_API_BACKWARD_COMPAT "chromium-cdm10-host4"
|
||||
#define CHROMIUM_CDM_API "chromium-cdm11-host4"
|
||||
|
||||
class GMPVideoEncodedFrame;
|
||||
class nsIFile;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ child:
|
|||
parent:
|
||||
async __delete__();
|
||||
|
||||
// cdm::Host_10
|
||||
// cdm::Host_11
|
||||
async OnResolvePromiseWithKeyStatus(uint32_t aPromiseId, uint32_t aKeyStatus);
|
||||
|
||||
async OnResolveNewSessionPromise(uint32_t aPromiseId, nsCString aSessionId);
|
||||
|
|
@ -106,7 +106,8 @@ parent:
|
|||
async ResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccessful);
|
||||
|
||||
// Return values of cdm::ContentDecryptionModule_10::Decrypt
|
||||
async Decrypted(uint32_t aId, uint32_t aStatus, Shmem aDecryptedData);
|
||||
async DecryptedShmem(uint32_t aId, uint32_t aStatus, Shmem aData);
|
||||
async DecryptedData(uint32_t aId, uint32_t aStatus, uint8_t[] aData);
|
||||
async DecryptFailed(uint32_t aId, uint32_t aStatus);
|
||||
|
||||
async OnDecoderInitDone(uint32_t aStatus);
|
||||
|
|
|
|||
|
|
@ -62,10 +62,6 @@ EXPORTS += [
|
|||
"GMPVideoHost.h",
|
||||
"GMPVideoi420FrameImpl.h",
|
||||
"GMPVideoPlaneImpl.h",
|
||||
"widevine-adapter/content_decryption_module.h",
|
||||
"widevine-adapter/content_decryption_module_export.h",
|
||||
"widevine-adapter/content_decryption_module_ext.h",
|
||||
"widevine-adapter/content_decryption_module_proxy.h",
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
|
|
|
|||
|
|
@ -127,14 +127,14 @@ bool WidevineVideoFrame::InitToBlack(int32_t aWidth, int32_t aHeight,
|
|||
SetFormat(cdm::VideoFormat::kI420);
|
||||
SetSize(cdm::Size{aWidth, aHeight});
|
||||
SetFrameBuffer(buffer);
|
||||
SetPlaneOffset(cdm::VideoPlane::kYPlane, 0);
|
||||
SetStride(cdm::VideoPlane::kYPlane, aWidth);
|
||||
SetPlaneOffset(cdm::kYPlane, 0);
|
||||
SetStride(cdm::kYPlane, aWidth);
|
||||
// Note: U and V planes are stored at the same place in order to
|
||||
// save memory since their contents are the same.
|
||||
SetPlaneOffset(cdm::VideoPlane::kUPlane, ySize);
|
||||
SetStride(cdm::VideoPlane::kUPlane, halfWidth);
|
||||
SetPlaneOffset(cdm::VideoPlane::kVPlane, ySize);
|
||||
SetStride(cdm::VideoPlane::kVPlane, halfWidth);
|
||||
SetPlaneOffset(cdm::kUPlane, ySize);
|
||||
SetStride(cdm::kUPlane, halfWidth);
|
||||
SetPlaneOffset(cdm::kVPlane, ySize);
|
||||
SetStride(cdm::kVPlane, halfWidth);
|
||||
SetTimestamp(aTimeStamp);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ class WidevineVideoFrame : public cdm::VideoFrame {
|
|||
cdm::VideoFormat mFormat;
|
||||
cdm::Size mSize;
|
||||
cdm::Buffer* mBuffer;
|
||||
uint32_t mPlaneOffsets[cdm::VideoPlane::kMaxPlanes];
|
||||
uint32_t mPlaneStrides[cdm::VideoPlane::kMaxPlanes];
|
||||
uint32_t mPlaneOffsets[cdm::kMaxPlanes];
|
||||
uint32_t mPlaneStrides[cdm::kMaxPlanes];
|
||||
int64_t mTimestamp;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#include <type_traits>
|
||||
|
||||
#include "content_decryption_module_export.h"
|
||||
#include "content_decryption_module_proxy.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
typedef unsigned char uint8_t;
|
||||
|
|
@ -16,7 +15,7 @@ typedef unsigned int uint32_t;
|
|||
typedef int int32_t;
|
||||
typedef __int64 int64_t;
|
||||
#else
|
||||
# include <stdint.h>
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
// The version number must be rolled when the exported functions are updated!
|
||||
|
|
@ -411,6 +410,7 @@ CHECK_TYPE(InitDataType, 4, 4);
|
|||
enum SessionType : uint32_t {
|
||||
kTemporary = 0,
|
||||
kPersistentLicense = 1,
|
||||
kPersistentUsageRecord = 2
|
||||
};
|
||||
CHECK_TYPE(SessionType, 4, 4);
|
||||
|
||||
|
|
@ -479,12 +479,13 @@ class CDM_CLASS_API DecryptedBlock {
|
|||
virtual ~DecryptedBlock() {}
|
||||
};
|
||||
|
||||
enum VideoPlane : uint32_t {
|
||||
kYPlane = 0,
|
||||
kUPlane = 1,
|
||||
kVPlane = 2,
|
||||
kMaxPlanes = 3,
|
||||
};
|
||||
// This intentionally avoids using an enum, since it will be used to do math
|
||||
// with other enums, which is deprecated in C++20.
|
||||
using VideoPlane = uint32_t;
|
||||
constexpr VideoPlane kYPlane = 0;
|
||||
constexpr VideoPlane kUPlane = 1;
|
||||
constexpr VideoPlane kVPlane = 2;
|
||||
constexpr VideoPlane kMaxPlanes = 3;
|
||||
CHECK_TYPE(VideoPlane, 4, 4);
|
||||
|
||||
class CDM_CLASS_API VideoFrame {
|
||||
|
|
@ -622,7 +623,8 @@ class CDM_CLASS_API FileIOClient {
|
|||
// - kInUse indicates that there are other read/write operations pending.
|
||||
// - kError indicates read failure, e.g. the storage is not open or cannot be
|
||||
// fully read.
|
||||
virtual void OnReadComplete(Status status, const uint8_t* data,
|
||||
virtual void OnReadComplete(Status status,
|
||||
const uint8_t* data,
|
||||
uint32_t data_size) = 0;
|
||||
|
||||
// Response to a FileIO::Write() call.
|
||||
|
|
@ -639,8 +641,21 @@ class CDM_CLASS_API FileIOClient {
|
|||
virtual ~FileIOClient() {}
|
||||
};
|
||||
|
||||
// Metrics that will be reported from the CDM through the ReportMetrics()
|
||||
// function. To add a new metric, please add it to the end of this enum list
|
||||
// without changing any existing enum values.
|
||||
// Note: For forward compatibility, Host implementations must gracefully handle
|
||||
// unexpected (new) enum values, e.g. no-op.
|
||||
enum MetricName : uint32_t {
|
||||
kSdkVersion,
|
||||
kCertificateSerialNumber,
|
||||
kDecoderBypassBlockCount,
|
||||
};
|
||||
CHECK_TYPE(MetricName, 4, 4);
|
||||
|
||||
class CDM_CLASS_API Host_10;
|
||||
class CDM_CLASS_API Host_11;
|
||||
class CDM_CLASS_API Host_12;
|
||||
|
||||
// ContentDecryptionModule interface that all CDMs need to implement.
|
||||
// The interface is versioned for backward compatibility.
|
||||
|
|
@ -708,28 +723,33 @@ class CDM_CLASS_API ContentDecryptionModule_10 {
|
|||
// The CDM must respond by calling either Host::OnResolveNewSessionPromise()
|
||||
// or Host::OnRejectPromise(). If the session is not found, call
|
||||
// Host::OnResolveNewSessionPromise() with session_id = NULL.
|
||||
virtual void LoadSession(uint32_t promise_id, SessionType session_type,
|
||||
virtual void LoadSession(uint32_t promise_id,
|
||||
SessionType session_type,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size) = 0;
|
||||
|
||||
// Updates the session with |response|. The CDM must respond by calling
|
||||
// either Host::OnResolvePromise() or Host::OnRejectPromise().
|
||||
virtual void UpdateSession(uint32_t promise_id, const char* session_id,
|
||||
uint32_t session_id_size, const uint8_t* response,
|
||||
virtual void UpdateSession(uint32_t promise_id,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size,
|
||||
const uint8_t* response,
|
||||
uint32_t response_size) = 0;
|
||||
|
||||
// Requests that the CDM close the session. The CDM must respond by calling
|
||||
// either Host::OnResolvePromise() or Host::OnRejectPromise() when the request
|
||||
// has been processed. This may be before the session is closed. Once the
|
||||
// session is closed, Host::OnSessionClosed() must also be called.
|
||||
virtual void CloseSession(uint32_t promise_id, const char* session_id,
|
||||
virtual void CloseSession(uint32_t promise_id,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size) = 0;
|
||||
|
||||
// Removes any stored session data associated with this session. Will only be
|
||||
// called for persistent sessions. The CDM must respond by calling either
|
||||
// Host::OnResolvePromise() or Host::OnRejectPromise() when the request has
|
||||
// been processed.
|
||||
virtual void RemoveSession(uint32_t promise_id, const char* session_id,
|
||||
virtual void RemoveSession(uint32_t promise_id,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size) = 0;
|
||||
|
||||
// Performs scheduled operation with |context| when the timer fires.
|
||||
|
|
@ -833,7 +853,8 @@ class CDM_CLASS_API ContentDecryptionModule_10 {
|
|||
// then |link_mask| and |output_protection_mask| are undefined and should
|
||||
// be ignored.
|
||||
virtual void OnQueryOutputProtectionStatus(
|
||||
QueryResult result, uint32_t link_mask,
|
||||
QueryResult result,
|
||||
uint32_t link_mask,
|
||||
uint32_t output_protection_mask) = 0;
|
||||
|
||||
// Called by the host after a call to Host::RequestStorageId(). If the
|
||||
|
|
@ -844,7 +865,8 @@ class CDM_CLASS_API ContentDecryptionModule_10 {
|
|||
// If the requested version is not available, null/zero will be provided as
|
||||
// |storage_id| and |storage_id_size|, respectively, and |version| should be
|
||||
// ignored.
|
||||
virtual void OnStorageId(uint32_t version, const uint8_t* storage_id,
|
||||
virtual void OnStorageId(uint32_t version,
|
||||
const uint8_t* storage_id,
|
||||
uint32_t storage_id_size) = 0;
|
||||
|
||||
// Destroys the object in the same context as it was created.
|
||||
|
|
@ -855,8 +877,6 @@ class CDM_CLASS_API ContentDecryptionModule_10 {
|
|||
virtual ~ContentDecryptionModule_10() {}
|
||||
};
|
||||
|
||||
// ----- Note: CDM interface(s) below still in development and not stable! -----
|
||||
|
||||
// ContentDecryptionModule interface that all CDMs need to implement.
|
||||
// The interface is versioned for backward compatibility.
|
||||
// Note: ContentDecryptionModule implementations must use the allocator
|
||||
|
|
@ -866,7 +886,7 @@ class CDM_CLASS_API ContentDecryptionModule_10 {
|
|||
class CDM_CLASS_API ContentDecryptionModule_11 {
|
||||
public:
|
||||
static const int kVersion = 11;
|
||||
static const bool kIsStable = false;
|
||||
static const bool kIsStable = true;
|
||||
typedef Host_11 Host;
|
||||
|
||||
// Initializes the CDM instance, providing information about permitted
|
||||
|
|
@ -923,21 +943,247 @@ class CDM_CLASS_API ContentDecryptionModule_11 {
|
|||
// The CDM must respond by calling either Host::OnResolveNewSessionPromise()
|
||||
// or Host::OnRejectPromise(). If the session is not found, call
|
||||
// Host::OnResolveNewSessionPromise() with session_id = NULL.
|
||||
virtual void LoadSession(uint32_t promise_id, SessionType session_type,
|
||||
virtual void LoadSession(uint32_t promise_id,
|
||||
SessionType session_type,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size) = 0;
|
||||
|
||||
// Updates the session with |response|. The CDM must respond by calling
|
||||
// either Host::OnResolvePromise() or Host::OnRejectPromise().
|
||||
virtual void UpdateSession(uint32_t promise_id, const char* session_id,
|
||||
uint32_t session_id_size, const uint8_t* response,
|
||||
virtual void UpdateSession(uint32_t promise_id,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size,
|
||||
const uint8_t* response,
|
||||
uint32_t response_size) = 0;
|
||||
|
||||
// Requests that the CDM close the session. The CDM must respond by calling
|
||||
// either Host::OnResolvePromise() or Host::OnRejectPromise() when the request
|
||||
// has been processed. This may be before the session is closed. Once the
|
||||
// session is closed, Host::OnSessionClosed() must also be called.
|
||||
virtual void CloseSession(uint32_t promise_id, const char* session_id,
|
||||
virtual void CloseSession(uint32_t promise_id,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size) = 0;
|
||||
|
||||
// Removes any stored session data associated with this session. Will only be
|
||||
// called for persistent sessions. The CDM must respond by calling either
|
||||
// Host::OnResolvePromise() or Host::OnRejectPromise() when the request has
|
||||
// been processed.
|
||||
virtual void RemoveSession(uint32_t promise_id,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size) = 0;
|
||||
|
||||
// Performs scheduled operation with |context| when the timer fires.
|
||||
virtual void TimerExpired(void* context) = 0;
|
||||
|
||||
// Decrypts the |encrypted_buffer|.
|
||||
//
|
||||
// Returns kSuccess if decryption succeeded, in which case the callee
|
||||
// should have filled the |decrypted_buffer| and passed the ownership of
|
||||
// |data| in |decrypted_buffer| to the caller.
|
||||
// Returns kNoKey if the CDM did not have the necessary decryption key
|
||||
// to decrypt.
|
||||
// Returns kDecryptError if any other error happened.
|
||||
// If the return value is not kSuccess, |decrypted_buffer| should be ignored
|
||||
// by the caller.
|
||||
virtual Status Decrypt(const InputBuffer_2& encrypted_buffer,
|
||||
DecryptedBlock* decrypted_buffer) = 0;
|
||||
|
||||
// Initializes the CDM audio decoder with |audio_decoder_config|. This
|
||||
// function must be called before DecryptAndDecodeSamples() is called.
|
||||
//
|
||||
// Returns kSuccess if the |audio_decoder_config| is supported and the CDM
|
||||
// audio decoder is successfully initialized.
|
||||
// Returns kInitializationError if |audio_decoder_config| is not supported.
|
||||
// The CDM may still be able to do Decrypt().
|
||||
// Returns kDeferredInitialization if the CDM is not ready to initialize the
|
||||
// decoder at this time. Must call Host::OnDeferredInitializationDone() once
|
||||
// initialization is complete.
|
||||
virtual Status InitializeAudioDecoder(
|
||||
const AudioDecoderConfig_2& audio_decoder_config) = 0;
|
||||
|
||||
// Initializes the CDM video decoder with |video_decoder_config|. This
|
||||
// function must be called before DecryptAndDecodeFrame() is called.
|
||||
//
|
||||
// Returns kSuccess if the |video_decoder_config| is supported and the CDM
|
||||
// video decoder is successfully initialized.
|
||||
// Returns kInitializationError if |video_decoder_config| is not supported.
|
||||
// The CDM may still be able to do Decrypt().
|
||||
// Returns kDeferredInitialization if the CDM is not ready to initialize the
|
||||
// decoder at this time. Must call Host::OnDeferredInitializationDone() once
|
||||
// initialization is complete.
|
||||
virtual Status InitializeVideoDecoder(
|
||||
const VideoDecoderConfig_2& video_decoder_config) = 0;
|
||||
|
||||
// De-initializes the CDM decoder and sets it to an uninitialized state. The
|
||||
// caller can initialize the decoder again after this call to re-initialize
|
||||
// it. This can be used to reconfigure the decoder if the configuration
|
||||
// changes.
|
||||
virtual void DeinitializeDecoder(StreamType decoder_type) = 0;
|
||||
|
||||
// Resets the CDM decoder to an initialized clean state. All internal buffers
|
||||
// MUST be flushed.
|
||||
virtual void ResetDecoder(StreamType decoder_type) = 0;
|
||||
|
||||
// Decrypts the |encrypted_buffer| and decodes the decrypted buffer into a
|
||||
// |video_frame|. Upon end-of-stream, the caller should call this function
|
||||
// repeatedly with empty |encrypted_buffer| (|data| == NULL) until
|
||||
// kNeedMoreData is returned.
|
||||
//
|
||||
// Returns kSuccess if decryption and decoding both succeeded, in which case
|
||||
// the callee will have filled the |video_frame| and passed the ownership of
|
||||
// |frame_buffer| in |video_frame| to the caller.
|
||||
// Returns kNoKey if the CDM did not have the necessary decryption key
|
||||
// to decrypt.
|
||||
// Returns kNeedMoreData if more data was needed by the decoder to generate
|
||||
// a decoded frame (e.g. during initialization and end-of-stream).
|
||||
// Returns kDecryptError if any decryption error happened.
|
||||
// Returns kDecodeError if any decoding error happened.
|
||||
// If the return value is not kSuccess, |video_frame| should be ignored by
|
||||
// the caller.
|
||||
virtual Status DecryptAndDecodeFrame(const InputBuffer_2& encrypted_buffer,
|
||||
VideoFrame* video_frame) = 0;
|
||||
|
||||
// Decrypts the |encrypted_buffer| and decodes the decrypted buffer into
|
||||
// |audio_frames|. Upon end-of-stream, the caller should call this function
|
||||
// repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty
|
||||
// |audio_frames| is produced.
|
||||
//
|
||||
// Returns kSuccess if decryption and decoding both succeeded, in which case
|
||||
// the callee will have filled |audio_frames| and passed the ownership of
|
||||
// |data| in |audio_frames| to the caller.
|
||||
// Returns kNoKey if the CDM did not have the necessary decryption key
|
||||
// to decrypt.
|
||||
// Returns kNeedMoreData if more data was needed by the decoder to generate
|
||||
// audio samples (e.g. during initialization and end-of-stream).
|
||||
// Returns kDecryptError if any decryption error happened.
|
||||
// Returns kDecodeError if any decoding error happened.
|
||||
// If the return value is not kSuccess, |audio_frames| should be ignored by
|
||||
// the caller.
|
||||
virtual Status DecryptAndDecodeSamples(const InputBuffer_2& encrypted_buffer,
|
||||
AudioFrames* audio_frames) = 0;
|
||||
|
||||
// Called by the host after a platform challenge was initiated via
|
||||
// Host::SendPlatformChallenge().
|
||||
virtual void OnPlatformChallengeResponse(
|
||||
const PlatformChallengeResponse& response) = 0;
|
||||
|
||||
// Called by the host after a call to Host::QueryOutputProtectionStatus(). The
|
||||
// |link_mask| is a bit mask of OutputLinkTypes and |output_protection_mask|
|
||||
// is a bit mask of OutputProtectionMethods. If |result| is kQueryFailed,
|
||||
// then |link_mask| and |output_protection_mask| are undefined and should
|
||||
// be ignored.
|
||||
virtual void OnQueryOutputProtectionStatus(
|
||||
QueryResult result,
|
||||
uint32_t link_mask,
|
||||
uint32_t output_protection_mask) = 0;
|
||||
|
||||
// Called by the host after a call to Host::RequestStorageId(). If the
|
||||
// version of the storage ID requested is available, |storage_id| and
|
||||
// |storage_id_size| are set appropriately. |version| will be the same as
|
||||
// what was requested, unless 0 (latest) was requested, in which case
|
||||
// |version| will be the actual version number for the |storage_id| returned.
|
||||
// If the requested version is not available, null/zero will be provided as
|
||||
// |storage_id| and |storage_id_size|, respectively, and |version| should be
|
||||
// ignored.
|
||||
virtual void OnStorageId(uint32_t version,
|
||||
const uint8_t* storage_id,
|
||||
uint32_t storage_id_size) = 0;
|
||||
|
||||
// Destroys the object in the same context as it was created.
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
protected:
|
||||
ContentDecryptionModule_11() {}
|
||||
virtual ~ContentDecryptionModule_11() {}
|
||||
};
|
||||
|
||||
// ----- Note: CDM interface(s) below still in development and not stable! -----
|
||||
|
||||
// ContentDecryptionModule interface that all CDMs need to implement.
|
||||
// The interface is versioned for backward compatibility.
|
||||
// Note: ContentDecryptionModule implementations must use the allocator
|
||||
// provided in CreateCdmInstance() to allocate any Buffer that needs to
|
||||
// be passed back to the caller. Implementations must call Buffer::Destroy()
|
||||
// when a Buffer is created that will never be returned to the caller.
|
||||
class CDM_CLASS_API ContentDecryptionModule_12 {
|
||||
public:
|
||||
static const int kVersion = 12;
|
||||
static const bool kIsStable = false;
|
||||
typedef Host_12 Host;
|
||||
|
||||
// Initializes the CDM instance, providing information about permitted
|
||||
// functionalities. The CDM must respond by calling Host::OnInitialized()
|
||||
// with whether the initialization succeeded. No other calls will be made by
|
||||
// the host before Host::OnInitialized() returns.
|
||||
// If |allow_distinctive_identifier| is false, messages from the CDM,
|
||||
// such as message events, must not contain a Distinctive Identifier,
|
||||
// even in an encrypted form.
|
||||
// If |allow_persistent_state| is false, the CDM must not attempt to
|
||||
// persist state. Calls to CreateFileIO() will fail.
|
||||
// If |use_hw_secure_codecs| is true, the CDM must ensure the decryption key
|
||||
// and video buffers (compressed and uncompressed) are securely protected by
|
||||
// hardware.
|
||||
virtual void Initialize(bool allow_distinctive_identifier,
|
||||
bool allow_persistent_state,
|
||||
bool use_hw_secure_codecs) = 0;
|
||||
|
||||
// Gets the key status if the CDM has a hypothetical key with the |policy|.
|
||||
// The CDM must respond by calling either Host::OnResolveKeyStatusPromise()
|
||||
// with the result key status or Host::OnRejectPromise() if an unexpected
|
||||
// error happened or this method is not supported.
|
||||
virtual void GetStatusForPolicy(uint32_t promise_id,
|
||||
const Policy& policy) = 0;
|
||||
|
||||
// SetServerCertificate(), CreateSessionAndGenerateRequest(), LoadSession(),
|
||||
// UpdateSession(), CloseSession(), and RemoveSession() all accept a
|
||||
// |promise_id|, which must be passed to the completion Host method
|
||||
// (e.g. Host::OnResolveNewSessionPromise()).
|
||||
|
||||
// Provides a server certificate to be used to encrypt messages to the
|
||||
// license server. The CDM must respond by calling either
|
||||
// Host::OnResolvePromise() or Host::OnRejectPromise().
|
||||
// If the CDM does not support server certificates, the promise should be
|
||||
// rejected with kExceptionNotSupportedError. If |server_certificate_data|
|
||||
// is empty, reject with kExceptionTypeError. Any other error should be
|
||||
// rejected with kExceptionInvalidStateError or kExceptionQuotaExceededError.
|
||||
// TODO(crbug.com/796417): Add support for the promise to return true or
|
||||
// false, rather than using kExceptionNotSupportedError to mean false.
|
||||
virtual void SetServerCertificate(uint32_t promise_id,
|
||||
const uint8_t* server_certificate_data,
|
||||
uint32_t server_certificate_data_size) = 0;
|
||||
|
||||
// Creates a session given |session_type|, |init_data_type|, and |init_data|.
|
||||
// The CDM must respond by calling either Host::OnResolveNewSessionPromise()
|
||||
// or Host::OnRejectPromise().
|
||||
virtual void CreateSessionAndGenerateRequest(uint32_t promise_id,
|
||||
SessionType session_type,
|
||||
InitDataType init_data_type,
|
||||
const uint8_t* init_data,
|
||||
uint32_t init_data_size) = 0;
|
||||
|
||||
// Loads the session of type |session_type| specified by |session_id|.
|
||||
// The CDM must respond by calling either Host::OnResolveNewSessionPromise()
|
||||
// or Host::OnRejectPromise(). If the session is not found, call
|
||||
// Host::OnResolveNewSessionPromise() with session_id = NULL.
|
||||
virtual void LoadSession(uint32_t promise_id,
|
||||
SessionType session_type,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size) = 0;
|
||||
|
||||
// Updates the session with |response|. The CDM must respond by calling
|
||||
// either Host::OnResolvePromise() or Host::OnRejectPromise().
|
||||
virtual void UpdateSession(uint32_t promise_id,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size,
|
||||
const uint8_t* response,
|
||||
uint32_t response_size) = 0;
|
||||
|
||||
// Requests that the CDM close the session. The CDM must respond by calling
|
||||
// either Host::OnResolvePromise() or Host::OnRejectPromise() when the request
|
||||
// has been processed. This may be before the session is closed. Once the
|
||||
// session is closed, Host::OnSessionClosed() must also be called.
|
||||
virtual void CloseSession(uint32_t promise_id,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size) = 0;
|
||||
|
||||
// Removes any stored session data associated with this session. Removes all
|
||||
|
|
@ -948,7 +1194,8 @@ class CDM_CLASS_API ContentDecryptionModule_11 {
|
|||
// processed by UpdateSession(). The CDM must respond by calling either
|
||||
// Host::OnResolvePromise() or Host::OnRejectPromise() when the request has
|
||||
// been processed.
|
||||
virtual void RemoveSession(uint32_t promise_id, const char* session_id,
|
||||
virtual void RemoveSession(uint32_t promise_id,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size) = 0;
|
||||
|
||||
// Performs scheduled operation with |context| when the timer fires.
|
||||
|
|
@ -1052,7 +1299,8 @@ class CDM_CLASS_API ContentDecryptionModule_11 {
|
|||
// then |link_mask| and |output_protection_mask| are undefined and should
|
||||
// be ignored.
|
||||
virtual void OnQueryOutputProtectionStatus(
|
||||
QueryResult result, uint32_t link_mask,
|
||||
QueryResult result,
|
||||
uint32_t link_mask,
|
||||
uint32_t output_protection_mask) = 0;
|
||||
|
||||
// Called by the host after a call to Host::RequestStorageId(). If the
|
||||
|
|
@ -1063,15 +1311,16 @@ class CDM_CLASS_API ContentDecryptionModule_11 {
|
|||
// If the requested version is not available, null/zero will be provided as
|
||||
// |storage_id| and |storage_id_size|, respectively, and |version| should be
|
||||
// ignored.
|
||||
virtual void OnStorageId(uint32_t version, const uint8_t* storage_id,
|
||||
virtual void OnStorageId(uint32_t version,
|
||||
const uint8_t* storage_id,
|
||||
uint32_t storage_id_size) = 0;
|
||||
|
||||
// Destroys the object in the same context as it was created.
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
protected:
|
||||
ContentDecryptionModule_11() {}
|
||||
virtual ~ContentDecryptionModule_11() {}
|
||||
ContentDecryptionModule_12() {}
|
||||
virtual ~ContentDecryptionModule_12() {}
|
||||
};
|
||||
|
||||
class CDM_CLASS_API Host_10 {
|
||||
|
|
@ -1118,15 +1367,18 @@ class CDM_CLASS_API Host_10 {
|
|||
// ContentDecryptionModule calls that accept a |promise_id|.
|
||||
// |exception| must be specified. |error_message| and |system_code|
|
||||
// are optional. |error_message_size| should not include null termination.
|
||||
virtual void OnRejectPromise(uint32_t promise_id, Exception exception,
|
||||
uint32_t system_code, const char* error_message,
|
||||
virtual void OnRejectPromise(uint32_t promise_id,
|
||||
Exception exception,
|
||||
uint32_t system_code,
|
||||
const char* error_message,
|
||||
uint32_t error_message_size) = 0;
|
||||
|
||||
// Called by the CDM when it has a message for session |session_id|.
|
||||
// Size parameters should not include null termination.
|
||||
virtual void OnSessionMessage(const char* session_id,
|
||||
uint32_t session_id_size,
|
||||
MessageType message_type, const char* message,
|
||||
MessageType message_type,
|
||||
const char* message,
|
||||
uint32_t message_size) = 0;
|
||||
|
||||
// Called by the CDM when there has been a change in keys or their status for
|
||||
|
|
@ -1251,15 +1503,18 @@ class CDM_CLASS_API Host_11 {
|
|||
// ContentDecryptionModule calls that accept a |promise_id|.
|
||||
// |exception| must be specified. |error_message| and |system_code|
|
||||
// are optional. |error_message_size| should not include null termination.
|
||||
virtual void OnRejectPromise(uint32_t promise_id, Exception exception,
|
||||
uint32_t system_code, const char* error_message,
|
||||
virtual void OnRejectPromise(uint32_t promise_id,
|
||||
Exception exception,
|
||||
uint32_t system_code,
|
||||
const char* error_message,
|
||||
uint32_t error_message_size) = 0;
|
||||
|
||||
// Called by the CDM when it has a message for session |session_id|.
|
||||
// Size parameters should not include null termination.
|
||||
virtual void OnSessionMessage(const char* session_id,
|
||||
uint32_t session_id_size,
|
||||
MessageType message_type, const char* message,
|
||||
MessageType message_type,
|
||||
const char* message,
|
||||
uint32_t message_size) = 0;
|
||||
|
||||
// Called by the CDM when there has been a change in keys or their status for
|
||||
|
|
@ -1326,18 +1581,146 @@ class CDM_CLASS_API Host_11 {
|
|||
// CDM can call this method multiple times to operate on different files.
|
||||
virtual FileIO* CreateFileIO(FileIOClient* client) = 0;
|
||||
|
||||
// Requests a CdmProxy that proxies part of CDM functionalities to a different
|
||||
// entity, e.g. a hardware CDM module. A CDM instance can have at most one
|
||||
// CdmProxy throughout its lifetime, which must be requested and initialized
|
||||
// during CDM instance initialization time, i.e. in or after CDM::Initialize()
|
||||
// and before OnInitialized() is called, to ensure proper connection of the
|
||||
// CdmProxy and the media player (e.g. hardware decoder). The CdmProxy is
|
||||
// owned by the host and is guaranteed to be valid throughout the CDM
|
||||
// instance's lifetime. The CDM must ensure that the |client| remain valid
|
||||
// before the CDM instance is destroyed. Returns null if CdmProxy is not
|
||||
// supported, called before CDM::Initialize(), RequestCdmProxy() is called
|
||||
// more than once, or called after the CDM instance has been initialized.
|
||||
virtual CdmProxy* RequestCdmProxy(CdmProxyClient* client) = 0;
|
||||
// Requests a specific version of the storage ID. A storage ID is a stable,
|
||||
// device specific ID used by the CDM to securely store persistent data. The
|
||||
// ID will be returned by the host via ContentDecryptionModule::OnStorageId().
|
||||
// If |version| is 0, the latest version will be returned. All |version|s
|
||||
// that are greater than or equal to 0x80000000 are reserved for the CDM and
|
||||
// should not be supported or returned by the host. The CDM must not expose
|
||||
// the ID outside the client device, even in encrypted form.
|
||||
virtual void RequestStorageId(uint32_t version) = 0;
|
||||
|
||||
// Reports the metric |metric_name| with value |value| to the host. Can be
|
||||
// called by the CDM at any time. May report the same metric multiple times
|
||||
// during the lifetime of the CDM.
|
||||
virtual void ReportMetrics(MetricName metric_name, uint64_t value) = 0;
|
||||
|
||||
protected:
|
||||
Host_11() {}
|
||||
virtual ~Host_11() {}
|
||||
};
|
||||
|
||||
class CDM_CLASS_API Host_12 {
|
||||
public:
|
||||
static const int kVersion = 12;
|
||||
|
||||
// Returns a Buffer* containing non-zero members upon success, or NULL on
|
||||
// failure. The caller owns the Buffer* after this call. The buffer is not
|
||||
// guaranteed to be zero initialized. The capacity of the allocated Buffer
|
||||
// is guaranteed to be not less than |capacity|.
|
||||
virtual Buffer* Allocate(uint32_t capacity) = 0;
|
||||
|
||||
// Requests the host to call ContentDecryptionModule::TimerFired() |delay_ms|
|
||||
// from now with |context|.
|
||||
virtual void SetTimer(int64_t delay_ms, void* context) = 0;
|
||||
|
||||
// Returns the current wall time.
|
||||
virtual Time GetCurrentWallTime() = 0;
|
||||
|
||||
// Called by the CDM with the result after the CDM instance was initialized.
|
||||
virtual void OnInitialized(bool success) = 0;
|
||||
|
||||
// Called by the CDM when a key status is available in response to
|
||||
// GetStatusForPolicy().
|
||||
virtual void OnResolveKeyStatusPromise(uint32_t promise_id,
|
||||
KeyStatus key_status) = 0;
|
||||
|
||||
// Called by the CDM when a session is created or loaded and the value for the
|
||||
// MediaKeySession's sessionId attribute is available (|session_id|).
|
||||
// This must be called before OnSessionMessage() or
|
||||
// OnSessionKeysChange() is called for the same session. |session_id_size|
|
||||
// should not include null termination.
|
||||
// When called in response to LoadSession(), the |session_id| must be the
|
||||
// same as the |session_id| passed in LoadSession(), or NULL if the
|
||||
// session could not be loaded.
|
||||
virtual void OnResolveNewSessionPromise(uint32_t promise_id,
|
||||
const char* session_id,
|
||||
uint32_t session_id_size) = 0;
|
||||
|
||||
// Called by the CDM when a session is updated or released.
|
||||
virtual void OnResolvePromise(uint32_t promise_id) = 0;
|
||||
|
||||
// Called by the CDM when an error occurs as a result of one of the
|
||||
// ContentDecryptionModule calls that accept a |promise_id|.
|
||||
// |exception| must be specified. |error_message| and |system_code|
|
||||
// are optional. |error_message_size| should not include null termination.
|
||||
virtual void OnRejectPromise(uint32_t promise_id,
|
||||
Exception exception,
|
||||
uint32_t system_code,
|
||||
const char* error_message,
|
||||
uint32_t error_message_size) = 0;
|
||||
|
||||
// Called by the CDM when it has a message for session |session_id|.
|
||||
// Size parameters should not include null termination.
|
||||
virtual void OnSessionMessage(const char* session_id,
|
||||
uint32_t session_id_size,
|
||||
MessageType message_type,
|
||||
const char* message,
|
||||
uint32_t message_size) = 0;
|
||||
|
||||
// Called by the CDM when there has been a change in keys or their status for
|
||||
// session |session_id|. |has_additional_usable_key| should be set if a
|
||||
// key is newly usable (e.g. new key available, previously expired key has
|
||||
// been renewed, etc.) and the browser should attempt to resume playback.
|
||||
// |keys_info| is the list of key IDs for this session along with their
|
||||
// current status. |keys_info_count| is the number of entries in |keys_info|.
|
||||
// Size parameter for |session_id| should not include null termination.
|
||||
virtual void OnSessionKeysChange(const char* session_id,
|
||||
uint32_t session_id_size,
|
||||
bool has_additional_usable_key,
|
||||
const KeyInformation* keys_info,
|
||||
uint32_t keys_info_count) = 0;
|
||||
|
||||
// Called by the CDM when there has been a change in the expiration time for
|
||||
// session |session_id|. This can happen as the result of an Update() call
|
||||
// or some other event. If this happens as a result of a call to Update(),
|
||||
// it must be called before resolving the Update() promise. |new_expiry_time|
|
||||
// represents the time after which the key(s) in the session will no longer
|
||||
// be usable for decryption. It can be 0 if no such time exists or if the
|
||||
// license explicitly never expires. Size parameter should not include null
|
||||
// termination.
|
||||
virtual void OnExpirationChange(const char* session_id,
|
||||
uint32_t session_id_size,
|
||||
Time new_expiry_time) = 0;
|
||||
|
||||
// Called by the CDM when session |session_id| is closed. Size
|
||||
// parameter should not include null termination.
|
||||
virtual void OnSessionClosed(const char* session_id,
|
||||
uint32_t session_id_size) = 0;
|
||||
|
||||
// The following are optional methods that may not be implemented on all
|
||||
// platforms.
|
||||
|
||||
// Sends a platform challenge for the given |service_id|. |challenge| is at
|
||||
// most 256 bits of data to be signed. Once the challenge has been completed,
|
||||
// the host will call ContentDecryptionModule::OnPlatformChallengeResponse()
|
||||
// with the signed challenge response and platform certificate. Size
|
||||
// parameters should not include null termination.
|
||||
virtual void SendPlatformChallenge(const char* service_id,
|
||||
uint32_t service_id_size,
|
||||
const char* challenge,
|
||||
uint32_t challenge_size) = 0;
|
||||
|
||||
// Attempts to enable output protection (e.g. HDCP) on the display link. The
|
||||
// |desired_protection_mask| is a bit mask of OutputProtectionMethods. No
|
||||
// status callback is issued, the CDM must call QueryOutputProtectionStatus()
|
||||
// periodically to ensure the desired protections are applied.
|
||||
virtual void EnableOutputProtection(uint32_t desired_protection_mask) = 0;
|
||||
|
||||
// Requests the current output protection status. Once the host has the status
|
||||
// it will call ContentDecryptionModule::OnQueryOutputProtectionStatus().
|
||||
virtual void QueryOutputProtectionStatus() = 0;
|
||||
|
||||
// Must be called by the CDM if it returned kDeferredInitialization during
|
||||
// InitializeAudioDecoder() or InitializeVideoDecoder().
|
||||
virtual void OnDeferredInitializationDone(StreamType stream_type,
|
||||
Status decoder_status) = 0;
|
||||
|
||||
// Creates a FileIO object from the host to do file IO operation. Returns NULL
|
||||
// if a FileIO object cannot be obtained. Once a valid FileIO object is
|
||||
// returned, |client| must be valid until FileIO::Close() is called. The
|
||||
// CDM can call this method multiple times to operate on different files.
|
||||
virtual FileIO* CreateFileIO(FileIOClient* client) = 0;
|
||||
|
||||
// Requests a specific version of the storage ID. A storage ID is a stable,
|
||||
// device specific ID used by the CDM to securely store persistent data. The
|
||||
|
|
@ -1348,9 +1731,14 @@ class CDM_CLASS_API Host_11 {
|
|||
// the ID outside the client device, even in encrypted form.
|
||||
virtual void RequestStorageId(uint32_t version) = 0;
|
||||
|
||||
// Reports the metric |metric_name| with value |value| to the host. Can be
|
||||
// called by the CDM at any time. May report the same metric multiple times
|
||||
// during the lifetime of the CDM.
|
||||
virtual void ReportMetrics(MetricName metric_name, uint64_t value) = 0;
|
||||
|
||||
protected:
|
||||
Host_11() {}
|
||||
virtual ~Host_11() {}
|
||||
Host_12() {}
|
||||
virtual ~Host_12() {}
|
||||
};
|
||||
|
||||
} // namespace cdm
|
||||
|
|
|
|||
|
|
@ -1,121 +0,0 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
#ifndef CDM_CONTENT_DECRYPTION_MODULE_PROXY_H_
|
||||
#define CDM_CONTENT_DECRYPTION_MODULE_PROXY_H_
|
||||
|
||||
#include "content_decryption_module_export.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
namespace cdm {
|
||||
|
||||
class CDM_CLASS_API CdmProxyClient;
|
||||
|
||||
// A proxy class for the CDM.
|
||||
// In general, the interpretation of the CdmProxy and CdmProxyClient method
|
||||
// parameters are protocol dependent. For enum parameters, values outside the
|
||||
// enum range may not work.
|
||||
class CDM_CLASS_API CdmProxy {
|
||||
public:
|
||||
enum Function : uint32_t {
|
||||
// For Intel Negotiate Crypto SessionKey Exchange (CSME) path to call
|
||||
// ID3D11VideoContext::NegotiateCryptoSessionKeyExchange.
|
||||
kIntelNegotiateCryptoSessionKeyExchange = 1,
|
||||
// There will be more values in the future e.g. for D3D11 RSA method.
|
||||
};
|
||||
|
||||
enum KeyType : uint32_t {
|
||||
kDecryptOnly = 0,
|
||||
kDecryptAndDecode = 1,
|
||||
};
|
||||
|
||||
// Initializes the proxy. The results will be returned in
|
||||
// CdmProxyClient::OnInitialized().
|
||||
virtual void Initialize() = 0;
|
||||
|
||||
// Processes and updates the state of the proxy.
|
||||
// |output_data_size| is required by some protocol to set up the output data.
|
||||
// The operation may fail if the |output_data_size| is wrong. The results will
|
||||
// be returned in CdmProxyClient::OnProcessed().
|
||||
virtual void Process(Function function, uint32_t crypto_session_id,
|
||||
const uint8_t* input_data, uint32_t input_data_size,
|
||||
uint32_t output_data_size) = 0;
|
||||
|
||||
// Creates a crypto session for handling media.
|
||||
// If extra data has to be passed to further setup the media crypto session,
|
||||
// pass the data as |input_data|. The results will be returned in
|
||||
// CdmProxyClient::OnMediaCryptoSessionCreated().
|
||||
virtual void CreateMediaCryptoSession(const uint8_t* input_data,
|
||||
uint32_t input_data_size) = 0;
|
||||
|
||||
// Sets a key for the session identified by |crypto_session_id|.
|
||||
virtual void SetKey(uint32_t crypto_session_id, const uint8_t* key_id,
|
||||
uint32_t key_id_size, KeyType key_type,
|
||||
const uint8_t* key_blob, uint32_t key_blob_size) = 0;
|
||||
|
||||
// Removes a key for the session identified by |crypto_session_id|.
|
||||
virtual void RemoveKey(uint32_t crypto_session_id, const uint8_t* key_id,
|
||||
uint32_t key_id_size) = 0;
|
||||
|
||||
protected:
|
||||
CdmProxy() {}
|
||||
virtual ~CdmProxy() {}
|
||||
};
|
||||
|
||||
// Responses to CdmProxy calls. All responses will be called asynchronously.
|
||||
class CDM_CLASS_API CdmProxyClient {
|
||||
public:
|
||||
enum Status : uint32_t {
|
||||
kOk,
|
||||
kFail,
|
||||
};
|
||||
|
||||
enum Protocol : uint32_t {
|
||||
kNone = 0, // No protocol supported. Can be used in failure cases.
|
||||
kIntel, // Method using Intel CSME.
|
||||
// There will be more values in the future e.g. kD3D11RsaHardware,
|
||||
// kD3D11RsaSoftware to use the D3D11 RSA method.
|
||||
};
|
||||
|
||||
// Callback for Initialize(). If the proxy created a crypto session, then the
|
||||
// ID for the crypto session is |crypto_session_id|.
|
||||
virtual void OnInitialized(Status status, Protocol protocol,
|
||||
uint32_t crypto_session_id) = 0;
|
||||
|
||||
// Callback for Process(). |output_data| is the output of processing.
|
||||
virtual void OnProcessed(Status status, const uint8_t* output_data,
|
||||
uint32_t output_data_size) = 0;
|
||||
|
||||
// Callback for CreateMediaCryptoSession(). On success:
|
||||
// - |crypto_session_id| is the ID for the created crypto session.
|
||||
// - |output_data| is extra value, if any.
|
||||
// Otherwise, |crypto_session_id| and |output_data| should be ignored.
|
||||
virtual void OnMediaCryptoSessionCreated(Status status,
|
||||
uint32_t crypto_session_id,
|
||||
uint64_t output_data) = 0;
|
||||
|
||||
// Callback for SetKey().
|
||||
virtual void OnKeySet(Status status) = 0;
|
||||
|
||||
// Callback for RemoveKey().
|
||||
virtual void OnKeyRemoved(Status status) = 0;
|
||||
|
||||
// Called when there is a hardware reset and all the hardware context is lost.
|
||||
virtual void NotifyHardwareReset() = 0;
|
||||
|
||||
protected:
|
||||
CdmProxyClient() {}
|
||||
virtual ~CdmProxyClient() {}
|
||||
};
|
||||
|
||||
} // namespace cdm
|
||||
|
||||
#endif // CDM_CONTENT_DECRYPTION_MODULE_PROXY_H_
|
||||
|
|
@ -10,7 +10,14 @@ SOURCES += [
|
|||
"WidevineVideoFrame.cpp",
|
||||
]
|
||||
|
||||
EXPORTS += ["WidevineFileIO.h", "WidevineUtils.h", "WidevineVideoFrame.h"]
|
||||
EXPORTS += [
|
||||
"content_decryption_module.h",
|
||||
"content_decryption_module_export.h",
|
||||
"content_decryption_module_ext.h",
|
||||
"WidevineFileIO.h",
|
||||
"WidevineUtils.h",
|
||||
"WidevineVideoFrame.h",
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = "xul"
|
||||
|
||||
|
|
|
|||
|
|
@ -16,24 +16,36 @@ namespace mozilla::dom {
|
|||
// https://streams.spec.whatwg.org/#transfer-array-buffer
|
||||
// As some parts of the specifcation want to use the abrupt completion value,
|
||||
// this function may leave a pending exception if it returns nullptr.
|
||||
//
|
||||
// This can be called with a CCW to an ArrayBuffer Object as we handle the
|
||||
// case explicitly.
|
||||
JSObject* TransferArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aObject) {
|
||||
MOZ_ASSERT(JS::IsArrayBufferObject(aObject));
|
||||
|
||||
// Step 1.
|
||||
MOZ_ASSERT(!JS::IsDetachedArrayBufferObject(aObject));
|
||||
|
||||
// Step 3 (Reordered)
|
||||
size_t bufferLength = JS::GetArrayBufferByteLength(aObject);
|
||||
|
||||
// Step 2 (Reordered)
|
||||
UniquePtr<void, JS::FreePolicy> bufferData{
|
||||
JS::StealArrayBufferContents(aCx, aObject)};
|
||||
|
||||
// Step 4.
|
||||
if (!JS::DetachArrayBuffer(aCx, aObject)) {
|
||||
JS::Rooted<JSObject*> unwrappedObj(aCx, JS::UnwrapArrayBuffer(aObject));
|
||||
if (!unwrappedObj) {
|
||||
js::ReportAccessDenied(aCx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t bufferLength = 0;
|
||||
UniquePtr<void, JS::FreePolicy> bufferData;
|
||||
{
|
||||
JSAutoRealm ar(aCx, unwrappedObj);
|
||||
|
||||
// Step 1.
|
||||
MOZ_ASSERT(!JS::IsDetachedArrayBufferObject(unwrappedObj));
|
||||
|
||||
// Step 3 (Reordered)
|
||||
bufferLength = JS::GetArrayBufferByteLength(unwrappedObj);
|
||||
|
||||
// Step 2 (Reordered)
|
||||
bufferData.reset(JS::StealArrayBufferContents(aCx, unwrappedObj));
|
||||
|
||||
// Step 4.
|
||||
if (!JS::DetachArrayBuffer(aCx, unwrappedObj)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
return JS::NewArrayBufferWithContents(aCx, bufferLength,
|
||||
std::move(bufferData));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue