WIP: broadcastMessage
This commit is contained in:
parent
c01f93f62c
commit
f1639cc33e
|
@ -13,6 +13,7 @@ window.API_METHODS = Object.assign(window.API_METHODS || {}, {
|
|||
// getStyles,
|
||||
getSectionsByUrl: styleManager.getSectionsByUrl,
|
||||
getSectionsById: styleManager.getSectionsById,
|
||||
getStylesInfo: styleManager.getStylesInfo,
|
||||
// saveStyle,
|
||||
// deleteStyle,
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global createCache db calcStyleDigest normalizeStyleSections db */
|
||||
/* global createCache db calcStyleDigest normalizeStyleSections db promisify */
|
||||
'use strict';
|
||||
|
||||
const styleManager = (() => {
|
||||
|
@ -8,18 +8,37 @@ const styleManager = (() => {
|
|||
const compiledRe = createCache();
|
||||
const compiledExclusion = createCache();
|
||||
const BAD_MATCHER = {test: () => false};
|
||||
const tabQuery = promisify(chrome.tabs.query.bind(chrome.tabs));
|
||||
const tabSendMessage = promisify(chrome.tabs.sendMessage.bind(chrome.tabs));
|
||||
const runtimeSendMessage = promisify(chrome.runtime.sendMessage.bind(chrome.runtime));
|
||||
|
||||
// FIXME: do we have to prepare `styles` map for all methods?
|
||||
return ensurePrepared({
|
||||
getSectionsForURL,
|
||||
styles,
|
||||
cachedStyleForUrl,
|
||||
getStylesInfo,
|
||||
getSectionsByUrl,
|
||||
installStyle,
|
||||
deleteStyle,
|
||||
setStyleExclusions,
|
||||
editSave
|
||||
editSave,
|
||||
toggleStyle
|
||||
// TODO: get all styles API?
|
||||
// TODO: get style by ID?
|
||||
});
|
||||
|
||||
function toggleStyle(id, enabled) {
|
||||
const style = styles.get(id);
|
||||
style.enabled = enabled;
|
||||
return saveStyle(style)
|
||||
.then(() => broadcastMessage('styleUpdated', {id, enabled}));
|
||||
}
|
||||
|
||||
function getStylesInfo() {
|
||||
// FIXME: remove code?
|
||||
return [...styles.values()];
|
||||
}
|
||||
|
||||
function editSave() {}
|
||||
|
||||
function setStyleExclusions() {}
|
||||
|
@ -105,14 +124,14 @@ const styleManager = (() => {
|
|||
}
|
||||
}
|
||||
|
||||
function getSectionsForURL(url) {
|
||||
function getSectionsByUrl(url) {
|
||||
// if (!URLS.supported(url) || prefs.get('disableAll')) {
|
||||
// return [];
|
||||
// }
|
||||
let result = cachedStyleForUrl.get(url);
|
||||
if (!result) {
|
||||
result = [];
|
||||
for (const style of styles) {
|
||||
for (const style of styles.values()) {
|
||||
if (!urlMatchStyle(url, style)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -213,4 +232,81 @@ const styleManager = (() => {
|
|||
function getUrlNoHash(url) {
|
||||
return url.split('#')[0];
|
||||
}
|
||||
|
||||
function cleanData(method, data) {
|
||||
if (
|
||||
(method === 'styleUpdated' || method === 'styleAdded') &&
|
||||
(data.sections || data.sourceCode)
|
||||
) {
|
||||
// apply/popup/manage use only meta for these two methods,
|
||||
// editor may need the full code but can fetch it directly,
|
||||
// so we send just the meta to avoid spamming lots of tabs with huge styles
|
||||
return getStyleWithNoCode(data);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
function isExtensionStyle(id) {
|
||||
// TODO
|
||||
// const style = styles.get(id);
|
||||
// if (!style)
|
||||
return false;
|
||||
}
|
||||
|
||||
function broadcastMessage(method, data) {
|
||||
const pendingPrivilage = runtimeSendMessage({method, cleanData(method, data)});
|
||||
// const affectsAll = !msg.affects || msg.affects.all;
|
||||
// const affectsOwnOriginOnly =
|
||||
// !affectsAll && (msg.affects.editor || msg.affects.manager);
|
||||
// const affectsTabs = affectsAll || affectsOwnOriginOnly;
|
||||
// const affectsIcon = affectsAll || msg.affects.icon;
|
||||
// const affectsPopup = affectsAll || msg.affects.popup;
|
||||
// const affectsSelf = affectsPopup || msg.prefs;
|
||||
// notify all open extension pages and popups
|
||||
// if (affectsSelf) {
|
||||
// msg.tabId = undefined;
|
||||
// sendMessage(msg, ignoreChromeError);
|
||||
// }
|
||||
// notify tabs
|
||||
if (affectsTabs || affectsIcon) {
|
||||
const notifyTab = tab => {
|
||||
if (!styleUpdated
|
||||
&& (affectsTabs || URLS.optionsUI.includes(tab.url))
|
||||
// own pages are already notified via sendMessage
|
||||
&& !(affectsSelf && tab.url.startsWith(URLS.ownOrigin))
|
||||
// skip lazy-loaded aka unloaded tabs that seem to start loading on message in FF
|
||||
&& (!FIREFOX || tab.width)) {
|
||||
msg.tabId = tab.id;
|
||||
sendMessage(msg, ignoreChromeError);
|
||||
}
|
||||
if (affectsIcon) {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
// debounce(API.updateIcon, 0, {tab});
|
||||
}
|
||||
};
|
||||
// list all tabs including chrome-extension:// which can be ours
|
||||
Promise.all([
|
||||
queryTabs(isExtensionStyle(data.id) ? {url: URLS.ownOrigin + '*'} : {}),
|
||||
getActiveTab(),
|
||||
]).then(([tabs, activeTab]) => {
|
||||
const activeTabId = activeTab && activeTab.id;
|
||||
for (const tab of tabs) {
|
||||
invokeOrPostpone(tab.id === activeTabId, notifyTab, tab);
|
||||
}
|
||||
});
|
||||
}
|
||||
// notify self: the message no longer is sent to the origin in new Chrome
|
||||
if (typeof onRuntimeMessage !== 'undefined') {
|
||||
onRuntimeMessage(originalMessage);
|
||||
}
|
||||
// notify apply.js on own pages
|
||||
if (typeof applyOnMessage !== 'undefined') {
|
||||
applyOnMessage(originalMessage);
|
||||
}
|
||||
// propagate saved style state/code efficiently
|
||||
if (styleUpdated) {
|
||||
msg.refreshOwnTabs = false;
|
||||
API.refreshAllTabs(msg);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* global promisify */
|
||||
'use strict';
|
||||
|
||||
const API = (() => {
|
||||
|
@ -12,29 +13,13 @@ const API = (() => {
|
|||
function sendMessage(msg) {
|
||||
return runtimeSendMessage(msg)
|
||||
.then(result => {
|
||||
if (result.__ERROR__) {
|
||||
if (result && 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) {
|
||||
|
@ -48,7 +33,11 @@ const API = (() => {
|
|||
if (BG !== window) {
|
||||
args = BG.deepCopy(args);
|
||||
}
|
||||
return BG.API_METHODS[name](...args)
|
||||
const fn = BG.API_METHODS[name];
|
||||
if (!fn) {
|
||||
throw new Error(`unknown API method: ${name}`);
|
||||
}
|
||||
return Promise.resolve(fn(...args))
|
||||
.then(BG.deepCopy);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
break;
|
||||
|
||||
case 'styleUpdated':
|
||||
if (request.codeIsUpdated === false) {
|
||||
if (!request.codeIsUpdated) {
|
||||
applyStyleState(request.style);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -104,71 +104,6 @@ if (FIREFOX_NO_DOM_STORAGE) {
|
|||
Object.defineProperty(window, 'sessionStorage', {value: {}});
|
||||
}
|
||||
|
||||
function notifyAllTabs(msg) {
|
||||
const originalMessage = msg;
|
||||
const styleUpdated = msg.method === 'styleUpdated' || msg.method === 'exclusionsUpdated';
|
||||
if (styleUpdated || msg.method === 'styleAdded') {
|
||||
// apply/popup/manage use only meta for these two methods,
|
||||
// editor may need the full code but can fetch it directly,
|
||||
// so we send just the meta to avoid spamming lots of tabs with huge styles
|
||||
msg = Object.assign({}, msg, {
|
||||
style: getStyleWithNoCode(msg.style)
|
||||
});
|
||||
}
|
||||
const affectsAll = !msg.affects || msg.affects.all;
|
||||
const affectsOwnOriginOnly = !affectsAll && (msg.affects.editor || msg.affects.manager);
|
||||
const affectsTabs = affectsAll || affectsOwnOriginOnly;
|
||||
const affectsIcon = affectsAll || msg.affects.icon;
|
||||
const affectsPopup = affectsAll || msg.affects.popup;
|
||||
const affectsSelf = affectsPopup || msg.prefs;
|
||||
// notify all open extension pages and popups
|
||||
if (affectsSelf) {
|
||||
msg.tabId = undefined;
|
||||
sendMessage(msg, ignoreChromeError);
|
||||
}
|
||||
// notify tabs
|
||||
if (affectsTabs || affectsIcon) {
|
||||
const notifyTab = tab => {
|
||||
if (!styleUpdated
|
||||
&& (affectsTabs || URLS.optionsUI.includes(tab.url))
|
||||
// own pages are already notified via sendMessage
|
||||
&& !(affectsSelf && tab.url.startsWith(URLS.ownOrigin))
|
||||
// skip lazy-loaded aka unloaded tabs that seem to start loading on message in FF
|
||||
&& (!FIREFOX || tab.width)) {
|
||||
msg.tabId = tab.id;
|
||||
sendMessage(msg, ignoreChromeError);
|
||||
}
|
||||
if (affectsIcon) {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
debounce(API.updateIcon, 0, {tab});
|
||||
}
|
||||
};
|
||||
// list all tabs including chrome-extension:// which can be ours
|
||||
Promise.all([
|
||||
queryTabs(affectsOwnOriginOnly ? {url: URLS.ownOrigin + '*'} : {}),
|
||||
getActiveTab(),
|
||||
]).then(([tabs, activeTab]) => {
|
||||
const activeTabId = activeTab && activeTab.id;
|
||||
for (const tab of tabs) {
|
||||
invokeOrPostpone(tab.id === activeTabId, notifyTab, tab);
|
||||
}
|
||||
});
|
||||
}
|
||||
// notify self: the message no longer is sent to the origin in new Chrome
|
||||
if (typeof onRuntimeMessage !== 'undefined') {
|
||||
onRuntimeMessage(originalMessage);
|
||||
}
|
||||
// notify apply.js on own pages
|
||||
if (typeof applyOnMessage !== 'undefined') {
|
||||
applyOnMessage(originalMessage);
|
||||
}
|
||||
// propagate saved style state/code efficiently
|
||||
if (styleUpdated) {
|
||||
msg.refreshOwnTabs = false;
|
||||
API.refreshAllTabs(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function sendMessage(msg, callback) {
|
||||
/*
|
||||
Promise mode [default]:
|
||||
|
|
17
js/promisify.js
Normal file
17
js/promisify.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
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[0] : result
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -153,9 +153,11 @@
|
|||
</p>
|
||||
</template>
|
||||
|
||||
<script src="js/promisify.js"></script>
|
||||
<script src="js/dom.js"></script>
|
||||
<script src="js/messaging.js"></script>
|
||||
<script src="js/prefs.js"></script>
|
||||
<script src="content/api.js"></script>
|
||||
<script src="content/apply.js"></script>
|
||||
<script src="js/localization.js"></script>
|
||||
<script src="manage/filters.js"></script>
|
||||
|
|
|
@ -32,7 +32,7 @@ const OWN_ICON = chrome.runtime.getManifest().icons['16'];
|
|||
const handleEvent = {};
|
||||
|
||||
Promise.all([
|
||||
API.getStyles({omitCode: !BG}),
|
||||
API.getStylesInfo(),
|
||||
urlFilterParam && API.searchDB({query: 'url:' + urlFilterParam}),
|
||||
onDOMready().then(initGlobalEvents),
|
||||
]).then(args => {
|
||||
|
@ -195,7 +195,7 @@ function createStyleElement({style, name}) {
|
|||
};
|
||||
}
|
||||
const parts = createStyleElement.parts;
|
||||
const configurable = style.usercssData && Object.keys(style.usercssData.vars).length > 0;
|
||||
const configurable = style.usercssData && style.usercssData.vars && Object.keys(style.usercssData.vars).length > 0;
|
||||
parts.checker.checked = style.enabled;
|
||||
parts.nameLink.textContent = tWordBreak(style.name);
|
||||
parts.nameLink.href = parts.editLink.href = parts.editHrefBase + style.id;
|
||||
|
@ -403,10 +403,7 @@ Object.assign(handleEvent, {
|
|||
},
|
||||
|
||||
toggle(event, entry) {
|
||||
API.saveStyle({
|
||||
id: entry.styleId,
|
||||
enabled: this.matches('.enable') || this.checked,
|
||||
});
|
||||
API.toggleStyle(entry.styleId, this.matches('.enable') || this.checked);
|
||||
},
|
||||
|
||||
check(event, entry) {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
],
|
||||
"background": {
|
||||
"scripts": [
|
||||
"js/promisify.js",
|
||||
"js/messaging.js",
|
||||
"js/storage-util.js",
|
||||
"js/sections-equal.js",
|
||||
|
@ -60,7 +61,7 @@
|
|||
"run_at": "document_start",
|
||||
"all_frames": true,
|
||||
"match_about_blank": true,
|
||||
"js": ["content/api.js", "content/apply.js"]
|
||||
"js": ["js/promisify.js", "content/api.js", "content/apply.js"]
|
||||
},
|
||||
{
|
||||
"matches": ["http://userstyles.org/*", "https://userstyles.org/*"],
|
||||
|
|
Loading…
Reference in New Issue
Block a user