Source code
Revision control
Copy as Markdown
Other Tools
/* 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
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
});
ChromeUtils.defineLazyGetter(lazy, "console", () => {
return console.createInstance({ prefix: "EME" });
});
const COLLECTION_NAME = "mfcdm-origins-list";
// These are defined in nsIWindowsMediaFoundationCDMOriginsListService.idl
const ORIGIN_BLOCKED = 0;
const ORIGIN_ALLOWED = 1;
function log(message) {
const LOGGING_ENABLED = Services.env.get("MOZ_LOG")?.includes("EME");
if (LOGGING_ENABLED) {
lazy.console.debug(
`WindowsMediaFoundationCDMOriginsListService : ${message}\n`
);
}
}
/**
* Represents an entry in the origin status list.
*
* @param {string} origin The origin URL.
* @param {boolean} status The status of the origin.
*/
class OriginStatusEntry {
constructor(origin, status) {
this._origin = origin;
this._status = status;
}
get origin() {
return this._origin;
}
get status() {
return this._status;
}
}
OriginStatusEntry.prototype.classID = Components.ID(
"{b1d5e2f2-8d65-41f3-86e8-9c6c21f2486d}"
);
OriginStatusEntry.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIOriginStatusEntry",
]);
export function WindowsMediaFoundationCDMOriginsListService() {
log("Created service");
Services.obs.addObserver(this, "xpcom-shutdown");
}
WindowsMediaFoundationCDMOriginsListService.prototype = {
classID: Components.ID("{a9b28d1f-7e11-4c5f-85a0-4fd39db1f7c9}"),
QueryInterface: ChromeUtils.generateQI([
"nsIWindowsMediaFoundationCDMOriginsListService",
]),
_rs: null,
_entriesReady: false,
// this callback will make content parents to broadcast the origin status entry.
_callbacks: [],
// An array of OriginStatusEntry.
_originsList: null,
async _getOriginsListFromRemoteService() {
log(`Create the remote service and fetching data`);
if (this._entriesReady) {
return;
}
this._rs = lazy.RemoteSettings(COLLECTION_NAME);
this._rs.on("sync", async event => {
let {
data: { current },
} = event;
this._onUpdateEntries(current || []);
});
let entries;
try {
entries = await this._rs.get();
} catch (e) {
log(`Error fetching origins list: ${e}`);
}
this._onUpdateEntries(entries || []);
this._entriesReady = true;
},
_onUpdateEntries(aEntries) {
log(`Update entries, aEntries=${JSON.stringify(aEntries, null, 2)}`);
const entries = Cc["@mozilla.org/array;1"].createInstance(
Ci.nsIMutableArray
);
for (let entry of aEntries) {
log(`Entry name: ${entry.origin}, allowed: ${entry.allowed}`);
const status = entry.allowed ? ORIGIN_ALLOWED : ORIGIN_BLOCKED;
const originStatusEntry = new OriginStatusEntry(entry.origin, status);
entries.appendElement(originStatusEntry);
}
this._originsList = entries;
if (this._callbacks.length) {
log("Processing entries for all callbacks.");
for (let callback of this._callbacks) {
try {
callback.onOriginsListLoaded(entries);
} catch (e) {
log(`Error calling callback: ${e}`);
}
}
}
},
// xpcom-shutdown observer
observe(_aSubject, aTopic, _aData) {
if (aTopic == "xpcom-shutdown") {
Services.obs.removeObserver(this, "xpcom-shutdown");
this._callbacks.length = 0;
this._callbacks = null;
this._originsList = null;
if (this._rs) {
this._rs.off("sync");
this._rs = null;
}
}
},
// Below methods are for nsIWindowsMediaFoundationCDMOriginsListService
setCallback(aCallback) {
log(`SetCallback`);
this._callbacks.push(aCallback);
if (!this._entriesReady) {
this._getOriginsListFromRemoteService();
} else {
log("Entries already ready. Immediately notifying new callback.");
aCallback.onOriginsListLoaded(this._originsList);
}
},
removeCallback(aCallback) {
log(`RemoveCallback`);
const index = this._callbacks.indexOf(aCallback);
if (index !== -1) {
this._callbacks.splice(index, 1);
log(`Callback removed successfully.`);
} else {
log(`Callback not found.`);
}
},
};