Skip to content

Commit

Permalink
handle toolkit.legacyUserProfileCustomizations.stylesheets (close #22)
Browse files Browse the repository at this point in the history
  • Loading branch information
NiklasGollenstede committed May 26, 2019
1 parent fe9318c commit 9711de9
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 13 deletions.
2 changes: 1 addition & 1 deletion background/chrome/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ async function writeStyles(process, clear, replace) {
loaded[key] = extract(loaded[key].replace(/\r\n?/g, '\n'));
});
} }
(await native.write(files, replace));
(await native.write(files, replace, true));

changed = Object.entries((await loaded)).some(([ key, loaded, ]) => written[key] !== loaded);
fireWritten([ changed, ]);
Expand Down
63 changes: 51 additions & 12 deletions background/chrome/native.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,70 @@ module.exports = {

//// start implementation

const FS = require('fs'), { promisify, } = require('util'), { EOL, } = require('os');
const FS = require('fs'), { promisify, } = require('util'), { EOL, } = require('os'), VM = require('vm');
const access = promisify(FS.access), mkdir = promisify(FS.mkdir), readFile = promisify(FS.readFile), writeFile = promisify(FS.writeFile);
const { profileDir, } = require('browser');

async function write(files, exp = '.*') {
try { (await access(profileDir)); } catch (_) { throw new Error(`Cant access profile directory in "${ profileDir }"`); }
async function write(files, exp = '.*', enable = false) {
try { (await access(profileDir)); } catch (_) { throw new Error(`Cant access profile directory in "${profileDir}"`); }
try { (await mkdir(profileDir +'/chrome')); } catch (_) { }

(await Promise.all([ 'chrome', 'content', ].map(async type => {
const old = (await readSafe(type));
const css = old.replace(new RegExp(exp +'|$'), () => files[type].replace(/\n/g, EOL));

(await writeFile(profileDir +`/chrome/userC${type.slice(1)}.css`, css, 'utf-8'));
})));
(await Promise.all([
replaceInFile(cssFilePath('chrome'), exp, files.chrome),
replaceInFile(cssFilePath('content'), exp, files.content),
enable && setUserConfig([
{ name: 'toolkit.legacyUserProfileCustomizations.stylesheets', value: true, comment: 'enforced by reStyle, required to apply browser styles', },
]).catch(console.error),
]));
}

async function read() {
const files = { chrome: '', content: '', };
(await Promise.all(Object.keys(files).map(async type => {
files[type] = (await readSafe(type));
files[type] = (await readIfExists(cssFilePath(type)));
})));
return files;
}

async function readSafe(type) {
try { return (await readFile(profileDir +`/chrome/userC${type.slice(1)}.css`, 'utf-8')); }
function cssFilePath(type) { return profileDir +`/chrome/userC${ type.slice(1) }.css`; }

async function readIfExists(path) {
try { return (await readFile(path, 'utf-8')); }
catch (error) { error && error.code !== 'ENOENT' && console.error(error); return ''; }
}

async function replaceInFile(path, exp, content) {
content = (await readIfExists(path))
.replace(new RegExp(exp +'|$'), () => content.replace(/\n/g, EOL));
(await writeFile(path, content, 'utf-8'));
}

/**
* Writes `about:config` values to the current profiles `user.js` file.
* If one or more entry with the same name exists, the first one will be replaced
* and the remaining ones removed. If none existed, the new entry will be appended.
* This function currently doesn't handle multi-line entries or comments properly.
* @param {[object]} prefs Array of objects representing the entries to write:
* @property {string} name Name of the config value.
* @property {string|number|boolean} value New value to write.
* @property {string} comment Single-line comment to append to the new line.
* @throws {TypeError} If the `user.js` file is not valid JavaScript before or after replacing the values.
*/
async function setUserConfig(prefs) {
const path = profileDir +'/user.js';
let script = tryCompile((await readIfExists(path)));

for (const { name, value, comment, } of prefs) {
let replaced = false;
script = tryCompile(script.replace(new RegExp(
`\\n\\s*?user_pref\\((["'])${ name.replace(/([.])/g, '[$1]') }\\1.*|$`, 'g'
), match => {
if (replaced) { return match ? '\n' : ''; } replaced = true;
return `\nuser_pref(${ JSON.stringify(name) }, ${ JSON.stringify(value) });`+ (comment ? ' // '+ comment : '');
}));
}

function tryCompile(script) { new VM.Script(script, { filename: 'user.js', }); return script; }

(await writeFile(path, script, 'utf-8'));
}

0 comments on commit 9711de9

Please sign in to comment.