Bug 1315850 - Implement ChromiumCDMProxy initialization. r=gerald

This means the MediaKeys is able to create a CDM.

MozReview-Commit-ID: 94Xc7sCLhH3

--HG--
extra : rebase_source : 914db1f04e0770776ae25c7b8bdc59e729fe78d0
This commit is contained in:
Chris Pearce 2017-03-09 11:29:45 +13:00
Родитель 1d0fde26c0
Коммит a987efe1ed
5 изменённых файлов: 147 добавлений и 4 удалений

Просмотреть файл

@ -6,15 +6,28 @@
#include "ChromiumCDMParent.h"
#include "mozilla/gmp/GMPTypes.h"
#include "GMPContentChild.h"
#include "mozilla/Unused.h"
#include "ChromiumCDMProxy.h"
namespace mozilla {
namespace gmp {
ChromiumCDMParent::ChromiumCDMParent(GMPContentParent* aContentParent)
: mContentParent(aContentParent)
ChromiumCDMParent::ChromiumCDMParent(GMPContentParent* aContentParent,
uint32_t aPluginId)
: mPluginId(aPluginId)
, mContentParent(aContentParent)
{
}
bool
ChromiumCDMParent::Init(ChromiumCDMProxy* aProxy,
bool aAllowDistinctiveIdentifier,
bool aAllowPersistentState)
{
mProxy = aProxy;
return SendInit(aAllowDistinctiveIdentifier, aAllowPersistentState);
}
ipc::IPCResult
ChromiumCDMParent::Recv__delete__()
{

Просмотреть файл

@ -13,6 +13,9 @@
#include "mozilla/RefPtr.h"
namespace mozilla {
class ChromiumCDMProxy;
namespace gmp {
class GMPContentParent;
@ -24,7 +27,13 @@ class ChromiumCDMParent final
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ChromiumCDMParent)
explicit ChromiumCDMParent(GMPContentParent* aContentParent);
ChromiumCDMParent(GMPContentParent* aContentParent, uint32_t aPluginId);
uint32_t PluginId() const { return mPluginId; }
bool Init(ChromiumCDMProxy* aProxy,
bool aAllowDistinctiveIdentifier,
bool aAllowPersistentState);
// TODO: Add functions for clients to send data to CDM, and
// a Close() function.
@ -62,7 +71,12 @@ protected:
ipc::IPCResult RecvShutdown() override;
void ActorDestroy(ActorDestroyReason aWhy) override;
const uint32_t mPluginId;
GMPContentParent* mContentParent;
// Note: this pointer is a weak reference because otherwise it would cause
// a cycle, as ChromiumCDMProxy has a strong reference to the
// ChromiumCDMParent.
ChromiumCDMProxy* mProxy = nullptr;
};
} // namespace gmp

Просмотреть файл

@ -6,6 +6,8 @@
#include "ChromiumCDMProxy.h"
#include "GMPUtils.h"
#include "nsPrintfCString.h"
#include "GMPService.h"
namespace mozilla {
@ -39,6 +41,95 @@ ChromiumCDMProxy::Init(PromiseId aPromiseId,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
EME_LOG("ChromiumCDMProxy::Init(%s, %s)",
NS_ConvertUTF16toUTF8(aOrigin).get(),
NS_ConvertUTF16toUTF8(aTopLevelOrigin).get());
if (!mGMPThread) {
RejectPromise(
aPromiseId,
NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Couldn't get GMP thread ChromiumCDMProxy::Init"));
return;
}
if (aGMPName.IsEmpty()) {
RejectPromise(aPromiseId,
NS_ERROR_DOM_INVALID_STATE_ERR,
nsPrintfCString("Unknown GMP for keysystem '%s'",
NS_ConvertUTF16toUTF8(mKeySystem).get()));
return;
}
gmp::NodeId nodeId(aOrigin, aTopLevelOrigin, aGMPName);
RefPtr<AbstractThread> thread = mGMPThread;
RefPtr<GMPCrashHelper> helper(mCrashHelper);
RefPtr<ChromiumCDMProxy> self(this);
nsCString keySystem = NS_ConvertUTF16toUTF8(mKeySystem);
RefPtr<Runnable> task(NS_NewRunnableFunction(
[self, nodeId, helper, aPromiseId, thread, keySystem]() -> void {
MOZ_ASSERT(self->IsOnOwnerThread());
RefPtr<gmp::GeckoMediaPluginService> service =
gmp::GeckoMediaPluginService::GetGeckoMediaPluginService();
if (!service) {
self->RejectPromise(
aPromiseId,
NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING(
"Couldn't get GeckoMediaPluginService in ChromiumCDMProxy::Init"));
return;
}
RefPtr<gmp::GetCDMParentPromise> promise =
service->GetCDM(nodeId, { keySystem }, helper);
promise->Then(
thread,
__func__,
[self, aPromiseId](RefPtr<gmp::ChromiumCDMParent> cdm) {
if (!cdm->Init(self,
self->mDistinctiveIdentifierRequired,
self->mPersistentStateRequired)) {
self->RejectPromise(aPromiseId,
NS_ERROR_FAILURE,
NS_LITERAL_CSTRING("GetCDM failed."));
return;
}
self->mCDM = cdm;
self->OnCDMCreated(aPromiseId);
},
[self, aPromiseId](nsresult rv) {
self->RejectPromise(
aPromiseId, NS_ERROR_FAILURE, NS_LITERAL_CSTRING("GetCDM failed."));
});
}));
mGMPThread->Dispatch(task.forget());
}
void
ChromiumCDMProxy::OnCDMCreated(uint32_t aPromiseId)
{
EME_LOG("ChromiumCDMProxy::OnCDMCreated(pid=%u) isMainThread=%d this=%p",
aPromiseId,
NS_IsMainThread(),
this);
if (!NS_IsMainThread()) {
mMainThread->Dispatch(NewRunnableMethod<PromiseId>(
this, &ChromiumCDMProxy::OnCDMCreated, aPromiseId),
NS_DISPATCH_NORMAL);
return;
}
// This should only be called once the CDM has been created.
MOZ_ASSERT(mCDM);
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
return;
}
mKeys->OnCDMCreated(aPromiseId, mCDM->PluginId());
}
#ifdef DEBUG
@ -98,11 +189,34 @@ ChromiumCDMProxy::RejectPromise(PromiseId aId,
nsresult aCode,
const nsCString& aReason)
{
if (!NS_IsMainThread()) {
nsCOMPtr<nsIRunnable> task;
task = NewRunnableMethod<PromiseId, nsresult, nsCString>(
this, &ChromiumCDMProxy::RejectPromise, aId, aCode, aReason);
NS_DispatchToMainThread(task);
return;
}
if (!mKeys.IsNull()) {
mKeys->RejectPromise(aId, aCode, aReason);
}
}
void
ChromiumCDMProxy::ResolvePromise(PromiseId aId)
{
if (!NS_IsMainThread()) {
nsCOMPtr<nsIRunnable> task;
task = NewRunnableMethod<PromiseId>(
this, &ChromiumCDMProxy::ResolvePromise, aId);
NS_DispatchToMainThread(task);
return;
}
if (!mKeys.IsNull()) {
mKeys->ResolvePromise(aId);
} else {
NS_WARNING("ChromiumCDMProxy unable to resolve promise!");
}
}
const nsCString&

Просмотреть файл

@ -108,6 +108,8 @@ public:
#endif
private:
void OnCDMCreated(uint32_t aPromiseId);
~ChromiumCDMProxy();
GMPCrashHelper* mCrashHelper;

Просмотреть файл

@ -243,7 +243,7 @@ GMPContentParent::GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE)
PChromiumCDMParent*
GMPContentParent::AllocPChromiumCDMParent()
{
ChromiumCDMParent* parent = new ChromiumCDMParent(this);
ChromiumCDMParent* parent = new ChromiumCDMParent(this, GetPluginId());
NS_ADDREF(parent);
return parent;
}