sendMessage()

Promise mode [default]:
  - rejects on receiving {__ERROR__: message} created by
    background.js::onRuntimeMessage
  - suppresses chrome.runtime.lastError
    by browserAction.setText which lacks a callback param in chrome API

Callback mode:
  - enabled by passing a second param
  - doesn't suppress chrome.runtime.lastError
This commit is contained in:
tophf 2017-11-24 18:26:20 +03:00
parent 226fc471eb
commit 978e5ca9f0
13 changed files with 94 additions and 95 deletions

View File

@ -17,6 +17,7 @@ globals:
URLS: false URLS: false
BG: false BG: false
notifyAllTabs: false notifyAllTabs: false
sendMessage: false
queryTabs: false queryTabs: false
getTab: false getTab: false
getOwnTab: false getOwnTab: false

View File

@ -110,7 +110,7 @@ contextMenus = Object.assign({
contexts: ['editable'], contexts: ['editable'],
documentUrlPatterns: [URLS.ownOrigin + 'edit*'], documentUrlPatterns: [URLS.ownOrigin + 'edit*'],
click: (info, tab) => { click: (info, tab) => {
chrome.tabs.sendMessage(tab.id, {method: 'editDeleteText'}); sendMessage(tab.id, {method: 'editDeleteText'});
}, },
} }
}); });
@ -179,15 +179,12 @@ window.addEventListener('storageReady', function _() {
}; };
const pingCS = (cs, {id, url}) => { const pingCS = (cs, {id, url}) => {
const maybeInject = pong => !pong && injectCS(cs, PING.tabId);
cs.matches.some(match => { cs.matches.some(match => {
if ((match === ALL_URLS || url.match(match)) if ((match === ALL_URLS || url.match(match)) &&
&& (!url.startsWith('chrome') || url === NTP)) { (!url.startsWith('chrome') || url === NTP)) {
chrome.tabs.sendMessage(id, PING, pong => { PING.tabId = id;
if (!pong) { sendMessage(PING).then(maybeInject);
injectCS(cs, id);
}
ignoreChromeError();
});
return true; return true;
} }
}); });
@ -211,13 +208,13 @@ function webNavigationListener(method, {url, tabId, frameId}) {
if (method === 'styleApply') { if (method === 'styleApply') {
handleCssTransitionBug({tabId, frameId, url, styles}); handleCssTransitionBug({tabId, frameId, url, styles});
} }
chrome.tabs.sendMessage(tabId, { sendMessage({
tabId,
frameId,
method, method,
// ping own page so it retrieves the styles directly // ping own page so it retrieves the styles directly
styles: url.startsWith(URLS.ownOrigin) ? 'DIY' : styles, styles: url.startsWith(URLS.ownOrigin) ? 'DIY' : styles,
}, { });
frameId
}, ignoreChromeError);
} }
// main page frame id is 0 // main page frame id is 0
if (frameId === 0) { if (frameId === 0) {
@ -303,9 +300,15 @@ function updateIcon(tab, styles) {
} }
function onRuntimeMessage(request, sender, sendResponse) { function onRuntimeMessage(request, sender, sendResponseInternal) {
const sendResponse = data => {
// wrap Error object instance as {__ERROR__: message} - will be unwrapped in sendMessage
if (data instanceof Error) {
data = {__ERROR__: data.message};
}
// prevent browser exception bug on sending a response to a closed tab // prevent browser exception bug on sending a response to a closed tab
sendResponse = (send => data => tryCatch(send, data))(sendResponse); tryCatch(sendResponseInternal, data);
};
switch (request.method) { switch (request.method) {
case 'getStyles': case 'getStyles':
getStyles(request).then(sendResponse); getStyles(request).then(sendResponse);
@ -353,6 +356,7 @@ function onRuntimeMessage(request, sender, sendResponse) {
} }
} }
function closeTab(tabId, request) { function closeTab(tabId, request) {
return new Promise(resolve => { return new Promise(resolve => {
if (request.tabId) { if (request.tabId) {

View File

@ -23,11 +23,7 @@ var usercssHelper = (() => {
function wrapReject(pending) { function wrapReject(pending) {
return pending return pending
.then(result => ({success: true, result})) .catch(err => new Error(Array.isArray(err) ? err.join('\n') : err.message || String(err)));
.catch(err => ({
success: false,
result: Array.isArray(err) ? err.join('\n') : err.message || String(err),
}));
} }
// Parse the source and find the duplication // Parse the source and find the duplication

View File

@ -1,4 +1,3 @@
/* global runtimeSend */
'use strict'; 'use strict';
function createSourceLoader() { function createSourceLoader() {
@ -95,16 +94,16 @@ function initUsercssInstall() {
if (history.length > 1) { if (history.length > 1) {
history.back(); history.back();
} else { } else {
runtimeSend({method: 'closeTab'}); chrome.runtime.sendMessage({method: 'closeTab'});
} }
break; break;
} }
}); });
}); });
return runtimeSend({ chrome.runtime.sendMessage({
method: 'openUsercssInstallPage', method: 'openUsercssInstallPage',
updateUrl: location.href updateUrl: location.href,
}).catch(alert); }, r => r && r.__ERROR__ && alert(r.__ERROR__));
} }
function isUsercss() { function isUsercss() {

View File

@ -1,10 +0,0 @@
'use strict';
function runtimeSend(request) {
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage(
request,
({success, result}) => (success ? resolve : reject)(result)
);
});
}

View File

@ -85,7 +85,6 @@
<div class="warnings"></div> <div class="warnings"></div>
</div> </div>
</div> </div>
<script src="/content/util.js"></script>
<script src="/install-usercss/install-usercss.js"></script> <script src="/install-usercss/install-usercss.js"></script>
</body> </body>
</html> </html>

View File

@ -1,4 +1,4 @@
/* global CodeMirror semverCompare makeLink closeCurrentTab runtimeSend */ /* global CodeMirror semverCompare makeLink closeCurrentTab */
/* global messageBox */ /* global messageBox */
'use strict'; 'use strict';
@ -44,7 +44,7 @@
cm.setCursor(cursor); cm.setCursor(cursor);
cm.scrollTo(scrollInfo.left, scrollInfo.top); cm.scrollTo(scrollInfo.left, scrollInfo.top);
return runtimeSend({ return sendMessage({
id: installed.id, id: installed.id,
method: 'saveUsercss', method: 'saveUsercss',
reason: 'update', reason: 'update',
@ -168,50 +168,36 @@
} }
function install(style) { function install(style) {
const request = Object.assign(style, { installed = style;
method: 'saveUsercss',
reason: 'update'
});
return runtimeSend(request)
.then(result => {
installed = result;
$$('.warning') $$('.warning')
.forEach(el => el.remove()); .forEach(el => el.remove());
$('.install').disabled = true; $('.install').disabled = true;
$('.install').classList.add('installed'); $('.install').classList.add('installed');
$('.set-update-url input[type=checkbox]').disabled = true; $('.set-update-url input[type=checkbox]').disabled = true;
$('.set-update-url').title = result.updateUrl ? $('.set-update-url').title = style.updateUrl ?
t('installUpdateFrom', result.updateUrl) : ''; t('installUpdateFrom', style.updateUrl) : '';
updateMeta(result); updateMeta(style);
chrome.runtime.sendMessage({method: 'openEditor', id: result.id}); sendMessage({method: 'openEditor', id: style.id});
if (!liveReload) { if (!liveReload) {
port.postMessage({method: 'closeTab'}); port.postMessage({method: 'closeTab'});
} }
window.dispatchEvent(new CustomEvent('installed')); window.dispatchEvent(new CustomEvent('installed'));
})
.catch(err => {
messageBox.alert(chrome.i18n.getMessage('styleInstallFailed', String(err)));
});
} }
function initSourceCode(sourceCode) { function initSourceCode(sourceCode) {
cm.setValue(sourceCode); cm.setValue(sourceCode);
cm.refresh(); cm.refresh();
runtimeSend({ sendMessage({method: 'buildUsercss', sourceCode, checkDup: true})
method: 'buildUsercss', .then(init)
sourceCode, .catch(err => {
checkDup: true
}).then(init, onInitError);
}
function onInitError(err) {
$('.header').classList.add('meta-init-error'); $('.header').classList.add('meta-init-error');
showError(err); showError(err);
});
} }
function buildWarning(err) { function buildWarning(err) {
@ -236,17 +222,14 @@
); );
} }
$('button.install').onclick = () => { $('button.install').onclick = () => {
const message = dup ? messageBox.confirm(dup ?
chrome.i18n.getMessage('styleInstallOverwrite', [ t('styleInstallOverwrite', [data.name, dupData.version, data.version]) :
data.name, dupData.version, data.version t('styleInstall', [data.name])
]) : ).then(ok => ok &&
chrome.i18n.getMessage('styleInstall', [data.name]); sendMessage(Object.assign(style, {method: 'saveUsercss', reason: 'update'}))
.then(install)
messageBox.confirm(message).then(result => { .catch(err => messageBox.alert(t('styleInstallFailed', err)))
if (result) { );
return install(style);
}
});
}; };
// set updateUrl // set updateUrl

View File

@ -87,7 +87,6 @@ function notifyAllTabs(msg) {
style: getStyleWithNoCode(msg.style) style: getStyleWithNoCode(msg.style)
}); });
} }
const maybeIgnoreLastError = FIREFOX ? ignoreChromeError : undefined;
const affectsAll = !msg.affects || msg.affects.all; const affectsAll = !msg.affects || msg.affects.all;
const affectsOwnOriginOnly = !affectsAll && (msg.affects.editor || msg.affects.manager); const affectsOwnOriginOnly = !affectsAll && (msg.affects.editor || msg.affects.manager);
const affectsTabs = affectsAll || affectsOwnOriginOnly; const affectsTabs = affectsAll || affectsOwnOriginOnly;
@ -101,7 +100,8 @@ function notifyAllTabs(msg) {
&& !(affectsSelf && tab.url.startsWith(URLS.ownOrigin)) && !(affectsSelf && tab.url.startsWith(URLS.ownOrigin))
// skip lazy-loaded aka unloaded tabs that seem to start loading on message in FF // skip lazy-loaded aka unloaded tabs that seem to start loading on message in FF
&& (!FIREFOX || tab.width)) { && (!FIREFOX || tab.width)) {
chrome.tabs.sendMessage(tab.id, msg, maybeIgnoreLastError); msg.tabId = tab.id;
sendMessage(msg, ignoreChromeError);
} }
if (affectsIcon && BG) { if (affectsIcon && BG) {
BG.updateIcon(tab); BG.updateIcon(tab);
@ -128,7 +128,34 @@ function notifyAllTabs(msg) {
} }
// notify background page and all open popups // notify background page and all open popups
if (affectsSelf) { if (affectsSelf) {
chrome.runtime.sendMessage(msg, maybeIgnoreLastError); msg.tabId = null;
sendMessage(msg, ignoreChromeError);
}
}
function sendMessage(msg, callback) {
/*
Promise mode [default]:
- rejects on receiving {__ERROR__: message} created by background.js::onRuntimeMessage
- automatically suppresses chrome.runtime.lastError because it's autogenerated
by browserAction.setText which lacks a callback param in chrome API
Standard callback mode:
- enabled by passing a second param
*/
const {tabId, frameId} = msg;
const fn = tabId ? chrome.tabs.sendMessage : chrome.runtime.sendMessage;
const args = tabId ? [tabId, msg, {frameId}] : [msg];
if (callback) {
fn(...args, callback);
} else {
return new Promise((resolve, reject) => {
fn(...args, r => {
const err = r && r.__ERROR__;
(err ? reject : resolve)(err || r);
chrome.runtime.lastError; // eslint-disable-line no-unused-expressions
});
});
} }
} }
@ -338,7 +365,7 @@ function sessionStorageHash(name) {
function onBackgroundReady() { function onBackgroundReady() {
return BG && BG.getStyles ? Promise.resolve() : new Promise(function ping(resolve) { return BG && BG.getStyles ? Promise.resolve() : new Promise(function ping(resolve) {
chrome.runtime.sendMessage({method: 'healthCheck'}, health => { sendMessage({method: 'healthCheck'}, health => {
if (health !== undefined) { if (health !== undefined) {
BG = chrome.extension.getBackgroundPage(); BG = chrome.extension.getBackgroundPage();
resolve(); resolve();

View File

@ -288,8 +288,8 @@ function importFromString(jsonString) {
if (tab.id === ownTab.id) { if (tab.id === ownTab.id) {
applyOnMessage(message); applyOnMessage(message);
} else { } else {
invokeOrPostpone(tab.id === activeTab.id, message.tabId = tab.id;
chrome.tabs.sendMessage, tab.id, message, ignoreChromeError); invokeOrPostpone(tab.id === activeTab.id, sendMessage, message, ignoreChromeError);
} }
setTimeout(BG.updateIcon, 0, tab, styles); setTimeout(BG.updateIcon, 0, tab, styles);
if (tab === lastTab) { if (tab === lastTab) {

View File

@ -581,10 +581,10 @@ function dieOnNullBackground() {
if (!FIREFOX || BG) { if (!FIREFOX || BG) {
return; return;
} }
chrome.runtime.sendMessage({method: 'healthCheck'}, health => { sendMessage({method: 'healthCheck'}, health => {
if (health && !chrome.extension.getBackgroundPage()) { if (health && !chrome.extension.getBackgroundPage()) {
onDOMready().then(() => { onDOMready().then(() => {
chrome.runtime.sendMessage({method: 'getStyles'}, showStyles); sendMessage({method: 'getStyles'}, showStyles);
messageBox({ messageBox({
title: 'Stylus', title: 'Stylus',
className: 'danger center', className: 'danger center',

View File

@ -54,14 +54,14 @@
"matches": ["http://userstyles.org/*", "https://userstyles.org/*"], "matches": ["http://userstyles.org/*", "https://userstyles.org/*"],
"run_at": "document_start", "run_at": "document_start",
"all_frames": false, "all_frames": false,
"js": ["content/install.js"] "js": ["content/install-hook-userstyles.js"]
}, },
{ {
"matches": ["<all_urls>"], "matches": ["<all_urls>"],
"include_globs": ["*.user.css", "*.user.styl"], "include_globs": ["*.user.css", "*.user.styl"],
"run_at": "document_idle", "run_at": "document_idle",
"all_frames": false, "all_frames": false,
"js": ["content/util.js", "content/install-user-css.js"] "js": ["content/install-hook-usercss.js"]
} }
], ],
"browser_action": { "browser_action": {

View File

@ -119,7 +119,7 @@ function initPopup(url) {
} }
getActiveTab().then(function ping(tab, retryCountdown = 10) { getActiveTab().then(function ping(tab, retryCountdown = 10) {
chrome.tabs.sendMessage(tab.id, {method: 'ping'}, {frameId: 0}, pong => { sendMessage({tabId: tab.id, method: 'ping', frameId: 0}, pong => {
if (pong) { if (pong) {
return; return;
} }