Skip to content

Instantly share code, notes, and snippets.

@24Ryou
Last active June 1, 2023 02:02
Show Gist options
  • Save 24Ryou/6b123ec55b1835fc5fdd21630244f2de to your computer and use it in GitHub Desktop.
Save 24Ryou/6b123ec55b1835fc5fdd21630244f2de to your computer and use it in GitHub Desktop.

Chrome Flags Backup

goto chrome://flags/ the press f12 and paste code then run backup() or 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