WIP
This commit is contained in:
parent
0f148eac32
commit
6d32ffb76b
|
@ -4,15 +4,17 @@ global handleCssTransitionBug detectSloppyRegexps
|
|||
global openEditor
|
||||
global styleViaAPI
|
||||
global loadScript
|
||||
global usercss
|
||||
global usercss styleManager
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
window.API_METHODS = Object.assign(window.API_METHODS || {}, {
|
||||
|
||||
getStyles,
|
||||
saveStyle,
|
||||
deleteStyle,
|
||||
// getStyles,
|
||||
getSectionsByUrl: styleManager.getSectionsByUrl,
|
||||
getSectionsById: styleManager.getSectionsById,
|
||||
// saveStyle,
|
||||
// deleteStyle,
|
||||
|
||||
getStyleFromDB: id =>
|
||||
dbExec('get', id).then(event => event.target.result),
|
||||
|
@ -495,25 +497,33 @@ function updateIcon({tab, styles}) {
|
|||
|
||||
|
||||
function onRuntimeMessage(msg, sender, sendResponse) {
|
||||
const fn = window.API_METHODS[msg.method];
|
||||
if (!fn) return;
|
||||
if (msg.method !== 'invokeAPI') {
|
||||
// FIXME: switch everything to api.js then throw an error when msg.method is unknown.
|
||||
return;
|
||||
}
|
||||
invoke()
|
||||
.catch(err =>
|
||||
// wrap 'Error' object instance as {__ERROR__: message},
|
||||
// which will be unwrapped by api.js,
|
||||
({
|
||||
__ERROR__: err.message || String(err)
|
||||
})
|
||||
)
|
||||
// prevent exceptions on sending to a closed tab
|
||||
.then(output => tryCatch(sendResponse, output));
|
||||
// keep channel open
|
||||
return true;
|
||||
|
||||
// wrap 'Error' object instance as {__ERROR__: message},
|
||||
// which will be unwrapped by sendMessage,
|
||||
// and prevent exceptions on sending to a closed tab
|
||||
const respond = data =>
|
||||
tryCatch(sendResponse,
|
||||
data instanceof Error ? {__ERROR__: data.message} : data);
|
||||
|
||||
const result = fn(msg, sender, respond);
|
||||
if (result instanceof Promise) {
|
||||
result
|
||||
.catch(e => ({__ERROR__: e instanceof Error ? e.message : e}))
|
||||
.then(respond);
|
||||
return KEEP_CHANNEL_OPEN;
|
||||
} else if (result === KEEP_CHANNEL_OPEN) {
|
||||
return KEEP_CHANNEL_OPEN;
|
||||
} else if (result !== undefined) {
|
||||
respond(result);
|
||||
function invoke() {
|
||||
try {
|
||||
const fn = window.API_METHODS[msg.name];
|
||||
if (!fn) {
|
||||
throw new Error(`unknown API: ${msg.name}`);
|
||||
}
|
||||
const context = {msg, sender};
|
||||
return Promise.resolve(fn.apply(context, msg.args));
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
const db = (() => {
|
||||
let exec;
|
||||
const preparing = prepare();
|
||||
|
@ -103,9 +105,9 @@ const db = (() => {
|
|||
|
||||
case 'put':
|
||||
if (!data.id) {
|
||||
return getStyles().then(() => {
|
||||
return getAllStyles().then(styles => {
|
||||
data.id = 1;
|
||||
for (const style of cachedStyles.list) {
|
||||
for (const style of styles) {
|
||||
data.id = Math.max(data.id, style.id + 1);
|
||||
}
|
||||
return dbExecChromeStorage('put', data);
|
||||
|
@ -118,17 +120,22 @@ const db = (() => {
|
|||
return chromeLocal.remove(STYLE_KEY_PREFIX + data);
|
||||
|
||||
case 'getAll':
|
||||
return chromeLocal.get(null).then(storage => {
|
||||
const styles = [];
|
||||
for (const key in storage) {
|
||||
if (key.startsWith(STYLE_KEY_PREFIX) &&
|
||||
Number(key.substr(STYLE_KEY_PREFIX.length))) {
|
||||
styles.push(storage[key]);
|
||||
}
|
||||
}
|
||||
return {target: {result: styles}};
|
||||
});
|
||||
return getAllStyles()
|
||||
.then(styles => ({target: {result: styles}}));
|
||||
}
|
||||
return Promise.reject();
|
||||
|
||||
function getAllStyles() {
|
||||
return chromeLocal.get(null).then(storage => {
|
||||
const styles = [];
|
||||
for (const key in storage) {
|
||||
if (key.startsWith(STYLE_KEY_PREFIX) &&
|
||||
Number(key.substr(STYLE_KEY_PREFIX.length))) {
|
||||
styles.push(storage[key]);
|
||||
}
|
||||
}
|
||||
return styles;
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
/* global createCache db calcStyleDigest normalizeStyleSections db */
|
||||
'use strict';
|
||||
|
||||
const styleManager = (() => {
|
||||
const preparing = prepare();
|
||||
const styles = new Map;
|
||||
const styles = new Map();
|
||||
const cachedStyleForUrl = createCache();
|
||||
const compiledRe = createCache();
|
||||
const compiledExclusion = createCache();
|
||||
|
@ -50,6 +53,7 @@ const styleManager = (() => {
|
|||
cachedStyleForUrl.clear();
|
||||
// FIXME: invalid signature
|
||||
notifyAllTabs();
|
||||
return style;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -68,7 +72,7 @@ const styleManager = (() => {
|
|||
// FIXME: update installDate?
|
||||
style = Object.assign(oldStyle, style);
|
||||
style.sections = normalizeStyleSections(style);
|
||||
return dbExec('put', style);
|
||||
return db.exec('put', style);
|
||||
})
|
||||
.then(event => {
|
||||
if (style.id == null) {
|
||||
|
@ -142,7 +146,7 @@ const styleManager = (() => {
|
|||
}
|
||||
|
||||
function urlMatchStyle(url, style) {
|
||||
if (style.exclusions && style.exclusions.some(e => compileExclusion(e).test(url)) {
|
||||
if (style.exclusions && style.exclusions.some(e => compileExclusion(e).test(url))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -22,10 +22,10 @@ API_METHODS.styleViaAPI = !CHROME && (() => {
|
|||
|
||||
let observingTabs = false;
|
||||
|
||||
return (request, sender) => {
|
||||
return function (request) {
|
||||
const action = ACTIONS[request.action];
|
||||
return !action ? NOP :
|
||||
action(request, sender)
|
||||
action(request, this.sender)
|
||||
.catch(onError)
|
||||
.then(maybeToggleObserver);
|
||||
};
|
||||
|
|
55
content/api.js
Normal file
55
content/api.js
Normal file
|
@ -0,0 +1,55 @@
|
|||
'use strict';
|
||||
|
||||
const API = (() => {
|
||||
const preparing = promisify(chrome.runtime.getBackgroundPage.bind(chrome.runtime))()
|
||||
.catch(() => null);
|
||||
const runtimeSendMessage = promisify(chrome.runtime.sendMessage.bind(chrome.runtime));
|
||||
return new Proxy(() => {}, {
|
||||
get: (target, name) =>
|
||||
(...args) => invokeBG(name, args),
|
||||
});
|
||||
|
||||
function sendMessage(msg) {
|
||||
return runtimeSendMessage(msg)
|
||||
.then(result => {
|
||||
if (result.__ERROR__) {
|
||||
throw new Error(result.__ERROR__);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function promisify(fn) {
|
||||
return (...args) =>
|
||||
new Promise((resolve, reject) => {
|
||||
fn(...args, (...result) => {
|
||||
if (chrome.runtime.lastError) {
|
||||
reject(chrome.runtime.lastError);
|
||||
return;
|
||||
}
|
||||
resolve(
|
||||
result.length === 0 ? undefined :
|
||||
result.length === 1 ? result[1] : result
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function invokeBG(name, args) {
|
||||
return preparing.then(BG => {
|
||||
if (!BG) {
|
||||
return sendMessage({
|
||||
method: 'invokeAPI',
|
||||
name,
|
||||
args
|
||||
});
|
||||
}
|
||||
// FIXME: why deep-copying input/output?
|
||||
if (BG !== window) {
|
||||
args = BG.deepCopy(args);
|
||||
}
|
||||
return BG.API_METHODS[name](...args)
|
||||
.then(BG.deepCopy);
|
||||
});
|
||||
}
|
||||
})();
|
|
@ -25,7 +25,13 @@
|
|||
const FF_BUG461 = !CHROME && !isOwnPage && !Event.prototype.getPreventDefault;
|
||||
const pageContextQueue = [];
|
||||
|
||||
requestStyles();
|
||||
requestStyles({}, styles => {
|
||||
// FIXME: need transition patch?
|
||||
// if (needTransitionPatch(styles)) {
|
||||
// applyTransitionPatch();
|
||||
// }
|
||||
applyStyles(styles);
|
||||
});
|
||||
chrome.runtime.onMessage.addListener(applyOnMessage);
|
||||
window.applyOnMessage = applyOnMessage;
|
||||
|
||||
|
@ -36,7 +42,7 @@
|
|||
|
||||
function requestStyles(options, callback = applyStyles) {
|
||||
if (!chrome.app && document instanceof XMLDocument) {
|
||||
chrome.runtime.sendMessage({method: 'styleViaAPI', action: 'styleApply'});
|
||||
API.styleViaAPI({action: 'styleApply'});
|
||||
return;
|
||||
}
|
||||
var matchUrl = location.href;
|
||||
|
@ -49,19 +55,15 @@
|
|||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
const request = Object.assign({
|
||||
method: 'getStylesForFrame',
|
||||
asHash: true,
|
||||
matchUrl,
|
||||
}, options);
|
||||
// On own pages we request the styles directly to minimize delay and flicker
|
||||
if (typeof API === 'function') {
|
||||
API.getStyles(request).then(callback);
|
||||
} else if (!CHROME && getStylesFallback(request)) {
|
||||
// NOP
|
||||
} else {
|
||||
chrome.runtime.sendMessage(request, callback);
|
||||
}
|
||||
// const request = Object.assign({
|
||||
// method: 'getStylesForFrame',
|
||||
// asHash: true,
|
||||
// matchUrl,
|
||||
// }, options);
|
||||
// FIXME: options?
|
||||
// FIXME: getStylesFallback?
|
||||
API.getSectionsByUrl(matchUrl)
|
||||
.then(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,12 +101,12 @@
|
|||
|
||||
if (!chrome.app && document instanceof XMLDocument && request.method !== 'ping') {
|
||||
request.action = request.method;
|
||||
request.method = 'styleViaAPI';
|
||||
request.method = null;
|
||||
request.styles = null;
|
||||
if (request.style) {
|
||||
request.style.sections = null;
|
||||
}
|
||||
chrome.runtime.sendMessage(request);
|
||||
API.styleViaAPI(request);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -120,7 +122,7 @@
|
|||
}
|
||||
if (request.style.enabled) {
|
||||
removeStyle({id: request.style.id, retire: true});
|
||||
requestStyles({id: request.style.id});
|
||||
API.getSectionsById(request.style.id).then(applyStyles);
|
||||
} else {
|
||||
removeStyle(request.style);
|
||||
}
|
||||
|
@ -128,7 +130,7 @@
|
|||
|
||||
case 'styleAdded':
|
||||
if (request.style.enabled) {
|
||||
requestStyles({id: request.style.id});
|
||||
API.getSectionsById(request.style.id).then(applyStyles);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -193,7 +195,7 @@
|
|||
addStyleElement(inCache);
|
||||
disabledElements.delete(id);
|
||||
} else {
|
||||
requestStyles({id});
|
||||
API.getSectionsById(id).then(applyStyles);
|
||||
}
|
||||
} else {
|
||||
if (inDoc) {
|
||||
|
@ -224,11 +226,11 @@
|
|||
}
|
||||
|
||||
function applyStyles(styles) {
|
||||
if (!styles) {
|
||||
// if (!styles) {
|
||||
// Chrome is starting up
|
||||
requestStyles();
|
||||
return;
|
||||
}
|
||||
// requestStyles();
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (!document.documentElement) {
|
||||
new MutationObserver((mutations, observer) => {
|
||||
|
@ -240,12 +242,13 @@
|
|||
return;
|
||||
}
|
||||
|
||||
if ('disableAll' in styles) {
|
||||
doDisableAll(styles.disableAll);
|
||||
}
|
||||
if ('exposeIframes' in styles) {
|
||||
doExposeIframes(styles.exposeIframes);
|
||||
}
|
||||
// FIXME: switch to prefs
|
||||
// if ('disableAll' in styles) {
|
||||
// doDisableAll(styles.disableAll);
|
||||
// }
|
||||
// if ('exposeIframes' in styles) {
|
||||
// doExposeIframes(styles.exposeIframes);
|
||||
// }
|
||||
|
||||
const gotNewStyles = styles.length || styles.needTransitionPatch;
|
||||
if (gotNewStyles) {
|
||||
|
@ -256,22 +259,17 @@
|
|||
}
|
||||
}
|
||||
|
||||
if (styles.needTransitionPatch) {
|
||||
applyTransitionPatch();
|
||||
}
|
||||
|
||||
if (gotNewStyles) {
|
||||
for (const id in styles) {
|
||||
const sections = styles[id];
|
||||
if (!Array.isArray(sections)) continue;
|
||||
applySections(id, sections.map(({code}) => code).join('\n'));
|
||||
for (const section of styles) {
|
||||
applySections(section.id, section.code);
|
||||
}
|
||||
docRootObserver.firstStart();
|
||||
}
|
||||
|
||||
if (FF_BUG461 && (gotNewStyles || styles.needTransitionPatch)) {
|
||||
setContentsInPageContext();
|
||||
}
|
||||
// FIXME
|
||||
// if (FF_BUG461 && (gotNewStyles || styles.needTransitionPatch)) {
|
||||
// setContentsInPageContext();
|
||||
// }
|
||||
|
||||
if (!isOwnPage && !docRewriteObserver && styleElements.size) {
|
||||
initDocRewriteObserver();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
function createCache(size = 1000) {
|
||||
const map = new Map;
|
||||
const map = new Map();
|
||||
const buffer = Array(size);
|
||||
let index = 0;
|
||||
let lastIndex = 0;
|
||||
|
@ -9,7 +11,9 @@ function createCache(size = 1000) {
|
|||
delete: delete_,
|
||||
clear,
|
||||
has: id => map.has(id),
|
||||
get size: () => map.size
|
||||
get size() {
|
||||
return map.size;
|
||||
}
|
||||
};
|
||||
|
||||
function get(id) {
|
||||
|
|
|
@ -104,61 +104,6 @@ if (FIREFOX_NO_DOM_STORAGE) {
|
|||
Object.defineProperty(window, 'sessionStorage', {value: {}});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-var
|
||||
var API = (() => {
|
||||
return new Proxy(() => {}, {
|
||||
get: (target, name) =>
|
||||
name === 'remoteCall' ?
|
||||
remoteCall :
|
||||
arg => invokeBG(name, arg),
|
||||
});
|
||||
|
||||
function remoteCall(name, arg, remoteWindow) {
|
||||
let thing = window[name] || window.API_METHODS[name];
|
||||
if (typeof thing === 'function') {
|
||||
thing = thing(arg);
|
||||
}
|
||||
if (!thing || typeof thing !== 'object') {
|
||||
return thing;
|
||||
} else if (thing instanceof Promise) {
|
||||
return thing.then(product => remoteWindow.deepCopy(product));
|
||||
} else {
|
||||
return remoteWindow.deepCopy(thing);
|
||||
}
|
||||
}
|
||||
|
||||
function invokeBG(name, arg = {}) {
|
||||
if (BG && (name in BG || name in BG.API_METHODS)) {
|
||||
const call = BG !== window ?
|
||||
BG.API.remoteCall(name, BG.deepCopy(arg), window) :
|
||||
remoteCall(name, arg, BG);
|
||||
return Promise.resolve(call);
|
||||
}
|
||||
if (BG && BG.getStyles) {
|
||||
throw new Error('Bad API method', name, arg);
|
||||
}
|
||||
if (FIREFOX) {
|
||||
arg.method = name;
|
||||
return sendMessage(arg);
|
||||
}
|
||||
return onBackgroundReady().then(() => invokeBG(name, arg));
|
||||
}
|
||||
|
||||
function onBackgroundReady() {
|
||||
return BG && BG.getStyles ? Promise.resolve() : new Promise(function ping(resolve) {
|
||||
sendMessage({method: 'healthCheck'}, health => {
|
||||
if (health !== undefined) {
|
||||
BG = chrome.extension.getBackgroundPage();
|
||||
resolve();
|
||||
} else {
|
||||
setTimeout(ping, 0, resolve);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
function notifyAllTabs(msg) {
|
||||
const originalMessage = msg;
|
||||
const styleUpdated = msg.method === 'styleUpdated' || msg.method === 'exclusionsUpdated';
|
||||
|
@ -224,7 +169,6 @@ function notifyAllTabs(msg) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function sendMessage(msg, callback) {
|
||||
/*
|
||||
Promise mode [default]:
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
"run_at": "document_start",
|
||||
"all_frames": true,
|
||||
"match_about_blank": true,
|
||||
"js": ["content/apply.js"]
|
||||
"js": ["content/api.js", "content/apply.js"]
|
||||
},
|
||||
{
|
||||
"matches": ["http://userstyles.org/*", "https://userstyles.org/*"],
|
||||
|
|
Loading…
Reference in New Issue
Block a user