Bug 1124031 part 4 - Enforce min CDM version from keySystem string. r=bz

This commit is contained in:
Chris Pearce 2015-02-20 14:38:08 +13:00
parent 2d90d26912
commit 778b941d64
6 changed files with 77 additions and 12 deletions

View File

@ -112,6 +112,10 @@
#include "mozilla/dom/FeatureList.h"
#ifdef MOZ_EME
#include "mozilla/EMEUtils.h"
#endif
namespace mozilla {
namespace dom {
@ -2637,13 +2641,26 @@ Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem,
return p.forget();
}
MediaKeySystemStatus status = MediaKeySystemAccess::GetKeySystemStatus(aKeySystem);
// Parse keysystem, split it out into keySystem prefix, and version suffix.
nsAutoString keySystem;
int32_t minCdmVersion = NO_CDM_VERSION;
if (!ParseKeySystem(aKeySystem,
keySystem,
minCdmVersion)) {
// Invalid keySystem string, or unsupported keySystem. Send notification
// to chrome to show a failure notice.
MediaKeySystemAccess::NotifyObservers(mWindow, aKeySystem, MediaKeySystemStatus::Cdm_not_supported);
p->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return p.forget();
}
MediaKeySystemStatus status = MediaKeySystemAccess::GetKeySystemStatus(keySystem, minCdmVersion);
if (status != MediaKeySystemStatus::Available) {
if (status != MediaKeySystemStatus::Error) {
// Failed due to user disabling something, send a notification to
// chrome, so we can show some UI to explain how the user can rectify
// the situation.
MediaKeySystemAccess::NotifyObservers(mWindow, aKeySystem, status);
MediaKeySystemAccess::NotifyObservers(mWindow, keySystem, status);
}
p->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return p.forget();
@ -2652,8 +2669,8 @@ Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem,
// TODO: Wait (async) until the CDM is downloaded, if it's not already.
if (!aOptions.WasPassed() ||
MediaKeySystemAccess::IsSupported(aKeySystem, aOptions.Value())) {
nsRefPtr<MediaKeySystemAccess> access(new MediaKeySystemAccess(mWindow, aKeySystem));
MediaKeySystemAccess::IsSupported(keySystem, aOptions.Value())) {
nsRefPtr<MediaKeySystemAccess> access(new MediaKeySystemAccess(mWindow, keySystem));
p->MaybeResolve(access);
return p.forget();
}

View File

@ -81,8 +81,6 @@ HaveGMPFor(mozIGeckoMediaPluginService* aGMPService,
if (!aTag.IsEmpty()) {
tags.AppendElement(aTag);
}
// Note: EME plugins need a non-null nodeId here, as they must
// not be shared across origins.
bool hasPlugin = false;
if (NS_FAILED(aGMPService->HasPluginForAPI(aAPI,
&tags,
@ -92,9 +90,37 @@ HaveGMPFor(mozIGeckoMediaPluginService* aGMPService,
return hasPlugin;
}
static MediaKeySystemStatus
EnsureMinCDMVersion(mozIGeckoMediaPluginService* aGMPService,
const nsAString& aKeySystem,
int32_t aMinCdmVersion)
{
if (aMinCdmVersion == NO_CDM_VERSION) {
return MediaKeySystemStatus::Available;
}
nsTArray<nsCString> tags;
tags.AppendElement(NS_ConvertUTF16toUTF8(aKeySystem));
nsAutoCString versionStr;
if (NS_FAILED(aGMPService->GetPluginVersionForAPI(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR),
&tags,
versionStr))) {
return MediaKeySystemStatus::Error;
}
nsresult rv;
int32_t version = versionStr.ToInteger(&rv);
if (NS_FAILED(rv) || version < 0 || aMinCdmVersion > version) {
return MediaKeySystemStatus::Cdm_insufficient_version;
}
return MediaKeySystemStatus::Available;
}
/* static */
MediaKeySystemStatus
MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem)
MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem,
int32_t aMinCdmVersion)
{
MOZ_ASSERT(Preferences::GetBool("media.eme.enabled", false));
nsCOMPtr<mozIGeckoMediaPluginService> mps =
@ -112,7 +138,7 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem)
NS_LITERAL_CSTRING(GMP_API_DECRYPTOR))) {
return MediaKeySystemStatus::Cdm_not_installed;
}
return MediaKeySystemStatus::Available;
return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion);
}
#ifdef XP_WIN
@ -130,7 +156,7 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem)
NS_LITERAL_CSTRING(GMP_API_DECRYPTOR))) {
return MediaKeySystemStatus::Cdm_not_installed;
}
return MediaKeySystemStatus::Available;
return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion);
}
#endif

View File

@ -44,7 +44,8 @@ public:
already_AddRefed<Promise> CreateMediaKeys(ErrorResult& aRv);
static MediaKeySystemStatus GetKeySystemStatus(const nsAString& aKeySystem);
static MediaKeySystemStatus GetKeySystemStatus(const nsAString& aKeySystem,
int32_t aMinCdmVersion);
static bool IsSupported(const nsAString& aKeySystem,
const Sequence<MediaKeySystemOptions>& aOptions);

View File

@ -266,6 +266,26 @@ var tests = [
],
shouldPass: false,
},
{
name: "CDM version less than",
keySystem: CLEARKEY_ID + ".0",
shouldPass: true
},
{
name: "CDM version equal to",
keySystem: CLEARKEY_ID + ".1",
shouldPass: true
},
{
name: "CDM version greater than",
keySystem: CLEARKEY_ID + ".2",
shouldPass: false
},
{
name: "Non-whole number CDM version",
keySystem: CLEARKEY_ID + ".0.1",
shouldPass: false
},
];
function beginTest() {

View File

@ -10,6 +10,7 @@ enum MediaKeySystemStatus {
"cdm-disabled",
"cdm-not-supported",
"cdm-not-installed",
"cdm-insufficient-version",
"cdm-created",
"error"
};

View File

@ -1,6 +1,6 @@
Name: clearkey
Description: ClearKey decrypt-only GMP plugin
Version: 0.1
Description: ClearKey Gecko Media Plugin
Version: 1
#ifdef ENABLE_WMF
APIs: eme-decrypt-v6[org.w3.clearkey], decode-audio[aac:org.w3.clearkey], decode-video[h264:org.w3.clearkey]
Libraries: dxva2.dll, d3d9.dll, msmpeg2vdec.dll, msmpeg2adec.dll, MSAudDecMFT.dll