190 lines
5.8 KiB
JavaScript
190 lines
5.8 KiB
JavaScript
/* 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, {
|
|
RemoteSettings: "resource://services-settings/remote-settings.sys.mjs",
|
|
BrowserTestUtils: "resource://testing-common/BrowserTestUtils.sys.mjs",
|
|
TestUtils: "resource://testing-common/TestUtils.sys.mjs",
|
|
});
|
|
|
|
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");
|
|
}
|
|
}
|
|
);
|
|
}
|