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
BG: false
notifyAllTabs: false
sendMessage: false
queryTabs: false
getTab: false
getOwnTab: false

View File

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

View File

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

View File

@ -1,4 +1,3 @@
/* global runtimeSend */
'use strict';
function createSourceLoader() {
@ -95,16 +94,16 @@ function initUsercssInstall() {
if (history.length > 1) {
history.back();
} else {
runtimeSend({method: 'closeTab'});
chrome.runtime.sendMessage({method: 'closeTab'});
}
break;
}
});
});
return runtimeSend({
chrome.runtime.sendMessage({
method: 'openUsercssInstallPage',
updateUrl: location.href
}).catch(alert);
updateUrl: location.href,
}, r => r && r.__ERROR__ && alert(r.__ERROR__));
}
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>
</div>
<script src="/content/util.js"></script>
<script src="/install-usercss/install-usercss.js"></script>
</body>
</html>

View File

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

View File

@ -87,7 +87,6 @@ function notifyAllTabs(msg) {
style: getStyleWithNoCode(msg.style)
});
}
const maybeIgnoreLastError = FIREFOX ? ignoreChromeError : undefined;
const affectsAll = !msg.affects || msg.affects.all;
const affectsOwnOriginOnly = !affectsAll && (msg.affects.editor || msg.affects.manager);
const affectsTabs = affectsAll || affectsOwnOriginOnly;
@ -101,7 +100,8 @@ function notifyAllTabs(msg) {
&& !(affectsSelf && tab.url.startsWith(URLS.ownOrigin))
// skip lazy-loaded aka unloaded tabs that seem to start loading on message in FF
&& (!FIREFOX || tab.width)) {
chrome.tabs.sendMessage(tab.id, msg, maybeIgnoreLastError);
msg.tabId = tab.id;
sendMessage(msg, ignoreChromeError);
}
if (affectsIcon && BG) {
BG.updateIcon(tab);
@ -128,7 +128,34 @@ function notifyAllTabs(msg) {
}
// notify background page and all open popups
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() {
return BG && BG.getStyles ? Promise.resolve() : new Promise(function ping(resolve) {
chrome.runtime.sendMessage({method: 'healthCheck'}, health => {
sendMessage({method: 'healthCheck'}, health => {
if (health !== undefined) {
BG = chrome.extension.getBackgroundPage();
resolve();

View File

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

View File

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

View File

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

View File

@ -119,7 +119,7 @@ function initPopup(url) {
}
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) {
return;
}