Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* 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/. */
/* global add_task */
"use strict";
/**
* This test verifies that nsIWindowsMediaFoundationCDMOriginsListService
* correctly triggers its callback and that the origin entries are propagated
* as expected. It also checks that the result of calling
* requestMediaKeySystemAccess for PlayReady is influenced by these entries.
*/
ChromeUtils.defineESModuleGetters(this, {
});
const COLLECTION_NAME = "mfcdm-origins-list";
const gRemoteSettings = RemoteSettings(COLLECTION_NAME);
const gOriginsListService = Cc[
"@mozilla.org/media/wmfcdm-origins-list;1"
].getService(Ci.nsIWindowsMediaFoundationCDMOriginsListService);
const gEntries = [
{
origin: "example.com",
allowed: false,
},
{
origin: "example.org",
allowed: true,
},
];
add_task(async function testOriginsListServiceCallback() {
info(`Simulate sending initial entries update to RemoteSettings`);
await updateRemoteSettings(gEntries);
info(`Waiting for the callback to be triggered`);
let waitUpdate = TestUtils.topicObserved("updated-entries");
let callback = {
onOriginsListLoaded(entries) {
Assert.equal(entries.length, gEntries.length, "Entry count matches");
for (let expected of gEntries) {
let found = false;
for (let i = 0; i < entries.length; i++) {
let e = entries.queryElementAt(i, Ci.nsIOriginStatusEntry);
if (
e.origin === expected.origin &&
e.status === (expected.allowed ? 1 : 0)
) {
found = true;
break;
}
}
Assert.ok(
found,
`Expected origin (${expected.origin}/${expected.allowed}) found`
);
}
Services.obs.notifyObservers(null, "updated-entries");
},
};
gOriginsListService.setCallback(callback);
await waitUpdate;
info(
`Simulate adding another new record which should trigger callback again`
);
waitUpdate = TestUtils.topicObserved("updated-entries");
gEntries.push({
origin: "example.net",
allowed: false,
});
await Promise.all([
TestUtils.topicObserved("updated-entries"),
updateRemoteSettings(gEntries),
]);
info(
`Remove old callback, and set a new callback, which should be triggered as well`
);
waitUpdate = TestUtils.topicObserved("updated-entries");
gOriginsListService.removeCallback(callback);
gOriginsListService.setCallback(callback);
await waitUpdate;
});
// This task follows the entries set in the previous task.
add_task(async function testCheckCreateKeySystemAccess() {
info(`Set pre-requirement prefs`);
await SpecialPowers.pushPrefEnv({
set: [
["media.wmf.media-engine.enabled", 2],
// Our mock CDM doesn't implement 'IsTypeSupportedEx()', only 'IsTypeSupported()'
["media.eme.playready.istypesupportedex", false],
["media.eme.wmf.use-mock-cdm-for-external-cdms", true],
],
});
info(`Open a new tab and navigate`);
let tab = await BrowserTestUtils.openNewForegroundTab(window.gBrowser);
// Test both preference values to control the default behavior when an origin
// is not explicitly listed in the entries.
// 3 : enabled allowed by default via Remote Settings
// 4 : enabled blocked by default via Remote Settings
const originFilterPrefs = [3, 4];
for (let prefValue of originFilterPrefs) {
const isDefaultAllowed = prefValue == 3;
info(`Testing default behavior: ${isDefaultAllowed ? "allow" : "block"}`);
await SpecialPowers.pushPrefEnv({
set: [["media.eme.mfcdm.origin-filter.enabled", prefValue]],
});
const notSpecifiedDomains = [
// Sub-domain, should follow the main domain result
{
origin: "test1.example.com",
allowed: false,
},
{
origin: "test1.example.org",
allowed: true,
},
// Not specified and not a subdomain, follow the default result
{
origin: "example.onion",
allowed: isDefaultAllowed,
},
];
for (let entry of gEntries.concat(notSpecifiedDomains)) {
info(`Navigate to ${entry.origin}`);
BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, entry.origin);
await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
info(`Creating a key system access, which should be ${entry.allowed}`);
await checkCreateKeySystemAccess({
tab,
isAllowed: entry.allowed,
});
}
}
info(`Remove tab`);
await BrowserTestUtils.removeTab(tab);
});
// Below are helper functions
function updateRemoteSettings(entries) {
return gRemoteSettings.emit("sync", {
data: {
current: entries,
created: [],
updated: [],
deleted: [],
},
});
}
function checkCreateKeySystemAccess({ tab, isAllowed } = {}) {
return SpecialPowers.spawn(
tab.linkedBrowser,
[isAllowed],
async isAllowed_ => {
const keySystem = "com.microsoft.playready.recommendation";
const config = [
{
videoCapabilities: [
{
contentType: 'video/mp4; codecs="avc1.42E01E"',
},
],
initDataTypes: ["cenc"],
sessionTypes: ["temporary"],
},
];
try {
info("Attemping to create a key system access");
await content.navigator.requestMediaKeySystemAccess(keySystem, config);
ok(isAllowed_, "Created a key system access");
} catch (e) {
ok(!isAllowed_, "Not allowed to create a key system access");
}
}
);
}