compatibility-user-settings.js (4566B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 const { RemoteSettings } = ChromeUtils.importESModule( 8 "resource://services-settings/remote-settings.sys.mjs" 9 ); 10 11 loader.lazyRequireGetter( 12 this, 13 ["TARGET_BROWSER_ID", "TARGET_BROWSER_STATUS", "TARGET_BROWSER_PREF"], 14 "resource://devtools/shared/compatibility/constants.js", 15 true 16 ); 17 18 class TargetBrowserFilter { 19 async filterEntry(record) { 20 if ( 21 !TARGET_BROWSER_ID.includes(record.browserid) || 22 !TARGET_BROWSER_STATUS.includes(record.status) 23 ) { 24 return null; 25 } 26 return { 27 id: record.browserid, 28 name: record.name, 29 version: record.version, 30 status: record.status, 31 }; 32 } 33 } 34 35 /** 36 * Returns the full list of browsers in the RemoteSetting devtools-compatibility-browsers 37 * collection (which is a flat copy of MDN compat data), sorted by browser and version. 38 * 39 * @returns Promise<Array<Object>> : Objects in the array have the following shape: 40 * - {string} id: The browser id (e.g. `firefox`,`safari_ios`). Should be one of TARGET_BROWSER_ID 41 * - {string} name: The browser display name (e.g. `Firefox`,`Safari for IOS`, …) 42 * - {string} version: The browser version (e.g. `99`,`15.3`, `1.0.4`, …) 43 * - {string} status: The browser status (e.g. `current`,`beta`, …). Should be one of TARGET_BROWSER_STATUS 44 */ 45 async function getBrowsersList() { 46 const records = await RemoteSettings("devtools-compatibility-browsers", { 47 filterCreator: async () => new TargetBrowserFilter(), 48 }).get(); 49 50 const numericCollator = new Intl.Collator([], { numeric: true }); 51 records.sort((a, b) => { 52 if (a.id == b.id) { 53 return numericCollator.compare(a.version, b.version); 54 } 55 return a.id > b.id ? 1 : -1; 56 }); 57 58 // MDN compat data might have browser data that have the same id and status. 59 // e.g. https://github.com/mdn/browser-compat-data/commit/53453400ecb2a85e7750d99e2e0a1611648d1d56#diff-31a16f09157f13354db27821261604aa 60 // In this case, only keep the newer version to keep uniqueness by id and status. 61 // This needs to be done after sorting since we rely on the order of the records. 62 return records.filter((record, index, arr) => { 63 const nextRecord = arr[index + 1]; 64 // If the next record in the array is the same browser and has the same status, filter 65 // out this one since it's a lower version. 66 if ( 67 nextRecord && 68 record.id === nextRecord.id && 69 record.status === nextRecord.status 70 ) { 71 return false; 72 } 73 74 return true; 75 }); 76 } 77 78 /** 79 * Returns the list of browsers for which we should check compatibility issues. 80 * 81 * @returns Promise<Array<Object>> : Objects in the array have the following shape: 82 * - {string} id: The browser id (e.g. `firefox`,`safari_ios`). Should be one of TARGET_BROWSER_ID 83 * - {string} name: The browser display name (e.g. `Firefox`,`Safari for IOS`, …) 84 * - {string} version: The browser version (e.g. `99`,`15.3`, `1.0.4`, …) 85 * - {string} status: The browser status (e.g. `current`,`beta`, …). Should be one of TARGET_BROWSER_STATUS 86 */ 87 async function getTargetBrowsers() { 88 const targetsString = Services.prefs.getCharPref(TARGET_BROWSER_PREF, ""); 89 const browsers = await getBrowsersList(); 90 91 // If not value are stored in the pref, it means the user did not chose specific browsers, 92 // so we need to return the full list. 93 if (!targetsString) { 94 return browsers; 95 } 96 97 const selectedBrowsersAndStatuses = JSON.parse(targetsString); 98 return browsers.filter( 99 browser => 100 !!selectedBrowsersAndStatuses.find( 101 ({ id, status }) => browser.id == id && browser.status == status 102 ) 103 ); 104 } 105 106 /** 107 * Store the list of browser id and status that should be used for checking compatibility 108 * issues. 109 * 110 * @param {object[]} browsers 111 * @param {string} browsers[].id: The browser id. Should be one of TARGET_BROWSER_ID 112 * @param {string} browsers[].status: The browser status. Should be one of TARGET_BROWSER_STATUS 113 */ 114 function setTargetBrowsers(browsers) { 115 Services.prefs.setCharPref( 116 TARGET_BROWSER_PREF, 117 JSON.stringify( 118 // Only store the id and the status 119 browsers.map(browser => ({ 120 id: browser.id, 121 status: browser.status, 122 })) 123 ) 124 ); 125 } 126 127 module.exports = { 128 getBrowsersList, 129 getTargetBrowsers, 130 setTargetBrowsers, 131 };