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
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { RemoteSettings } = ChromeUtils.importESModule(
);
loader.lazyRequireGetter(
this,
["TARGET_BROWSER_ID", "TARGET_BROWSER_STATUS", "TARGET_BROWSER_PREF"],
true
);
/**
* Returns the full list of browsers in the RemoteSetting devtools-compatibility-browsers
* collection (which is a flat copy of MDN compat data), sorted by browser and version.
*
* @returns Promise<Array<Object>> : Objects in the array have the following shape:
* - {string} id: The browser id (e.g. `firefox`,`safari_ios`). Should be one of TARGET_BROWSER_ID
* - {string} name: The browser display name (e.g. `Firefox`,`Safari for IOS`, …)
* - {string} version: The browser version (e.g. `99`,`15.3`, `1.0.4`, …)
* - {string} status: The browser status (e.g. `current`,`beta`, …). Should be one of TARGET_BROWSER_STATUS
*/
async function getBrowsersList() {
const records = await RemoteSettings("devtools-compatibility-browsers", {
filterFunc: record => {
if (
!TARGET_BROWSER_ID.includes(record.browserid) ||
!TARGET_BROWSER_STATUS.includes(record.status)
) {
return null;
}
return {
id: record.browserid,
name: record.name,
version: record.version,
status: record.status,
};
},
}).get();
const numericCollator = new Intl.Collator([], { numeric: true });
records.sort((a, b) => {
if (a.id == b.id) {
return numericCollator.compare(a.version, b.version);
}
return a.id > b.id ? 1 : -1;
});
// MDN compat data might have browser data that have the same id and status.
// In this case, only keep the newer version to keep uniqueness by id and status.
// This needs to be done after sorting since we rely on the order of the records.
return records.filter((record, index, arr) => {
const nextRecord = arr[index + 1];
// If the next record in the array is the same browser and has the same status, filter
// out this one since it's a lower version.
if (
nextRecord &&
record.id === nextRecord.id &&
record.status === nextRecord.status
) {
return false;
}
return true;
});
}
/**
* Returns the list of browsers for which we should check compatibility issues.
*
* @returns Promise<Array<Object>> : Objects in the array have the following shape:
* - {string} id: The browser id (e.g. `firefox`,`safari_ios`). Should be one of TARGET_BROWSER_ID
* - {string} name: The browser display name (e.g. `Firefox`,`Safari for IOS`, …)
* - {string} version: The browser version (e.g. `99`,`15.3`, `1.0.4`, …)
* - {string} status: The browser status (e.g. `current`,`beta`, …). Should be one of TARGET_BROWSER_STATUS
*/
async function getTargetBrowsers() {
const targetsString = Services.prefs.getCharPref(TARGET_BROWSER_PREF, "");
const browsers = await getBrowsersList();
// If not value are stored in the pref, it means the user did not chose specific browsers,
// so we need to return the full list.
if (!targetsString) {
return browsers;
}
const selectedBrowsersAndStatuses = JSON.parse(targetsString);
return browsers.filter(
browser =>
!!selectedBrowsersAndStatuses.find(
({ id, status }) => browser.id == id && browser.status == status
)
);
}
/**
* Store the list of browser id and status that should be used for checking compatibility
* issues.
*
* @param {Object[]} browsers
* @param {string} browsers[].id: The browser id. Should be one of TARGET_BROWSER_ID
* @param {string} browsers[].status: The browser status. Should be one of TARGET_BROWSER_STATUS
*/
function setTargetBrowsers(browsers) {
Services.prefs.setCharPref(
TARGET_BROWSER_PREF,
JSON.stringify(
// Only store the id and the status
browsers.map(browser => ({
id: browser.id,
status: browser.status,
}))
)
);
}
module.exports = {
getBrowsersList,
getTargetBrowsers,
setTargetBrowsers,
};