165 lines
4.3 KiB
JavaScript
165 lines
4.3 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/. */
|
|
|
|
const lazy = {};
|
|
ChromeUtils.defineESModuleGetters(lazy, {
|
|
RemoteSettings: "resource://services-settings/remote-settings.sys.mjs",
|
|
});
|
|
|
|
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.`);
|
|
}
|
|
},
|
|
};
|