Skip to content

Commit

Permalink
use native-ext v0.3.0 (2h)
Browse files Browse the repository at this point in the history
  • Loading branch information
NiklasGollenstede committed Jun 6, 2018
1 parent 6b3e64c commit 7d39649
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 114 deletions.
52 changes: 23 additions & 29 deletions background/chrome/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
(function(global) { 'use strict'; define(({ // 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/.
'node_modules/web-ext-utils/browser/': { manifest, rootUrl, },
'node_modules/web-ext-utils/loader/views': { openView, },
'node_modules/web-ext-utils/utils/': { reportError, },
'node_modules/web-ext-utils/utils/event': { setEvent, },
'node_modules/native-ext/': Native,
'node_modules/es6lib/functional': { debounce, },
'node_modules/regexpx/': RegExpX,
'common/options': options,
'../util': { debounceIdle, },
Expand All @@ -24,7 +22,7 @@ class ChromeStyle {
// that means they are pretty useless unless they are !important ==> add that to all rules
this.chrome = (chrome || '').toString({ minify: false, important: true, namespace: false, }).trim().replace(/\r\n?/g, '\n');
this.content = (content || '').toString({ minify: false, important: true, namespace: false, }).trim().replace(/\r\n?/g, '\n');
writeStyles();
applyStyles();
}

static get changed() { return changed; }
Expand All @@ -33,13 +31,13 @@ class ChromeStyle {
if (!styles.has(this)) { return; }
styles.delete(this);
this.code = null;
writeStyles();
applyStyles();
}

toJSON() { return { path: this.path, chrome: this.chrome, content: this.content, }; }

static fromJSON({ path, chrome, content, }) {
// writeStyles(); // this is only used to load styles after a restart. This style should not have changed since it was last written.
// applyStyles(); // this is only used to load styles after a restart. This style should not have changed since it was last written.
return new ChromeStyle(path, chrome, content);
}

Expand Down Expand Up @@ -78,24 +76,23 @@ function extract(file) {
return (rExtract.exec(file) || [ '', ])[0].replace(/^\n?.*\n/, '').replace(/\n.*\n?$/, '');
}

// `load` tries to require the ./native module in node.js, returns `false` if that fails
// `unload` releases the module after a while to allow node.js to quit
let native = null; const load = async () => {
if (native) { return native; }
if (!(await Native.test())) {
reportError(`NativeExt unaviable`, `${manifest.name} could not connect to it's native counterpart. To use chrome styles, please follow the setup instructions.`);
active = options.chrome.value = false; openView('setup'); return null;
}
return (native = (await Native.require(require.resolve('./native'))));
}, unload = debounce(() => {
Native.unref(native); native = null;
}, 60e3);

// `writeStyles` actually writes the styles, but not to frequently and only if `options.chrome` enabled
let current = null, active = options.chrome.value; options.chrome.onChange(([ value, ]) => { active = value; writeStyles(!value); });
const writeStyles = debounceIdle(async (clear) => { try {
// `applyStyles` actually writes the styles, but not to frequently and only if `options.chrome` enabled
let active = options.chrome.value; options.chrome.onChange(([ value, ]) => { active = value; applyStyles(!value); });
const applyStyles = debounceIdle(async (clear) => {
if (!(active || clear)) { return; } // this shouldn't be possible
if (clear && !current) { return; } // witched off but didn't work before

Native.getApplicationName({ stale: true, }).then(name => !name
&& reportError('Set up NativeExt', `Applying chrome styles requires NativeExt, but it is not installed or not set up correctly.`)
);

Native.do(writeStyles); // deduplicates calls (until started)
}, 1e3);

let current = null; async function writeStyles(process) { try {
let clear; if (!active) { if (current) { clear = true; } { return; } }

if (!active && (!clear || !current)) { return; } if (!(await load())) { return; }
const sorted = clear ? null : Array.from(styles).sort((a, b) => a.path < b.path ? -1 : 1);

// TODO: this throws all @namespace declarations into a single file. Is that even supposed to work? Do later (default) declarations overwrite earlier ones?
Expand All @@ -108,21 +105,18 @@ const writeStyles = debounceIdle(async (clear) => { try {
).join('\n')) + suffix
));

if (!current) {
current = (await native.read());
const native = (await process.require(require.resolve('./native')));
if (!current) { current = (await native.read()); {
Object.keys(current).forEach(key => {
current[key] = extract(current[key].replace(/\r\n?/g, '\n'));
});
}

} }
(await native.write(files, rExtractSource));

changed = Object.entries((await current)).some(([ key, current, ]) => data[key] !== current);

fireWritten([ changed, ]);
} catch (error) {
reportError(`Failed to write chrome styles`, error);
} finally { unload(); } }, 1e3);

} catch (error) { reportError(`Failed to write chrome styles`, error); } }


return ChromeStyle;
Expand Down
11 changes: 2 additions & 9 deletions background/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
(function(global) { 'use strict'; define(async ({ // 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/.
'node_modules/web-ext-utils/browser/': Browser,
'node_modules/web-ext-utils/update/': updated,
'node_modules/web-ext-utils/utils/': { reportError, },
'node_modules/native-ext/': Native,
'common/options': options,
'views/': _, // put views in TabView (but doesn't load them yet)
Expand All @@ -14,17 +13,11 @@
}) => {

/**
* This file mostly just requires other files in order to load them.
* This file just requires other files in order to load them.
* LocalStyle and RemoteStyle automatically load their styles from their sources
* and apply them as ChromeStyles or ContentStyles.
*/


// handle uncaught exceptions/rejections in the native modules to prevent the process from exiting
Native.onUncaughtException(error => { reportError('Unhandled error in native code', error); /*Native.nuke();*/ });
Native.onUnhandledRejection(error => { reportError('Unhandled rejection in native code', error); /*Native.nuke();*/ });
// TODO: don't just log the errors, they could be critical

void (updated, Badge, LocalStyle, RemoteStyle); // must load these

// debug stuff
Object.assign(global, module.exports = {
Expand Down
75 changes: 41 additions & 34 deletions background/local/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
(function(global) { 'use strict'; define(({ // 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/.
'node_modules/web-ext-utils/browser/': { manifest, },
'node_modules/web-ext-utils/loader/views': { openView, },
'node_modules/web-ext-utils/utils/': { reportError, },
'node_modules/native-ext/': Native,
'common/options': options,
Expand All @@ -27,14 +25,14 @@ class LocalStyle extends Style {

/// creates a new `.css` file in the local folder
static async createStyle(name, file) {
if (!native) { throw new Error(`Can only write files if Development mode is enabled`); }
if (!native) { throw new Error(`Can only write files if NativeExt is set up and Development mode is enabled`); }
const path = options.local.children.folder.value.replace(/([\\/])?$/, _=>_ || '/') + name;
(await native.createStyle(path, file)); return path;
}

/// opens a `.css` file in the local folder with the systems default editor
static async openStyle(name) {
if (!native) { throw new Error(`Can only write files if Development mode is enabled`); }
if (!native) { throw new Error(`Can only open files if NativeExt is set up and Development mode is enabled`); }
const path = options.local.children.folder.value.replace(/([\\/])?$/, _=>_ || '/') + name;
(await native.openStyle(path)); return path;
}
Expand All @@ -52,36 +50,42 @@ class LocalStyle extends Style {

//// start implementation

let native = null/*Port*/; const styles = new Map/*<id, LocalStyle>*/; let exclude = null/*RegExp*/;
let active = options.local.value; options.local.onChange(async ([ value, ]) => { try { (await (value ? enable() : disable())); } catch (error) { reportError(error); } });
let unloading = false; global.addEventListener('unload', () => (unloading = true));

if (active) { enable(true).catch(reportError); } else { if (global.__startupSyncPoint__) { global.__startupSyncPoint__(); } else { global.__startupSyncPoint__ = () => null; } }
let native = null/*exports*/, onSpawn, waiting;
const styles = new Map/*<id, LocalStyle>*/; let exclude = null/*RegExp*/;
options.local.children.folder.onChange(async () => {
if (active) { try { disable(); (await enable()); } catch (error) { reportError(error); } }
});
let active = options.local.value; options.local.onChange(async ([ value, ]) => {
try { (await (value ? enable() : disable())); } catch (error) { reportError(error); }
});
if (active) { enable(true).catch(reportError); } else { letRemoteProceed(); }

// reads the local dir and starts listening for changes of it or the chrome/ dir
async function enable(init) {
if (active && !init) { return; } active = options.local.value = true;

if (!(await Native.test())) {
reportError(`NativeExt unaviable`, `${manifest.name} could not connect to it's native counterpart. To use local styles, please follow the setup instructions.`);
disable(); openView('setup'); return;
}
if (!(await Native.getApplicationName({ stale: true, }))) { {
reportError('Set up NativeExt', `Loading local styles requires NativeExt, but it is not installed or not set up correctly.`);
!waiting && (waiting = Native.getApplicationName({ blocking: true, }).then(() => enable()));
active = false; letRemoteProceed();
} return; } waiting = null;

// console.log('enable local styles');
exclude = new RegExp(options.local.children.exclude.value || '^.^');
native = (await Native.require(
require.resolve('./native'),
{ onDisconnect: () => global.setTimeout(() => {
!unloading && active && reportError('Connection to native extension lost');
// TODO: show permanent notification with option to restart
}, 20), },
));
const files = (await Native.on((onSpawn = async process => {
native = (await process.require(require.resolve('./native')));

const files = (await native.readStyles(options.local.children.folder.value, onCange));
if (options.local.children.chrome.value) { debounceIdle(() => {
files && active && native && native.watchChrome(onChromeChange);
}, 2500)(); }

return native.readStyles(options.local.children.folder.value, onCange);
})));

if (files === null) { return void reportError(`Can't read local dir`,
`The folder "${options.local.children.folder.value}" does not exist of can not be read. To use local styles, create the folder or change it in the options.`
); }
if (files === null) { {
Native.on.removeListener(onSpawn); active = false; letRemoteProceed();
reportError(`Can't read local dir`, `The folder "${options.local.children.folder.value}" does not exist or can not be read. To use local styles, create the folder or change it in the options.`);
} return; }

// console.log('got local styles', files);
(await Promise.all(
Expand All @@ -102,11 +106,16 @@ async function enable(init) {
}

styles.forEach(style => { try { style.disabled = false; } catch (error) { reportError(`Failed to add local style`, error); } });
}

if (!options.local.children.chrome.value) { return; }
function disable() {
options.local.value = false; if (!active) { return; } active = false;
// console.log('disable local styles');
Array.from(styles.values(), _=>_.destroy()); styles.clear();

(await new Promise(done => debounceIdle(done, 2500)()));
native.watchChrome(onChromeChange);
native && native.release(onCange);
native && native.release(onChromeChange);
Native.on.removeListener(onSpawn); native = null;
}

// called when a .css file in the local dir was actually changed
Expand Down Expand Up @@ -180,13 +189,11 @@ async function onChromeChange(path, css) { try {
})));
} catch (error) { console.error('Error in fs.watch handler', error); } }

function disable() {
options.local.value = false; if (!active) { return; } active = false;
// console.log('disable local styles');
Array.from(styles.values(), _=>_.destroy()); styles.clear();
native && native.release(onCange);
Native.unref(native); native = null;
}
function letRemoteProceed() { if (global.__startupSyncPoint__) {
global.__startupSyncPoint__();
} else {
global.__startupSyncPoint__ = () => null;
} }

return LocalStyle;

Expand Down
2 changes: 1 addition & 1 deletion background/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ const chromeUrlPrefixes = [
'chrome://', // only this (?)
];

const contentDomains = options.advanced.children.restrictedDomains.value.split(',');
const contentDomains = options.internal.children.restrictedDomains.value.split(',');
const contentUrlPrefixes = [
'about:',
'blob:', 'data:', // pretty sure data: doesn't work in a WebStyle, and even if blob:https?:// does, others shouldn't
Expand Down
11 changes: 6 additions & 5 deletions build-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = function({ options, /*packageJson,*/ manifestJson, files, }) {
manifestJson.permissions.push(
'nativeMessaging',
'notifications',
// 'sessions', // remove closed popups // TODO: add this as a minor update at some point
'tabs',
'webNavigation',
'<all_urls>',
Expand All @@ -22,16 +23,16 @@ module.exports = function({ options, /*packageJson,*/ manifestJson, files, }) {
files.node_modules = [
'es6lib/dom.js',
'es6lib/functional.js',
'multiport/index.js',
'native-ext/index.js',
'native-ext/install.js',
'native-ext/tar.js',
'native-ext/version-native.js',
'native-ext/init.node.js',
'native-ext/manager.js',
'native-ext/process.js',
'pbq/require.js',
'regexpx/index.js',
'web-ext-utils/browser/index.js',
'web-ext-utils/browser/storage.js',
'web-ext-utils/browser/version.js',
'web-ext-utils/lib/multiport/index.js',
'web-ext-utils/lib/pbq/require.js',
'web-ext-utils/loader/_background.html',
'web-ext-utils/loader/_background.js',
'web-ext-utils/loader/_view.html',
Expand Down
4 changes: 2 additions & 2 deletions common/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ const model = {
},
},
},
advanced: {
title: 'Advanced',
internal: {
title: 'Internal',
expanded: false,
hidden: !isBeta,
description: `Proceed at your own risk`,
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "re-style",
"version": "0.3.2",
"version": "0.4.0",
"title": "reStyle",
"description": "A user style manager for Firefox 57+ which can load local files and apply UI styles",
"author": "Niklas Gollenstede",
Expand All @@ -18,10 +18,12 @@
],
"dependencies": {
"es6lib": "0.0.2",
"native-ext": "0.2.3",
"multiport": "0.2.3",
"native-ext": "0.3.0",
"pbq": "0.3.3",
"regexpx": "0.1.4",
"web-ext-build": "0.0.9",
"web-ext-utils": "0.0.20"
"web-ext-utils": "0.1.1"
},
"devDependencies": {
"babel-eslint": "8.2.2",
Expand Down
12 changes: 6 additions & 6 deletions views/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ return new Home({
backgroundSize: '80%', height: '100%',
backgroundImage: `url(${ getURL('icon.svg') })`,
}, }),
}, {
id: 'setup',
title: 'Setup',
icon: createElement('div', { style: {
position: 'relative', fontSize: '130%', top: '-6px',
}, }, [ '❔', ]),
}, {
id: 'options',
title: 'Options',
icon: createElement('div', { style: {
position: 'relative', fontSize: '180%', top: '-5px',
}, }, [ '⚙', ]),
}, {
id: 'setup',
title: 'Setup',
icon: createElement('div', { style: {
position: 'relative', fontSize: '130%', top: '-6px',
}, }, [ '❔', ]),
}, {
id: 'about',
title: 'About',
Expand Down
18 changes: 16 additions & 2 deletions views/panel.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(function(global) { 'use strict'; define(({ // 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/.
'node_modules/web-ext-utils/browser/': { Tabs, },
'node_modules/web-ext-utils/browser/': { Tabs, WebNavigation, },
'node_modules/web-ext-utils/loader/views': { openView, },
'node_modules/web-ext-utils/utils/': { reportError, reportSuccess, },
'node_modules/es6lib/dom': { createElement, },
Expand All @@ -17,7 +17,7 @@ document.body.innerHTML = `<style>
:root { font-family: Segoe UI, Tahoma, sans-serif; overflow: hidden; }
:root, body { background: #424f5a; } body>* { filter: invert(1) hue-rotate(180deg); }
:root { box-sizing: border-box; } * { box-sizing: inherit; }
:root { width: 350px; margin-bottom: -1px; } body { width: 333px; margin: 0; }
:root { margin-bottom: -1px; } body { min-width: 333px; margin: 0; }
:root { user-select: none; -moz-user-select: none; }
</style><div id=main>
<style>
Expand Down Expand Up @@ -181,4 +181,18 @@ if ((/^https?:$/).test(url.protocol)) {
} else { addTo.style.display = 'none'; }
} else { addTo.style.display = 'none'; }


/// reload on tab change
function reload(info) { (
info.transitionType // webNavigation
? info.tabId === tab.id && info.frameId === 0
: info.windowId === tab.windowId
) && window.location.reload(); }
Tabs.onActivated.addListener(reload);
WebNavigation.onCommitted.addListener(reload); // actual url changes (Tabs.onUpdated) would be correct, but might be to annoying
window.addEventListener('unload', () => {
Tabs.onActivated.removeListener(reload);
WebNavigation.onCommitted.removeListener(reload);
});

}); })(this);
Loading

0 comments on commit 7d39649

Please sign in to comment.