-
-
Save jimbrig/f35e7be71cea5a52269de237c13276b2 to your computer and use it in GitHub Desktop.
Backup chrome flags to json and restore the backup on another machine.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 2022-04-03, tested with Chrome 99.0.4844.84 on MacBook Pro m1 | |
/* | |
Open chrome://flags/ | |
F12 open developer console, swtich to tab "Console" | |
Paste below codes | |
- input backup() to download flags backup file | |
- input restore() to select one backup to restore | |
*/ | |
function saveFile(filename, data) { | |
return new Promise(resolve => { | |
const blob = new Blob([data], { type: 'octet/stream' }); | |
const url = window.URL.createObjectURL(blob); | |
const dom = document.createElement('a'); | |
setTimeout(() => { | |
dom.href = url; | |
dom.download = filename; | |
dom.dispatchEvent(new MouseEvent('click')); | |
window.URL.revokeObjectURL(url); | |
resolve(); | |
}); | |
}); | |
} | |
function selectFile(ext) { | |
return new Promise((resolve, reject) => { | |
const input = document.createElement('input'); | |
input.type = 'file'; | |
input.accept = '.json'; | |
input.onchange = (e) => { | |
if (e.target.files.length == 0) { | |
reject("canceled"); | |
return; | |
} | |
const file = e.target.files[0]; | |
resolve(file); | |
}; | |
input.dispatchEvent(new MouseEvent('click')); | |
}); | |
} | |
function readFile(file) { | |
return new Promise((resolve, reject) => { | |
const reader = new FileReader(); | |
reader.onabort = reader.onerror = e => reject(e); | |
reader.onload = e => resolve(e.target.result); | |
reader.readAsBinaryString(file); | |
}); | |
} | |
async function getFlags() { | |
const module = await import('chrome://resources/js/cr.m.js'); | |
const config = await module.sendWithPromise('requestExperimentalFeatures'); | |
return config; | |
} | |
function parseFlags(config) { | |
const flags = {}; | |
config.supportedFeatures.forEach(flag => { | |
const k = flag.internal_name; | |
flags[k] = flag; | |
if (flag.options) { | |
const options = flag.options.filter(option => option.selected); | |
flag.selected = options.length == 0 ? flag.options[0] : options[0]; | |
flag.value = flag.selected.internal_name; | |
} else { | |
flag.value = flag.enabled.toString(); | |
} | |
}); | |
return flags; | |
} | |
async function backup() { | |
const config = await getFlags(); | |
await saveFile("backup.chrome-flags.json", JSON.stringify(config)); | |
} | |
async function restore() { | |
const file = await selectFile('.json'); | |
const data = await readFile(file); | |
const flags = parseFlags(JSON.parse(data)); | |
const current = parseFlags(await getFlags()); | |
const keys = Array.from(new Set(Object.keys(flags).concat(Object.keys(current)))); | |
const same = keys.filter(k => current[k].value == flags[k].value); | |
const diff = keys.filter(k => same.indexOf(k) == -1); | |
const tasks = []; | |
const table = diff.map(k => { | |
const a = current[k]; | |
const b = flags[k]; | |
const noOptions = ["trie", "false"].indexOf(a.value) != -1; | |
tasks.push(noOptions ? [k, b.value] : [b.value, "true"]); | |
return noOptions ? { | |
name: flags[k].name, | |
current: a.value, | |
update: b.value, | |
url: `chrome://flags/#${current[k].internal_name}`, | |
} : { | |
name: flags[k].name, | |
current: a.selected.description, | |
update: b.selected.description, | |
url: `chrome://flags/#${current[k].internal_name}`, | |
}; | |
}); | |
console.table(table); | |
console.log(`%c skip ${same.length} same items`, 'background: #FF0; color: #202124'); | |
console.log(`%c restore ${diff.length} diff items:`, 'background: #FF0; color: #202124'); | |
for (const task of tasks) { | |
chrome.send("enableExperimentalFeature", task); | |
} | |
} | |
// backup(); | |
// restore(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment