mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1016162 - Base EME DOM APIs, not connected to a CDM yet. r=bz
This commit is contained in:
parent
a0f8826cb9
commit
3c3777d2de
@ -1565,6 +1565,8 @@ pref("identity.fxaccounts.settings.uri", "https://accounts.firefox.com/settings"
|
||||
pref("ui.key.menuAccessKeyFocuses", true);
|
||||
#endif
|
||||
|
||||
// Encrypted media extensions.
|
||||
pref("media.eme.enabled", false);
|
||||
|
||||
// Delete HTTP cache v2 data of users that didn't opt-in manually
|
||||
pref("browser.cache.auto_delete_cache_version", 1);
|
||||
|
@ -497,6 +497,7 @@ GK_ATOM(keydown, "keydown")
|
||||
GK_ATOM(keygen, "keygen")
|
||||
GK_ATOM(keypress, "keypress")
|
||||
GK_ATOM(keyset, "keyset")
|
||||
GK_ATOM(keysystem, "keysystem")
|
||||
GK_ATOM(keytext, "keytext")
|
||||
GK_ATOM(keyup, "keyup")
|
||||
GK_ATOM(kind, "kind")
|
||||
@ -1944,6 +1945,8 @@ GK_ATOM(oncuechange, "oncuechange")
|
||||
GK_ATOM(oncurrentchange, "oncurrentchange")
|
||||
GK_ATOM(onenter, "onenter")
|
||||
GK_ATOM(onexit, "onexit")
|
||||
GK_ATOM(onneedkey, "onneedkey")
|
||||
GK_ATOM(needkey, "needkey")
|
||||
GK_ATOM(onremovetrack, "onremovetrack")
|
||||
GK_ATOM(loadstart, "loadstart")
|
||||
GK_ATOM(suspend, "suspend")
|
||||
|
@ -20,6 +20,16 @@
|
||||
#include "mozilla/dom/AudioChannelBinding.h"
|
||||
#include "mozilla/dom/TextTrackManager.h"
|
||||
#include "MediaDecoder.h"
|
||||
#include "mozilla/dom/MediaKeys.h"
|
||||
|
||||
// Something on Linux #defines None, which is an entry in the
|
||||
// MediaWaitingFor enum, so undef it here before including the binfing,
|
||||
// so that the build doesn't fail...
|
||||
#ifdef None
|
||||
#undef None
|
||||
#endif
|
||||
|
||||
#include "mozilla/dom/HTMLMediaElementBinding.h"
|
||||
|
||||
// Define to output information on decoding and painting framerate
|
||||
/* #define DEBUG_FRAME_RATE 1 */
|
||||
@ -37,6 +47,7 @@ class MediaResource;
|
||||
class MediaDecoder;
|
||||
class VideoFrameContainer;
|
||||
namespace dom {
|
||||
class MediaKeys;
|
||||
class TextTrack;
|
||||
class TimeRanges;
|
||||
class WakeLock;
|
||||
@ -478,6 +489,22 @@ public:
|
||||
|
||||
// XPCOM MozPreservesPitch() is OK
|
||||
|
||||
MediaKeys* GetMediaKeys() const;
|
||||
|
||||
already_AddRefed<Promise> SetMediaKeys(MediaKeys* mediaKeys,
|
||||
ErrorResult& aRv);
|
||||
|
||||
MediaWaitingFor WaitingFor() const;
|
||||
|
||||
mozilla::dom::EventHandlerNonNull* GetOnneedkey();
|
||||
void SetOnneedkey(mozilla::dom::EventHandlerNonNull* listener);
|
||||
|
||||
void DispatchNeedKey(const nsTArray<uint8_t>& aInitData,
|
||||
const nsAString& aInitDataType);
|
||||
|
||||
|
||||
bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
|
||||
|
||||
bool MozAutoplayEnabled() const
|
||||
{
|
||||
return mAutoplayEnabled;
|
||||
@ -1010,6 +1037,9 @@ protected:
|
||||
// Range of time played.
|
||||
nsRefPtr<TimeRanges> mPlayed;
|
||||
|
||||
// Encrypted Media Extension media keys.
|
||||
nsRefPtr<MediaKeys> mMediaKeys;
|
||||
|
||||
// Stores the time at the start of the current 'played' range.
|
||||
double mCurrentPlayRangeStart;
|
||||
|
||||
@ -1139,6 +1169,8 @@ protected:
|
||||
nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
|
||||
|
||||
nsRefPtr<TextTrackManager> mTextTrackManager;
|
||||
|
||||
MediaWaitingFor mWaitingFor;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "mozilla/dom/ElementInlines.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/dom/MediaKeyNeededEvent.h"
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "nsIDOMHTMLMediaElement.h"
|
||||
@ -423,6 +425,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTM
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlayed);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeys)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
|
||||
@ -439,10 +442,11 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLE
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioChannelAgent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
|
||||
for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) {
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputStreams[i].mStream);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputStreams[i].mStream)
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlayed);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlayed)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextTrackManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaKeys)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLMediaElement)
|
||||
@ -895,6 +899,9 @@ void HTMLMediaElement::LoadFromSourceChildren()
|
||||
ReportLoadError("MediaLoadUnsupportedTypeAttribute", params, ArrayLength(params));
|
||||
continue;
|
||||
}
|
||||
// TODO: "If candidate has a keySystem attribute whose value represents a
|
||||
// Key System that the user agent knows it cannot use with type,
|
||||
// then end the synchronous section[...]" (Bug 1016707)
|
||||
nsAutoString media;
|
||||
if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::media, media) && !media.IsEmpty()) {
|
||||
nsCSSParser cssParser;
|
||||
@ -2003,7 +2010,8 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<nsINodeInfo>& aNodeInfo)
|
||||
mHasAudio(false),
|
||||
mDownloadSuspendedByCache(false),
|
||||
mAudioChannelFaded(false),
|
||||
mPlayingThroughTheAudioChannel(false)
|
||||
mPlayingThroughTheAudioChannel(false),
|
||||
mWaitingFor(MediaWaitingFor::None)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (!gMediaElementLog) {
|
||||
@ -3894,6 +3902,72 @@ NS_IMETHODIMP HTMLMediaElement::CanPlayChanged(int32_t canPlay)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MediaKeys*
|
||||
HTMLMediaElement::GetMediaKeys() const
|
||||
{
|
||||
return mMediaKeys;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global =
|
||||
do_QueryInterface(OwnerDoc()->GetInnerWindow());
|
||||
if (!global) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
// TODO: Need to shutdown existing MediaKeys instance? bug 1016709.
|
||||
nsRefPtr<Promise> promise = new Promise(global);
|
||||
if (mMediaKeys != aMediaKeys) {
|
||||
mMediaKeys = aMediaKeys;
|
||||
}
|
||||
promise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
MediaWaitingFor
|
||||
HTMLMediaElement::WaitingFor() const
|
||||
{
|
||||
return mWaitingFor;
|
||||
}
|
||||
|
||||
EventHandlerNonNull*
|
||||
HTMLMediaElement::GetOnneedkey()
|
||||
{
|
||||
EventListenerManager *elm = GetExistingListenerManager();
|
||||
return elm ? elm->GetEventHandler(nsGkAtoms::onneedkey, EmptyString())
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::SetOnneedkey(EventHandlerNonNull* handler)
|
||||
{
|
||||
EventListenerManager *elm = GetOrCreateListenerManager();
|
||||
if (elm) {
|
||||
elm->SetEventHandler(nsGkAtoms::onneedkey, EmptyString(), handler);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::DispatchNeedKey(const nsTArray<uint8_t>& aInitData,
|
||||
const nsAString& aInitDataType)
|
||||
{
|
||||
nsRefPtr<MediaKeyNeededEvent> event(
|
||||
MediaKeyNeededEvent::Constructor(this, aInitDataType, aInitData));
|
||||
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
|
||||
new AsyncEventDispatcher(this, event);
|
||||
asyncDispatcher->PostDOMEvent();
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLMediaElement::IsEventAttributeName(nsIAtom* aName)
|
||||
{
|
||||
return aName == nsGkAtoms::onneedkey ||
|
||||
nsGenericHTMLElement::IsEventAttributeName(aName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::WindowVolumeChanged()
|
||||
{
|
||||
SetVolumeInternal();
|
||||
|
@ -64,6 +64,16 @@ public:
|
||||
SetHTMLAttr(nsGkAtoms::media, aMedia, rv);
|
||||
}
|
||||
|
||||
void GetKeySystem(nsString& aKeySystem) const
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::keysystem, aKeySystem);
|
||||
}
|
||||
|
||||
void SetKeySystem(const nsAString& aKeySystem)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::keysystem, aKeySystem);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual JSObject* WrapNode(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
|
199
content/media/eme/CDMProxy.cpp
Normal file
199
content/media/eme/CDMProxy.cpp
Normal file
@ -0,0 +1,199 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/CDMProxy.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/dom/MediaKeys.h"
|
||||
#include "mozilla/dom/MediaKeySession.h"
|
||||
#include "mozIGeckoMediaPluginService.h"
|
||||
#include "nsContentCID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "MainThreadUtils.h"
|
||||
|
||||
// TODO: Change the functions in this file to do IPC via the Gecko Media
|
||||
// Plugins API. In the meantime, the code here merely implements the
|
||||
// interface we expect will be required when the IPC is working.
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
CDMProxy::CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem)
|
||||
: mKeys(aKeys)
|
||||
, mKeySystem(aKeySystem)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_COUNT_CTOR(CDMProxy);
|
||||
}
|
||||
|
||||
CDMProxy::~CDMProxy()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CDMProxy);
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::Init(PromiseId aPromiseId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mGMPThread) {
|
||||
nsCOMPtr<mozIGeckoMediaPluginService> mps =
|
||||
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
|
||||
if (!mps) {
|
||||
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
mps->GetThread(getter_AddRefs(mGMPThread));
|
||||
if (!mGMPThread) {
|
||||
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Dispatch task to GMPThread to initialize CDM via IPC.
|
||||
|
||||
mKeys->OnCDMCreated(aPromiseId);
|
||||
}
|
||||
|
||||
static int sFakeSessionIdNum = 0;
|
||||
|
||||
void
|
||||
CDMProxy::CreateSession(dom::SessionType aSessionType,
|
||||
PromiseId aPromiseId,
|
||||
const nsAString& aInitDataType,
|
||||
const Uint8Array& aInitData)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mGMPThread);
|
||||
|
||||
// TODO: Dispatch task to GMPThread to call CDM CreateSession via IPC.
|
||||
|
||||
// Make a fake session id. We'll get this from the CDM normally.
|
||||
nsAutoString id;
|
||||
id.AppendASCII("FakeSessionId_");
|
||||
id.AppendInt(sFakeSessionIdNum++);
|
||||
|
||||
mKeys->OnSessionActivated(aPromiseId, id);
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::LoadSession(PromiseId aPromiseId,
|
||||
const nsAString& aSessionId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mGMPThread);
|
||||
|
||||
// TODO: Dispatch task to GMPThread to call CDM LoadSession via IPC.
|
||||
// make MediaKeys::mPendingSessions CC'd
|
||||
|
||||
mKeys->OnSessionActivated(aPromiseId, aSessionId);
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::SetServerCertificate(PromiseId aPromiseId,
|
||||
const Uint8Array& aCertData)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mGMPThread);
|
||||
|
||||
// TODO: Dispatch task to GMPThread to call CDM SetServerCertificate via IPC.
|
||||
|
||||
ResolvePromise(aPromiseId);
|
||||
}
|
||||
|
||||
static int sUpdateCount = 0;
|
||||
|
||||
void
|
||||
CDMProxy::UpdateSession(const nsAString& aSessionId,
|
||||
PromiseId aPromiseId,
|
||||
const Uint8Array& aResponse)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mGMPThread);
|
||||
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
|
||||
|
||||
// TODO: Dispatch task to GMPThread to call CDM UpdateSession via IPC.
|
||||
|
||||
nsRefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
|
||||
nsAutoCString str(NS_LITERAL_CSTRING("Update_"));
|
||||
str.AppendInt(sUpdateCount++);
|
||||
nsTArray<uint8_t> msg;
|
||||
msg.AppendElements(str.get(), str.Length());
|
||||
session->DispatchKeyMessage(msg, NS_LITERAL_STRING("http://bogus.url"));
|
||||
ResolvePromise(aPromiseId);
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::CloseSession(const nsAString& aSessionId,
|
||||
PromiseId aPromiseId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
|
||||
|
||||
// TODO: Dispatch task to GMPThread to call CDM CloseSession via IPC.
|
||||
|
||||
nsRefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
|
||||
|
||||
// Pretend that the CDM actually does close the session...
|
||||
// "...the [MediaKeySession's] closed attribute promise is resolved
|
||||
// when the session is closed."
|
||||
session->OnClosed();
|
||||
|
||||
// "The promise is resolved when the request has been processed."
|
||||
ResolvePromise(aPromiseId);
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::RemoveSession(const nsAString& aSessionId,
|
||||
PromiseId aPromiseId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// TODO: Dispatch task to GMPThread to call CDM RemoveSession via IPC.
|
||||
|
||||
// Assume CDM immediately removes session's data, then close the session
|
||||
// as per the spec.
|
||||
CloseSession(aSessionId, aPromiseId);
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mKeys.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::RejectPromise(PromiseId aId, nsresult aCode)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
if (!mKeys.IsNull()) {
|
||||
mKeys->RejectPromise(aId, aCode);
|
||||
} else {
|
||||
NS_WARNING("CDMProxy unable to reject promise!");
|
||||
}
|
||||
} else {
|
||||
nsRefPtr<nsIRunnable> task(new RejectPromiseTask(this, aId, aCode));
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::ResolvePromise(PromiseId aId)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
if (!mKeys.IsNull()) {
|
||||
mKeys->ResolvePromise(aId);
|
||||
} else {
|
||||
NS_WARNING("CDMProxy unable to resolve promise!");
|
||||
}
|
||||
} else {
|
||||
nsRefPtr<nsIRunnable> task;
|
||||
task = NS_NewRunnableMethodWithArg<PromiseId>(this,
|
||||
&CDMProxy::ResolvePromise,
|
||||
aId);
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
171
content/media/eme/CDMProxy.h
Normal file
171
content/media/eme/CDMProxy.h
Normal file
@ -0,0 +1,171 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 CDMProxy_h_
|
||||
#define CDMProxy_h_
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "mozilla/dom/MediaKeys.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
|
||||
class nsIThread;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class MediaKeySession;
|
||||
}
|
||||
|
||||
// A placeholder proxy to the CDM.
|
||||
// TODO: The functions here need to do IPC to talk to the CDM via the
|
||||
// Gecko Media Plugin API, which we'll need to extend for H.264 and EME
|
||||
// content.
|
||||
// Note: Promises are passed in via a PromiseId, so that the ID can be
|
||||
// passed via IPC to the CDM, which can then signal when to reject or
|
||||
// resolve the promise using its PromiseId.
|
||||
class CDMProxy {
|
||||
typedef dom::PromiseId PromiseId;
|
||||
typedef dom::SessionType SessionType;
|
||||
typedef dom::Uint8Array Uint8Array;
|
||||
public:
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMProxy)
|
||||
|
||||
// Main thread only.
|
||||
CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem);
|
||||
|
||||
// Main thread only.
|
||||
// Loads the CDM corresponding to mKeySystem.
|
||||
// Calls MediaKeys::OnCDMCreated() when the CDM is created.
|
||||
void Init(PromiseId aPromiseId);
|
||||
|
||||
// Main thread only.
|
||||
// Uses the CDM to create a key session.
|
||||
// Caller is responsible for calling aInitData.ComputeLengthAndData().
|
||||
// Calls MediaKeys::OnSessionActivated() when session is created.
|
||||
void CreateSession(dom::SessionType aSessionType,
|
||||
PromiseId aPromiseId,
|
||||
const nsAString& aInitDataType,
|
||||
const Uint8Array& aInitData);
|
||||
|
||||
// Main thread only.
|
||||
// Uses the CDM to load a presistent session stored on disk.
|
||||
// Calls MediaKeys::OnSessionActivated() when session is loaded.
|
||||
void LoadSession(PromiseId aPromiseId,
|
||||
const nsAString& aSessionId);
|
||||
|
||||
// Main thread only.
|
||||
// Sends a new certificate to the CDM.
|
||||
// Caller is responsible for calling aCert.ComputeLengthAndData().
|
||||
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
|
||||
// processed the request.
|
||||
void SetServerCertificate(PromiseId aPromiseId,
|
||||
const Uint8Array& aCert);
|
||||
|
||||
// Main thread only.
|
||||
// Sends an update to the CDM.
|
||||
// Caller is responsible for calling aResponse.ComputeLengthAndData().
|
||||
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
|
||||
// processed the request.
|
||||
void UpdateSession(const nsAString& aSessionId,
|
||||
PromiseId aPromiseId,
|
||||
const Uint8Array& aResponse);
|
||||
|
||||
// Main thread only.
|
||||
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
|
||||
// processed the request.
|
||||
// If processing this operation results in the session actually closing,
|
||||
// we also call MediaKeySession::OnClosed(), which in turn calls
|
||||
// MediaKeys::OnSessionClosed().
|
||||
void CloseSession(const nsAString& aSessionId,
|
||||
PromiseId aPromiseId);
|
||||
|
||||
// Main thread only.
|
||||
// Removes all data for a persisent session.
|
||||
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
|
||||
// processed the request.
|
||||
void RemoveSession(const nsAString& aSessionId,
|
||||
PromiseId aPromiseId);
|
||||
|
||||
// Main thread only.
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
|
||||
class RejectPromiseTask : public nsRunnable {
|
||||
public:
|
||||
RejectPromiseTask(CDMProxy* aProxy,
|
||||
PromiseId aId,
|
||||
nsresult aCode)
|
||||
: mProxy(aProxy)
|
||||
, mId(aId)
|
||||
, mCode(aCode)
|
||||
{
|
||||
}
|
||||
NS_METHOD Run() {
|
||||
mProxy->RejectPromise(mId, mCode);
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
nsRefPtr<CDMProxy> mProxy;
|
||||
PromiseId mId;
|
||||
nsresult mCode;
|
||||
};
|
||||
|
||||
// Reject promise with DOMException corresponding to aExceptionCode.
|
||||
// Can be called from any thread.
|
||||
void RejectPromise(PromiseId aId, nsresult aExceptionCode);
|
||||
// Resolves promise with "undefined".
|
||||
// Can be called from any thread.
|
||||
void ResolvePromise(PromiseId aId);
|
||||
|
||||
~CDMProxy();
|
||||
|
||||
// Helper to enforce that a raw pointer is only accessed on the main thread.
|
||||
template<class Type>
|
||||
class MainThreadOnlyRawPtr {
|
||||
public:
|
||||
MainThreadOnlyRawPtr(Type* aPtr)
|
||||
: mPtr(aPtr)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
bool IsNull() const {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return !mPtr;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mPtr = nullptr;
|
||||
}
|
||||
|
||||
Type* operator->() const {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mPtr;
|
||||
}
|
||||
private:
|
||||
Type* mPtr;
|
||||
};
|
||||
|
||||
// Our reference back to the MediaKeys object.
|
||||
// WARNING: This is a non-owning reference that is cleared by MediaKeys
|
||||
// destructor. only use on main thread, and always nullcheck before using!
|
||||
MainThreadOnlyRawPtr<dom::MediaKeys> mKeys;
|
||||
|
||||
const nsAutoString mKeySystem;
|
||||
|
||||
// Gecko Media Plugin thread. All interactions with the out-of-process
|
||||
// EME plugin must come from this thread.
|
||||
nsRefPtr<nsIThread> mGMPThread;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // CDMProxy_h_
|
32
content/media/eme/EMELog.cpp
Normal file
32
content/media/eme/EMELog.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "EMELog.h"
|
||||
#include "mozilla/NullPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
|
||||
PRLogModuleInfo* GetEMELog() {
|
||||
static PRLogModuleInfo* log = nullptr;
|
||||
if (!log) {
|
||||
log = PR_NewLogModule("EME");
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
PRLogModuleInfo* GetEMEVerboseLog() {
|
||||
static PRLogModuleInfo* log = nullptr;
|
||||
if (!log) {
|
||||
log = PR_NewLogModule("EMEV");
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace mozilla
|
35
content/media/eme/EMELog.h
Normal file
35
content/media/eme/EMELog.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "prlog.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
|
||||
#ifndef EME_LOG
|
||||
PRLogModuleInfo* GetEMELog();
|
||||
#define EME_LOG(...) PR_LOG(GetEMELog(), PR_LOG_DEBUG, (__VA_ARGS__))
|
||||
#endif
|
||||
|
||||
#ifndef EME_VERBOSE_LOG
|
||||
PRLogModuleInfo* GetEMEVerboseLog();
|
||||
#define EME_VERBOSE_LOG(...) PR_LOG(GetEMEVerboseLog(), PR_LOG_DEBUG, (__VA_ARGS__))
|
||||
|
||||
#else
|
||||
|
||||
#ifndef EME_LOG
|
||||
#define EME_LOG(...)
|
||||
#endif
|
||||
|
||||
#ifndef EME_VERBOSE_LOG
|
||||
#define EME_VERBOSE_LOG(...)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // PR_LOGGING
|
||||
} // namespace mozilla
|
39
content/media/eme/MediaKeyError.cpp
Normal file
39
content/media/eme/MediaKeyError.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
#include "MediaKeyError.h"
|
||||
#include "mozilla/dom/MediaKeyErrorBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
MediaKeyError::MediaKeyError(EventTarget* aOwner, uint32_t aSystemCode)
|
||||
: Event(aOwner, nullptr, nullptr)
|
||||
, mSystemCode(aSystemCode)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
MediaKeyError::~MediaKeyError()
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MediaKeyError::SystemCode() const
|
||||
{
|
||||
return mSystemCode;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
MediaKeyError::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return MediaKeyErrorBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
38
content/media/eme/MediaKeyError.h
Normal file
38
content/media/eme/MediaKeyError.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 mozilla_dom_MediaKeyError_h
|
||||
#define mozilla_dom_MediaKeyError_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MediaKeyError MOZ_FINAL : public Event
|
||||
{
|
||||
public:
|
||||
NS_FORWARD_TO_EVENT
|
||||
|
||||
MediaKeyError(EventTarget* aOwner, uint32_t aSystemCode);
|
||||
~MediaKeyError();
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
uint32_t SystemCode() const;
|
||||
|
||||
private:
|
||||
uint32_t mSystemCode;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
127
content/media/eme/MediaKeyMessageEvent.cpp
Normal file
127
content/media/eme/MediaKeyMessageEvent.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/dom/MediaKeyMessageEvent.h"
|
||||
#include "mozilla/dom/MediaKeyMessageEventBinding.h"
|
||||
#include "js/GCAPI.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "mozilla/dom/PrimitiveConversions.h"
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(MediaKeyMessageEvent)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(MediaKeyMessageEvent, Event)
|
||||
NS_IMPL_RELEASE_INHERITED(MediaKeyMessageEvent, Event)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaKeyMessageEvent, Event)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MediaKeyMessageEvent, Event)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mMessage)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaKeyMessageEvent, Event)
|
||||
tmp->mMessage = nullptr;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaKeyMessageEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(Event)
|
||||
|
||||
MediaKeyMessageEvent::MediaKeyMessageEvent(EventTarget* aOwner)
|
||||
: Event(aOwner, nullptr, nullptr)
|
||||
{
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
MediaKeyMessageEvent::~MediaKeyMessageEvent()
|
||||
{
|
||||
mMessage = nullptr;
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
MediaKeyMessageEvent*
|
||||
MediaKeyMessageEvent::AsMediaKeyMessageEvent()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
MediaKeyMessageEvent::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return MediaKeyMessageEventBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
already_AddRefed<MediaKeyMessageEvent>
|
||||
MediaKeyMessageEvent::Constructor(EventTarget* aOwner,
|
||||
const nsAString& aURL,
|
||||
const nsTArray<uint8_t>& aMessage)
|
||||
{
|
||||
nsRefPtr<MediaKeyMessageEvent> e = new MediaKeyMessageEvent(aOwner);
|
||||
e->InitEvent(NS_LITERAL_STRING("message"), false, false);
|
||||
e->mRawMessage = aMessage;
|
||||
e->mDestinationURL = aURL;
|
||||
e->SetTrusted(true);
|
||||
return e.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<MediaKeyMessageEvent>
|
||||
MediaKeyMessageEvent::Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aType,
|
||||
const MediaKeyMessageEventInit& aEventInitDict,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
nsRefPtr<MediaKeyMessageEvent> e = new MediaKeyMessageEvent(owner);
|
||||
bool trusted = e->Init(owner);
|
||||
e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable);
|
||||
if (aEventInitDict.mMessage.WasPassed()) {
|
||||
const auto& a = aEventInitDict.mMessage.Value();
|
||||
a.ComputeLengthAndData();
|
||||
e->mMessage = Uint8Array::Create(aGlobal.GetContext(), owner, a.Length(), a.Data());
|
||||
} else {
|
||||
e->mMessage = Uint8Array::Create(aGlobal.GetContext(), owner, 0, nullptr);
|
||||
}
|
||||
if (!e->mMessage) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
e->mDestinationURL = aEventInitDict.mDestinationURL;
|
||||
e->SetTrusted(trusted);
|
||||
return e.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
MediaKeyMessageEvent::GetMessage(JSContext* cx, ErrorResult& aRv)
|
||||
{
|
||||
if (!mMessage) {
|
||||
mMessage = Uint8Array::Create(cx,
|
||||
this,
|
||||
mRawMessage.Length(),
|
||||
mRawMessage.Elements());
|
||||
if (!mMessage) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
mRawMessage.Clear();
|
||||
}
|
||||
JS::ExposeObjectToActiveJS(mMessage);
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeyMessageEvent::GetDestinationURL(nsString& aRetVal) const
|
||||
{
|
||||
aRetVal = mDestinationURL;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
65
content/media/eme/MediaKeyMessageEvent.h
Normal file
65
content/media/eme/MediaKeyMessageEvent.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 mozilla_dom_MediaKeyMessageEvent_h__
|
||||
#define mozilla_dom_MediaKeyMessageEvent_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/dom/MediaKeyMessageEventBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MediaKeyMessageEventInit;
|
||||
|
||||
class MediaKeyMessageEvent MOZ_FINAL : public Event
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MediaKeyMessageEvent, Event)
|
||||
virtual ~MediaKeyMessageEvent();
|
||||
protected:
|
||||
MediaKeyMessageEvent(EventTarget* aOwner);
|
||||
|
||||
JS::Heap<JSObject*> mMessage;
|
||||
nsString mDestinationURL;
|
||||
|
||||
public:
|
||||
virtual MediaKeyMessageEvent* AsMediaKeyMessageEvent();
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
static already_AddRefed<MediaKeyMessageEvent>
|
||||
Constructor(EventTarget* aOwner,
|
||||
const nsAString& aURL,
|
||||
const nsTArray<uint8_t>& aMessage);
|
||||
|
||||
static already_AddRefed<MediaKeyMessageEvent>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aType,
|
||||
const MediaKeyMessageEventInit& aEventInitDict,
|
||||
ErrorResult& aRv);
|
||||
|
||||
JSObject* GetMessage(JSContext* cx, ErrorResult& aRv);
|
||||
|
||||
void GetDestinationURL(nsString& aRetVal) const;
|
||||
|
||||
private:
|
||||
nsTArray<uint8_t> mRawMessage;
|
||||
};
|
||||
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_MediaKeyMessageEvent_h__
|
118
content/media/eme/MediaKeyNeededEvent.cpp
Normal file
118
content/media/eme/MediaKeyNeededEvent.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "MediaKeyNeededEvent.h"
|
||||
#include "mozilla/dom/MediaKeyNeededEventBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "nsINode.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(MediaKeyNeededEvent)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(MediaKeyNeededEvent, Event)
|
||||
NS_IMPL_RELEASE_INHERITED(MediaKeyNeededEvent, Event)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaKeyNeededEvent, Event)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MediaKeyNeededEvent, Event)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mInitData)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaKeyNeededEvent, Event)
|
||||
tmp->mInitData = nullptr;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaKeyNeededEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(Event)
|
||||
|
||||
MediaKeyNeededEvent::MediaKeyNeededEvent(EventTarget* aOwner)
|
||||
: Event(aOwner, nullptr, nullptr)
|
||||
{
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
MediaKeyNeededEvent::~MediaKeyNeededEvent()
|
||||
{
|
||||
mInitData = nullptr;
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
MediaKeyNeededEvent::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return MediaKeyNeededEventBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
already_AddRefed<MediaKeyNeededEvent>
|
||||
MediaKeyNeededEvent::Constructor(EventTarget* aOwner,
|
||||
const nsAString& aInitDataType,
|
||||
const nsTArray<uint8_t>& aInitData)
|
||||
{
|
||||
nsRefPtr<MediaKeyNeededEvent> e = new MediaKeyNeededEvent(aOwner);
|
||||
e->InitEvent(NS_LITERAL_STRING("needkey"), false, false);
|
||||
e->mInitDataType = aInitDataType;
|
||||
e->mRawInitData = aInitData;
|
||||
e->SetTrusted(true);
|
||||
return e.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<MediaKeyNeededEvent>
|
||||
MediaKeyNeededEvent::Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aType,
|
||||
const MediaKeyNeededEventInit& aEventInitDict,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
nsRefPtr<MediaKeyNeededEvent> e = new MediaKeyNeededEvent(owner);
|
||||
bool trusted = e->Init(owner);
|
||||
e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable);
|
||||
e->mInitDataType = aEventInitDict.mInitDataType;
|
||||
if (aEventInitDict.mInitData.WasPassed() &&
|
||||
!aEventInitDict.mInitData.Value().IsNull()) {
|
||||
const auto& a = aEventInitDict.mInitData.Value().Value();
|
||||
a.ComputeLengthAndData();
|
||||
e->mInitData = Uint8Array::Create(aGlobal.GetContext(), owner, a.Length(), a.Data());
|
||||
if (!e->mInitData) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
e->SetTrusted(trusted);
|
||||
return e.forget();
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeyNeededEvent::GetInitDataType(nsString& aRetVal) const
|
||||
{
|
||||
aRetVal = mInitDataType;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
MediaKeyNeededEvent::GetInitData(JSContext* cx, ErrorResult& aRv)
|
||||
{
|
||||
if (mRawInitData.Length()) {
|
||||
mInitData = Uint8Array::Create(cx,
|
||||
this,
|
||||
mRawInitData.Length(),
|
||||
mRawInitData.Elements());
|
||||
if (!mInitData) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
mRawInitData.Clear();
|
||||
}
|
||||
if (mInitData) {
|
||||
JS::ExposeObjectToActiveJS(mInitData);
|
||||
}
|
||||
return mInitData;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
62
content/media/eme/MediaKeyNeededEvent.h
Normal file
62
content/media/eme/MediaKeyNeededEvent.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 mozilla_dom_MediaKeyNeededEvent_h__
|
||||
#define mozilla_dom_MediaKeyNeededEvent_h__
|
||||
|
||||
#include "mozilla/dom/MediaKeyNeededEventBinding.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MediaKeyNeededEvent MOZ_FINAL : public Event
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MediaKeyNeededEvent, Event)
|
||||
virtual ~MediaKeyNeededEvent();
|
||||
protected:
|
||||
MediaKeyNeededEvent(EventTarget* aOwner);
|
||||
|
||||
nsString mInitDataType;
|
||||
JS::Heap<JSObject*> mInitData;
|
||||
|
||||
public:
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
static already_AddRefed<MediaKeyNeededEvent>
|
||||
Constructor(EventTarget* aOwner,
|
||||
const nsAString& aInitDataType,
|
||||
const nsTArray<uint8_t>& aInitData);
|
||||
|
||||
static already_AddRefed<MediaKeyNeededEvent>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aType,
|
||||
const MediaKeyNeededEventInit& aEventInitDict,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void GetInitDataType(nsString& aRetVal) const;
|
||||
|
||||
JSObject* GetInitData(JSContext* cx, ErrorResult& aRv);
|
||||
private:
|
||||
nsTArray<uint8_t> mRawInitData;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_MediaKeyNeededEvent_h__
|
178
content/media/eme/MediaKeySession.cpp
Normal file
178
content/media/eme/MediaKeySession.cpp
Normal file
@ -0,0 +1,178 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/MediaKeySession.h"
|
||||
#include "mozilla/dom/MediaKeyError.h"
|
||||
#include "mozilla/dom/MediaKeyMessageEvent.h"
|
||||
#include "mozilla/dom/MediaKeyNeededEvent.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/CDMProxy.h"
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaKeySession,
|
||||
DOMEventTargetHelper,
|
||||
mMediaKeyError,
|
||||
mKeys,
|
||||
mClosed)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaKeySession)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(MediaKeySession, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(MediaKeySession, DOMEventTargetHelper)
|
||||
|
||||
MediaKeySession::MediaKeySession(nsPIDOMWindow* aParent,
|
||||
MediaKeys* aKeys,
|
||||
const nsAString& aKeySystem,
|
||||
SessionType aSessionType)
|
||||
: DOMEventTargetHelper(aParent)
|
||||
, mKeys(aKeys)
|
||||
, mKeySystem(aKeySystem)
|
||||
, mSessionType(aSessionType)
|
||||
, mIsClosed(false)
|
||||
{
|
||||
MOZ_ASSERT(aParent);
|
||||
mClosed = mKeys->MakePromise();
|
||||
}
|
||||
|
||||
void MediaKeySession::Init(const nsAString& aSessionId)
|
||||
{
|
||||
mSessionId = aSessionId;
|
||||
}
|
||||
|
||||
MediaKeySession::~MediaKeySession()
|
||||
{
|
||||
}
|
||||
|
||||
MediaKeyError*
|
||||
MediaKeySession::GetError() const
|
||||
{
|
||||
return mMediaKeyError;
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeySession::GetKeySystem(nsString& aKeySystem) const
|
||||
{
|
||||
aKeySystem = mKeySystem;
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeySession::GetSessionId(nsString& aSessionId) const
|
||||
{
|
||||
aSessionId = mSessionId;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
MediaKeySession::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return MediaKeySessionBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
double
|
||||
MediaKeySession::Expiration() const
|
||||
{
|
||||
return JS::GenericNaN();
|
||||
}
|
||||
|
||||
Promise*
|
||||
MediaKeySession::Closed() const
|
||||
{
|
||||
return mClosed;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaKeySession::Update(const Uint8Array& aResponse)
|
||||
{
|
||||
nsRefPtr<Promise> promise(mKeys->MakePromise());
|
||||
aResponse.ComputeLengthAndData();
|
||||
if (IsClosed() ||
|
||||
!mKeys->GetCDMProxy() ||
|
||||
!aResponse.Length()) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
mKeys->GetCDMProxy()->UpdateSession(mSessionId,
|
||||
mKeys->StorePromise(promise),
|
||||
aResponse);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaKeySession::Close()
|
||||
{
|
||||
nsRefPtr<Promise> promise(mKeys->MakePromise());
|
||||
if (IsClosed() || !mKeys->GetCDMProxy()) {
|
||||
promise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
return promise.forget();
|
||||
}
|
||||
mKeys->GetCDMProxy()->CloseSession(mSessionId, mKeys->StorePromise(promise));
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeySession::OnClosed()
|
||||
{
|
||||
if (IsClosed()) {
|
||||
return;
|
||||
}
|
||||
mIsClosed = true;
|
||||
// TODO: reset usableKeyIds
|
||||
mKeys->OnSessionClosed(this);
|
||||
mKeys = nullptr;
|
||||
mClosed->MaybeResolve(JS::UndefinedHandleValue);
|
||||
}
|
||||
|
||||
bool
|
||||
MediaKeySession::IsClosed() const
|
||||
{
|
||||
return mIsClosed;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaKeySession::Remove()
|
||||
{
|
||||
nsRefPtr<Promise> promise(mKeys->MakePromise());
|
||||
if (mSessionType != SessionType::Persistent) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
// "The operation is not supported on session type sessions."
|
||||
return promise.forget();
|
||||
}
|
||||
if (IsClosed() || !mKeys->GetCDMProxy()) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
// "The session is closed."
|
||||
return promise.forget();
|
||||
}
|
||||
mKeys->GetCDMProxy()->RemoveSession(mSessionId, mKeys->StorePromise(promise));
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeySession::DispatchKeyMessage(const nsTArray<uint8_t>& aMessage,
|
||||
const nsString& aURL)
|
||||
{
|
||||
nsRefPtr<MediaKeyMessageEvent> event(
|
||||
MediaKeyMessageEvent::Constructor(this, aURL, aMessage));
|
||||
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
|
||||
new AsyncEventDispatcher(this, event);
|
||||
asyncDispatcher->PostDOMEvent();
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeySession::DispatchKeyError(uint32_t aSystemCode)
|
||||
{
|
||||
RefPtr<MediaKeyError> event(new MediaKeyError(this, aSystemCode));
|
||||
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
|
||||
new AsyncEventDispatcher(this, event);
|
||||
asyncDispatcher->PostDOMEvent();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
93
content/media/eme/MediaKeySession.h
Normal file
93
content/media/eme/MediaKeySession.h
Normal file
@ -0,0 +1,93 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 mozilla_dom_MediaKeySession_h
|
||||
#define mozilla_dom_MediaKeySession_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/dom/Date.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/MediaKeySessionBinding.h"
|
||||
#include "mozilla/dom/MediaKeysBinding.h"
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class CDMProxy;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class MediaKeyError;
|
||||
|
||||
class MediaKeySession MOZ_FINAL : public DOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaKeySession,
|
||||
DOMEventTargetHelper)
|
||||
public:
|
||||
MediaKeySession(nsPIDOMWindow* aParent,
|
||||
MediaKeys* aKeys,
|
||||
const nsAString& aKeySystem,
|
||||
SessionType aSessionType);
|
||||
|
||||
void Init(const nsAString& aSessionId);
|
||||
|
||||
~MediaKeySession();
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// Mark this as resultNotAddRefed to return raw pointers
|
||||
MediaKeyError* GetError() const;
|
||||
|
||||
void GetKeySystem(nsString& aRetval) const;
|
||||
|
||||
void GetSessionId(nsString& aRetval) const;
|
||||
|
||||
// Number of ms since epoch at which expiration occurs, or NaN if unknown.
|
||||
// TODO: The type of this attribute is still under contention.
|
||||
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=25902
|
||||
double Expiration() const;
|
||||
|
||||
Promise* Closed() const;
|
||||
|
||||
already_AddRefed<Promise> Update(const Uint8Array& response);
|
||||
|
||||
already_AddRefed<Promise> Close();
|
||||
|
||||
already_AddRefed<Promise> Remove();
|
||||
|
||||
void DispatchKeyMessage(const nsTArray<uint8_t>& aMessage,
|
||||
const nsString& aURL);
|
||||
|
||||
void DispatchKeyError(uint32_t system_code);
|
||||
|
||||
void OnClosed();
|
||||
|
||||
bool IsClosed() const;
|
||||
|
||||
private:
|
||||
nsRefPtr<Promise> mClosed;
|
||||
|
||||
nsRefPtr<MediaKeyError> mMediaKeyError;
|
||||
nsRefPtr<MediaKeys> mKeys;
|
||||
const nsString mKeySystem;
|
||||
nsString mSessionId;
|
||||
const SessionType mSessionType;
|
||||
bool mIsClosed;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
291
content/media/eme/MediaKeys.cpp
Normal file
291
content/media/eme/MediaKeys.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/MediaKeys.h"
|
||||
#include "mozilla/dom/MediaKeysBinding.h"
|
||||
#include "mozilla/dom/MediaKeyMessageEvent.h"
|
||||
#include "mozilla/dom/MediaKeyError.h"
|
||||
#include "mozilla/dom/MediaKeySession.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/CDMProxy.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "EMELog.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaKeys,
|
||||
mParent,
|
||||
mKeySessions,
|
||||
mPromises,
|
||||
mPendingSessions);
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeys)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeys)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeys)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
MediaKeys::MediaKeys(nsPIDOMWindow* aParent, const nsAString& aKeySystem)
|
||||
: mParent(aParent),
|
||||
mKeySystem(aKeySystem)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
MediaKeys::~MediaKeys()
|
||||
{
|
||||
if (mProxy) {
|
||||
mProxy->Shutdown();
|
||||
mProxy = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
MediaKeys::GetParentObject() const
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
MediaKeys::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return MediaKeysBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeys::GetKeySystem(nsString& retval) const
|
||||
{
|
||||
retval = mKeySystem;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaKeys::SetServerCertificate(const Uint8Array& aCert)
|
||||
{
|
||||
aCert.ComputeLengthAndData();
|
||||
nsRefPtr<Promise> promise(MakePromise());
|
||||
mProxy->SetServerCertificate(StorePromise(promise), aCert);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
/* static */
|
||||
IsTypeSupportedResult
|
||||
MediaKeys::IsTypeSupported(const GlobalObject& aGlobal,
|
||||
const nsAString& aKeySystem,
|
||||
const Optional<nsAString>& aInitDataType,
|
||||
const Optional<nsAString>& aContentType,
|
||||
const Optional<nsAString>& aCapability)
|
||||
{
|
||||
// TODO: Query list of known CDMs and their supported content types.
|
||||
// TODO: Should really get spec changed to this is async, so we can wait
|
||||
// for user to consent to running plugin.
|
||||
return IsTypeSupportedResult::Maybe;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaKeys::MakePromise()
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
|
||||
if (!global) {
|
||||
NS_WARNING("Passed non-global to MediaKeys ctor!");
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<Promise> promise = new Promise(global);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
PromiseId
|
||||
MediaKeys::StorePromise(Promise* aPromise)
|
||||
{
|
||||
static uint32_t sEMEPromiseCount = 1;
|
||||
MOZ_ASSERT(aPromise);
|
||||
uint32_t id = sEMEPromiseCount++;
|
||||
mPromises.Put(id, aPromise);
|
||||
return id;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaKeys::RetrievePromise(PromiseId aId)
|
||||
{
|
||||
nsRefPtr<Promise> promise;
|
||||
mPromises.Remove(aId, getter_AddRefs(promise));
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeys::RejectPromise(PromiseId aId, nsresult aExceptionCode)
|
||||
{
|
||||
nsRefPtr<Promise> promise(RetrievePromise(aId));
|
||||
if (!promise) {
|
||||
NS_WARNING("MediaKeys tried to reject a non-existent promise");
|
||||
return;
|
||||
}
|
||||
if (mPendingSessions.Contains(aId)) {
|
||||
// This promise could be a createSession or loadSession promise,
|
||||
// so we might have a pending session waiting to be resolved into
|
||||
// the promise on success. We've been directed to reject to promise,
|
||||
// so we can throw away the corresponding session object.
|
||||
mPendingSessions.Remove(aId);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(NS_FAILED(aExceptionCode));
|
||||
promise->MaybeReject(aExceptionCode);
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeys::ResolvePromise(PromiseId aId)
|
||||
{
|
||||
nsRefPtr<Promise> promise(RetrievePromise(aId));
|
||||
if (!promise) {
|
||||
NS_WARNING("MediaKeys tried to resolve a non-existent promise");
|
||||
return;
|
||||
}
|
||||
// We should not resolve CreateSession or LoadSession calls via this path,
|
||||
// OnSessionActivated() should be called instead.
|
||||
MOZ_ASSERT(!mPendingSessions.Contains(aId));
|
||||
promise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<Promise>
|
||||
MediaKeys::Create(const GlobalObject& aGlobal,
|
||||
const nsAString& aKeySystem,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// CDMProxy keeps MediaKeys alive until it resolves the promise and thus
|
||||
// returns the MediaKeys object to JS.
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!window) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<MediaKeys> keys = new MediaKeys(window, aKeySystem);
|
||||
nsRefPtr<Promise> promise(keys->MakePromise());
|
||||
if (!promise) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!aKeySystem.EqualsASCII("org.w3.clearkey")) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
keys->mProxy = new CDMProxy(keys, aKeySystem);
|
||||
keys->mProxy->Init(keys->StorePromise(promise));
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeys::OnCDMCreated(PromiseId aId)
|
||||
{
|
||||
nsRefPtr<Promise> promise(RetrievePromise(aId));
|
||||
if (!promise) {
|
||||
NS_WARNING("MediaKeys tried to resolve a non-existent promise");
|
||||
return;
|
||||
}
|
||||
nsRefPtr<MediaKeys> keys(this);
|
||||
promise->MaybeResolve(keys);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaKeys::LoadSession(const nsAString& aSessionId)
|
||||
{
|
||||
nsRefPtr<Promise> promise(MakePromise());
|
||||
|
||||
if (aSessionId.IsEmpty()) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
// "The sessionId parameter is empty."
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// TODO: The spec doesn't specify what to do in this case...
|
||||
if (mKeySessions.Contains(aSessionId)) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Create session.
|
||||
nsRefPtr<MediaKeySession> session(
|
||||
new MediaKeySession(GetParentObject(), this, mKeySystem, SessionType::Persistent));
|
||||
|
||||
// Proxy owns session object until resolving promise.
|
||||
mProxy->LoadSession(StorePromise(promise),
|
||||
aSessionId);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaKeys::CreateSession(const nsAString& initDataType,
|
||||
const Uint8Array& aInitData,
|
||||
SessionType aSessionType)
|
||||
{
|
||||
aInitData.ComputeLengthAndData();
|
||||
nsRefPtr<Promise> promise(MakePromise());
|
||||
nsRefPtr<MediaKeySession> session = new MediaKeySession(GetParentObject(),
|
||||
this,
|
||||
mKeySystem,
|
||||
aSessionType);
|
||||
auto pid = StorePromise(promise);
|
||||
// Hang onto session until the CDM has finished setting it up.
|
||||
mPendingSessions.Put(pid, session);
|
||||
mProxy->CreateSession(aSessionType,
|
||||
pid,
|
||||
initDataType,
|
||||
aInitData);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeys::OnSessionActivated(PromiseId aId, const nsAString& aSessionId)
|
||||
{
|
||||
nsRefPtr<Promise> promise(RetrievePromise(aId));
|
||||
if (!promise) {
|
||||
NS_WARNING("MediaKeys tried to resolve a non-existent promise");
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mPendingSessions.Contains(aId));
|
||||
|
||||
nsRefPtr<MediaKeySession> session;
|
||||
if (!mPendingSessions.Get(aId, getter_AddRefs(session)) || !session) {
|
||||
NS_WARNING("Received activation for non-existent session!");
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Session has completed creation/loading, remove it from mPendingSessions,
|
||||
// and resolve the promise with it. We store it in mKeySessions, so we can
|
||||
// find it again if we need to send messages to it etc.
|
||||
mPendingSessions.Remove(aId);
|
||||
session->Init(aSessionId);
|
||||
mKeySessions.Put(aSessionId, session);
|
||||
promise->MaybeResolve(session);
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeys::OnSessionClosed(MediaKeySession* aSession)
|
||||
{
|
||||
nsAutoString id;
|
||||
aSession->GetSessionId(id);
|
||||
mKeySessions.Remove(id);
|
||||
}
|
||||
|
||||
already_AddRefed<MediaKeySession>
|
||||
MediaKeys::GetSession(const nsAString& aSessionId)
|
||||
{
|
||||
nsRefPtr<MediaKeySession> session;
|
||||
mKeySessions.Get(aSessionId, getter_AddRefs(session));
|
||||
return session.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
120
content/media/eme/MediaKeys.h
Normal file
120
content/media/eme/MediaKeys.h
Normal file
@ -0,0 +1,120 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 mozilla_dom_mediakeys_h__
|
||||
#define mozilla_dom_mediakeys_h__
|
||||
|
||||
#include "nsIDOMMediaError.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsISupports.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/MediaKeysBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class CDMProxy;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class MediaKeySession;
|
||||
|
||||
typedef nsRefPtrHashtable<nsStringHashKey, MediaKeySession> KeySessionHashMap;
|
||||
typedef nsRefPtrHashtable<nsUint32HashKey, dom::Promise> PromiseHashMap;
|
||||
typedef nsRefPtrHashtable<nsUint32HashKey, MediaKeySession> PendingKeySessionsHashMap;
|
||||
typedef uint32_t PromiseId;
|
||||
|
||||
// This class is used on the main thread only.
|
||||
// Note: it's addref/release is not (and can't be) thread safe!
|
||||
class MediaKeys MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeys)
|
||||
|
||||
MediaKeys(nsPIDOMWindow* aParentWindow, const nsAString& aKeySystem);
|
||||
|
||||
~MediaKeys();
|
||||
|
||||
nsPIDOMWindow* GetParentObject() const;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// Javascript: readonly attribute DOMString keySystem;
|
||||
void GetKeySystem(nsString& retval) const;
|
||||
|
||||
// JavaScript: MediaKeys.createSession()
|
||||
already_AddRefed<Promise> CreateSession(const nsAString& aInitDataType,
|
||||
const Uint8Array& aInitData,
|
||||
SessionType aSessionType);
|
||||
|
||||
// JavaScript: MediaKeys.loadSession()
|
||||
already_AddRefed<Promise> LoadSession(const nsAString& aSessionId);
|
||||
|
||||
// JavaScript: MediaKeys.SetServerCertificate()
|
||||
already_AddRefed<Promise> SetServerCertificate(const Uint8Array& aServerCertificate);
|
||||
|
||||
// JavaScript: MediaKeys.create()
|
||||
static
|
||||
already_AddRefed<Promise> Create(const GlobalObject& aGlobal,
|
||||
const nsAString& aKeySystem,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// JavaScript: MediaKeys.IsTypeSupported()
|
||||
static IsTypeSupportedResult IsTypeSupported(const GlobalObject& aGlobal,
|
||||
const nsAString& aKeySystem,
|
||||
const Optional<nsAString>& aInitDataType,
|
||||
const Optional<nsAString>& aContentType,
|
||||
const Optional<nsAString>& aCapability);
|
||||
|
||||
already_AddRefed<MediaKeySession> GetSession(const nsAString& aSessionId);
|
||||
|
||||
// Called once a Create() operation succeeds.
|
||||
void OnCDMCreated(PromiseId aId);
|
||||
// Called once a CreateSession or LoadSession succeeds.
|
||||
void OnSessionActivated(PromiseId aId, const nsAString& aSessionId);
|
||||
// Called once a session has closed.
|
||||
void OnSessionClosed(MediaKeySession* aSession);
|
||||
|
||||
CDMProxy* GetCDMProxy() { return mProxy; }
|
||||
|
||||
// Makes a new promise, or nullptr on failure.
|
||||
already_AddRefed<Promise> MakePromise();
|
||||
// Stores promise in mPromises, returning an ID that can be used to retrieve
|
||||
// it later. The ID is passed to the CDM, so that it can signal specific
|
||||
// promises to be resolved.
|
||||
PromiseId StorePromise(Promise* aPromise);
|
||||
|
||||
// Reject promise with DOMException corresponding to aExceptionCode.
|
||||
void RejectPromise(PromiseId aId, nsresult aExceptionCode);
|
||||
// Resolves promise with "undefined".
|
||||
void ResolvePromise(PromiseId aId);
|
||||
|
||||
private:
|
||||
|
||||
// Removes promise from mPromises, and returns it.
|
||||
already_AddRefed<Promise> RetrievePromise(PromiseId aId);
|
||||
|
||||
// Owning ref to proxy. The proxy has a weak reference back to the MediaKeys,
|
||||
// and the MediaKeys destructor clears the proxy's reference to the MediaKeys.
|
||||
nsRefPtr<CDMProxy> mProxy;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mParent;
|
||||
nsString mKeySystem;
|
||||
KeySessionHashMap mKeySessions;
|
||||
PromiseHashMap mPromises;
|
||||
PendingKeySessionsHashMap mPendingSessions;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_mediakeys_h__
|
31
content/media/eme/moz.build
Normal file
31
content/media/eme/moz.build
Normal file
@ -0,0 +1,31 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'MediaKeyError.h',
|
||||
'MediaKeyMessageEvent.h',
|
||||
'MediaKeyNeededEvent.h',
|
||||
'MediaKeys.h',
|
||||
'MediaKeySession.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
'CDMProxy.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'CDMProxy.cpp',
|
||||
'EMELog.cpp',
|
||||
'MediaKeyError.cpp',
|
||||
'MediaKeyMessageEvent.cpp',
|
||||
'MediaKeyNeededEvent.cpp',
|
||||
'MediaKeys.cpp',
|
||||
'MediaKeySession.cpp',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'gklayout'
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
@ -50,6 +50,8 @@ if CONFIG['MOZ_OMX_DECODER']:
|
||||
|
||||
PARALLEL_DIRS += ['webspeech']
|
||||
|
||||
PARALLEL_DIRS += ['eme']
|
||||
|
||||
TEST_DIRS += [
|
||||
'test',
|
||||
'gtest',
|
||||
|
@ -293,7 +293,6 @@ EVENT(mozpointerlockerror,
|
||||
NS_POINTERLOCKERROR,
|
||||
EventNameType_HTML,
|
||||
NS_EVENT)
|
||||
|
||||
EVENT(pointerdown,
|
||||
NS_POINTER_DOWN,
|
||||
EventNameType_All,
|
||||
|
@ -130,3 +130,25 @@ partial interface HTMLMediaElement {
|
||||
// because of the audiochannel manager.
|
||||
// * onmozinterruptend - called when the interruption is concluded
|
||||
};
|
||||
|
||||
enum MediaWaitingFor {
|
||||
"none",
|
||||
"data",
|
||||
"key"
|
||||
};
|
||||
|
||||
// Encrypted Media Extensions
|
||||
partial interface HTMLMediaElement {
|
||||
[Pref="media.eme.enabled"]
|
||||
readonly attribute MediaKeys? mediaKeys;
|
||||
|
||||
// Promise<any>
|
||||
[Pref="media.eme.enabled", Throws, NewObject]
|
||||
Promise setMediaKeys(MediaKeys? mediaKeys);
|
||||
|
||||
[Pref="media.eme.enabled"]
|
||||
attribute EventHandler onneedkey;
|
||||
|
||||
[Pref="media.eme.enabled"]
|
||||
readonly attribute MediaWaitingFor waitingFor;
|
||||
};
|
||||
|
@ -19,3 +19,9 @@ interface HTMLSourceElement : HTMLElement {
|
||||
[SetterThrows]
|
||||
attribute DOMString media;
|
||||
};
|
||||
|
||||
// Encrypted Media Extensions
|
||||
partial interface HTMLSourceElement {
|
||||
[Pref="media.eme.enabled"]
|
||||
attribute DOMString keySystem;
|
||||
};
|
||||
|
19
dom/webidl/MediaKeyError.webidl
Normal file
19
dom/webidl/MediaKeyError.webidl
Normal file
@ -0,0 +1,19 @@
|
||||
/* -*- Mode: IDL; 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html
|
||||
*
|
||||
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
|
||||
* W3C liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
// According to the spec, "The future of error events and MediaKeyError
|
||||
// is uncertain."
|
||||
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=21798
|
||||
[Pref="media.eme.enabled"]
|
||||
interface MediaKeyError : Event {
|
||||
readonly attribute unsigned long systemCode;
|
||||
};
|
23
dom/webidl/MediaKeyMessageEvent.webidl
Normal file
23
dom/webidl/MediaKeyMessageEvent.webidl
Normal file
@ -0,0 +1,23 @@
|
||||
/* -*- Mode: IDL; 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html
|
||||
*
|
||||
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
|
||||
* W3C liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[Pref="media.eme.enabled", Constructor(DOMString type, optional MediaKeyMessageEventInit eventInitDict)]
|
||||
interface MediaKeyMessageEvent : Event {
|
||||
[Throws]
|
||||
readonly attribute Uint8Array message;
|
||||
readonly attribute DOMString? destinationURL;
|
||||
};
|
||||
|
||||
dictionary MediaKeyMessageEventInit : EventInit {
|
||||
Uint8Array message;
|
||||
DOMString? destinationURL = "";
|
||||
};
|
23
dom/webidl/MediaKeyNeededEvent.webidl
Normal file
23
dom/webidl/MediaKeyNeededEvent.webidl
Normal file
@ -0,0 +1,23 @@
|
||||
/* -*- Mode: IDL; 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html
|
||||
*
|
||||
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
|
||||
* W3C liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[Pref="media.eme.enabled", Constructor(DOMString type, optional MediaKeyNeededEventInit eventInitDict)]
|
||||
interface MediaKeyNeededEvent : Event {
|
||||
readonly attribute DOMString initDataType;
|
||||
[Throws]
|
||||
readonly attribute Uint8Array? initData;
|
||||
};
|
||||
|
||||
dictionary MediaKeyNeededEventInit : EventInit {
|
||||
DOMString initDataType = "";
|
||||
Uint8Array? initData;
|
||||
};
|
43
dom/webidl/MediaKeySession.webidl
Normal file
43
dom/webidl/MediaKeySession.webidl
Normal file
@ -0,0 +1,43 @@
|
||||
/* -*- Mode: IDL; 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html
|
||||
*
|
||||
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
|
||||
* W3C liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[Pref="media.eme.enabled"]
|
||||
interface MediaKeySession : EventTarget {
|
||||
// error state
|
||||
readonly attribute MediaKeyError? error;
|
||||
|
||||
// session properties
|
||||
readonly attribute DOMString keySystem;
|
||||
readonly attribute DOMString sessionId;
|
||||
|
||||
// Invalid WebIDL, doesn't work.
|
||||
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=25594
|
||||
// readonly attribute Array<Uint8Array> usableKeyIds;
|
||||
|
||||
readonly attribute unrestricted double expiration;
|
||||
|
||||
// Promise<any>
|
||||
readonly attribute Promise closed;
|
||||
|
||||
// session operations
|
||||
//Promise<any>
|
||||
[NewObject]
|
||||
Promise update(Uint8Array response);
|
||||
|
||||
// Promise<any>
|
||||
[NewObject]
|
||||
Promise close();
|
||||
|
||||
// Promise<any>
|
||||
[NewObject]
|
||||
Promise remove();
|
||||
};
|
37
dom/webidl/MediaKeys.webidl
Normal file
37
dom/webidl/MediaKeys.webidl
Normal file
@ -0,0 +1,37 @@
|
||||
/* -*- Mode: IDL; 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html
|
||||
*
|
||||
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
|
||||
* W3C liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
enum IsTypeSupportedResult { "" /* empty string */, "maybe", "probably" };
|
||||
enum SessionType { "temporary", "persistent" };
|
||||
|
||||
[Pref="media.eme.enabled"]
|
||||
interface MediaKeys {
|
||||
readonly attribute DOMString keySystem;
|
||||
|
||||
// Promise<MediaKeySession>
|
||||
[NewObject]
|
||||
Promise createSession(DOMString initDataType, Uint8Array initData, optional SessionType sessionType = "temporary");
|
||||
|
||||
// Promise<MediaKeySession>
|
||||
[NewObject]
|
||||
Promise loadSession(DOMString sessionId);
|
||||
|
||||
// Promise<any>
|
||||
[NewObject]
|
||||
Promise setServerCertificate(Uint8Array serverCertificate);
|
||||
|
||||
// Promise<MediaKeys>
|
||||
[Throws,NewObject]
|
||||
static Promise create(DOMString keySystem);
|
||||
static IsTypeSupportedResult isTypeSupported(DOMString keySystem, optional DOMString initDataType, optional DOMString contentType, optional DOMString capability);
|
||||
|
||||
};
|
@ -231,6 +231,11 @@ WEBIDL_FILES = [
|
||||
'LockedFile.webidl',
|
||||
'MediaElementAudioSourceNode.webidl',
|
||||
'MediaError.webidl',
|
||||
'MediaKeyError.webidl',
|
||||
'MediaKeyMessageEvent.webidl',
|
||||
'MediaKeyNeededEvent.webidl',
|
||||
'MediaKeys.webidl',
|
||||
'MediaKeySession.webidl',
|
||||
'MediaList.webidl',
|
||||
'MediaQueryList.webidl',
|
||||
'MediaRecorder.webidl',
|
||||
|
@ -28,6 +28,12 @@ BEGIN_WORKERS_NAMESPACE
|
||||
* | Killing | yes | yes | doesn't run |
|
||||
* +-------------+-------------+-----------------+----------------+
|
||||
*/
|
||||
|
||||
#ifdef Status
|
||||
/* Xlib headers insist on this for some reason... Nuke it because
|
||||
it'll override our member name */
|
||||
#undef Status
|
||||
#endif
|
||||
enum Status
|
||||
{
|
||||
// Not yet scheduled.
|
||||
|
@ -168,6 +168,7 @@ HTML5_ATOM(order, "order")
|
||||
HTML5_ATOM(other, "other")
|
||||
HTML5_ATOM(oncut, "oncut")
|
||||
HTML5_ATOM(nargs, "nargs")
|
||||
HTML5_ATOM(keysystem, "keysystem")
|
||||
HTML5_ATOM(media, "media")
|
||||
HTML5_ATOM(label, "label")
|
||||
HTML5_ATOM(local, "local")
|
||||
|
@ -322,6 +322,7 @@ enum nsEventStructType
|
||||
#define NS_RATECHANGE (NS_MEDIA_EVENT_START+17)
|
||||
#define NS_DURATIONCHANGE (NS_MEDIA_EVENT_START+18)
|
||||
#define NS_VOLUMECHANGE (NS_MEDIA_EVENT_START+19)
|
||||
#define NS_NEED_KEY (NS_MEDIA_EVENT_START+20)
|
||||
|
||||
// paint notification events
|
||||
#define NS_NOTIFYPAINT_START 3400
|
||||
|
Loading…
Reference in New Issue
Block a user