fixes/cosmetics
* usercss installer url check * extract downloaders * simplify tabManager * rework/split openInstallerPage * use a simple object instead of map * trivial bugfixes * cosmetics
This commit is contained in:
parent
73f6e8a964
commit
b01f03babf
|
@ -626,12 +626,12 @@
|
||||||
"description": "The label of live-reload error"
|
"description": "The label of live-reload error"
|
||||||
},
|
},
|
||||||
"liveReloadInstallHint": {
|
"liveReloadInstallHint": {
|
||||||
"message": "Keep this tab open to auto-update the installed style on external changes.",
|
"message": "Keep this tab open to auto-update the style on external changes.",
|
||||||
"description": "The label of live-reload feature"
|
"description": "The label of live-reload feature"
|
||||||
},
|
},
|
||||||
"liveReloadInstallHintFF": {
|
"liveReloadInstallHintFF": {
|
||||||
"message": "Keep the original tab open too as it's needed for local file:// URLs in Firefox 68 and newer.",
|
"message": "Keep both this tab and the original tab open to auto-update the style on external changes.",
|
||||||
"description": "The extra hint of live-reload feature shown only for file:// URLs in Firefox 68+"
|
"description": "The extra hint of live-reload feature shown only for file:// URLs in Firefox"
|
||||||
},
|
},
|
||||||
"liveReloadLabel": {
|
"liveReloadLabel": {
|
||||||
"message": "Live reload",
|
"message": "Live reload",
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
URLS ignoreChromeError usercssHelper
|
URLS ignoreChromeError usercssHelper
|
||||||
styleManager msg navigatorUtil workerUtil contentScripts sync
|
styleManager msg navigatorUtil workerUtil contentScripts sync
|
||||||
findExistingTab createTab activateTab isTabReplaceable getActiveTab
|
findExistingTab createTab activateTab isTabReplaceable getActiveTab
|
||||||
iconManager */
|
iconManager tabManager */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
@ -89,6 +89,14 @@ navigatorUtil.onUrlChange(({tabId, frameId}, type) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
tabManager.onUpdate(({tabId, url, oldUrl = ''}) => {
|
||||||
|
if (usercssHelper.testUrl(url) && !oldUrl.startsWith(URLS.installUsercss)) {
|
||||||
|
usercssHelper.testContents(tabId, url).then(data => {
|
||||||
|
if (data.code) usercssHelper.openInstallerPage(tabId, url, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (FIREFOX) {
|
if (FIREFOX) {
|
||||||
// FF misses some about:blank iframes so we inject our content script explicitly
|
// FF misses some about:blank iframes so we inject our content script explicitly
|
||||||
navigatorUtil.onDOMContentLoaded(webNavIframeHelperFF, {
|
navigatorUtil.onDOMContentLoaded(webNavIframeHelperFF, {
|
||||||
|
@ -108,13 +116,6 @@ if (chrome.commands) {
|
||||||
chrome.commands.onCommand.addListener(command => browserCommands[command]());
|
chrome.commands.onCommand.addListener(command => browserCommands[command]());
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect usercss and open the installer page
|
|
||||||
navigatorUtil.onCommitted(({tabId, frameId, url}) => {
|
|
||||||
if (!frameId && usercssHelper.testUrl(url)) {
|
|
||||||
usercssHelper.openInstallerPage(tabId, url);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// *************************************************************************
|
// *************************************************************************
|
||||||
chrome.runtime.onInstalled.addListener(({reason}) => {
|
chrome.runtime.onInstalled.addListener(({reason}) => {
|
||||||
// save install type: "admin", "development", "normal", "sideload" or "other"
|
// save install type: "admin", "development", "normal", "sideload" or "other"
|
||||||
|
|
|
@ -30,13 +30,13 @@ const iconManager = (() => {
|
||||||
|
|
||||||
// FIXME: in some cases, we only have to redraw the badge. is it worth a optimization?
|
// FIXME: in some cases, we only have to redraw the badge. is it worth a optimization?
|
||||||
function updateIconBadge(tabId, count, force = true) {
|
function updateIconBadge(tabId, count, force = true) {
|
||||||
tabManager.setMeta(tabId, 'count', count);
|
tabManager.set(tabId, 'count', count);
|
||||||
refreshIconBadgeText(tabId);
|
refreshIconBadgeText(tabId);
|
||||||
refreshIcon(tabId, force);
|
refreshIcon(tabId, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshIconBadgeText(tabId) {
|
function refreshIconBadgeText(tabId) {
|
||||||
const count = tabManager.getMeta(tabId, 'count');
|
const count = tabManager.get(tabId, 'count');
|
||||||
iconUtil.setBadgeText({
|
iconUtil.setBadgeText({
|
||||||
text: prefs.get('show-badge') && count ? String(count) : '',
|
text: prefs.get('show-badge') && count ? String(count) : '',
|
||||||
tabId
|
tabId
|
||||||
|
@ -50,13 +50,13 @@ const iconManager = (() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshIcon(tabId, force = false) {
|
function refreshIcon(tabId, force = false) {
|
||||||
const oldIcon = tabManager.getMeta(tabId, 'icon');
|
const oldIcon = tabManager.get(tabId, 'icon');
|
||||||
const newIcon = getIconName(tabManager.getMeta(tabId, 'count'));
|
const newIcon = getIconName(tabManager.get(tabId, 'count'));
|
||||||
|
|
||||||
if (!force && oldIcon === newIcon) {
|
if (!force && oldIcon === newIcon) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tabManager.setMeta(tabId, 'icon', newIcon);
|
tabManager.set(tabId, 'icon', newIcon);
|
||||||
iconUtil.setIcon({
|
iconUtil.setIcon({
|
||||||
path: getIconPath(newIcon),
|
path: getIconPath(newIcon),
|
||||||
tabId
|
tabId
|
||||||
|
|
|
@ -9,40 +9,35 @@ const tabManager = (() => {
|
||||||
chrome.tabs.onReplaced.addListener((added, removed) => cache.delete(removed));
|
chrome.tabs.onReplaced.addListener((added, removed) => cache.delete(removed));
|
||||||
navigatorUtil.onUrlChange(({tabId, frameId, url}) => {
|
navigatorUtil.onUrlChange(({tabId, frameId, url}) => {
|
||||||
if (frameId) return;
|
if (frameId) return;
|
||||||
setMeta(tabId, 'url', url);
|
const oldUrl = tabManager.get(tabId, 'url');
|
||||||
emitUpdate({tabId, url});
|
tabManager.set(tabId, 'url', url);
|
||||||
});
|
for (const fn of listeners) {
|
||||||
|
|
||||||
return {onUpdate, setMeta, getMeta, list};
|
|
||||||
|
|
||||||
function list() {
|
|
||||||
return cache.keys();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onUpdate(callback) {
|
|
||||||
listeners.push(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function emitUpdate(e) {
|
|
||||||
for (const callback of listeners) {
|
|
||||||
try {
|
try {
|
||||||
callback(e);
|
fn({tabId, url, oldUrl});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
function setMeta(tabId, key, value) {
|
return {
|
||||||
let meta = cache.get(tabId);
|
onUpdate(fn) {
|
||||||
if (!meta) {
|
listeners.push(fn);
|
||||||
meta = new Map();
|
},
|
||||||
cache.set(tabId, meta);
|
get(tabId, key) {
|
||||||
}
|
const meta = cache.get(tabId);
|
||||||
meta.set(key, value);
|
return meta && meta[key];
|
||||||
}
|
},
|
||||||
|
set(tabId, key, value) {
|
||||||
function getMeta(tabId, key) {
|
let meta = cache.get(tabId);
|
||||||
return cache.get(tabId).get(key);
|
if (!meta) {
|
||||||
}
|
meta = {};
|
||||||
|
cache.set(tabId, meta);
|
||||||
|
}
|
||||||
|
meta[key] = value;
|
||||||
|
},
|
||||||
|
list() {
|
||||||
|
return cache.keys();
|
||||||
|
},
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
/* global API_METHODS usercss styleManager deepCopy openURL download URLS getTab promisify */
|
/* global API_METHODS usercss styleManager deepCopy openURL download URLS getTab */
|
||||||
/* exports usercssHelper */
|
/* exports usercssHelper */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
const usercssHelper = (() => {
|
const usercssHelper = (() => {
|
||||||
// detecting FF68 by the added feature as navigator.ua may be spoofed via about:config or devtools
|
const installCodeCache = {};
|
||||||
const tabExec = !chrome.app && chrome.storage.managed && promisify(chrome.tabs.executeScript.bind(chrome.tabs));
|
const clearInstallCode = url => delete installCodeCache[url];
|
||||||
const downloadSelf = tabExec && {file: '/content/download-self.js'};
|
const isResponseText = r => /^text\/(css|plain)(;.*?)?$/i.test(r.headers.get('content-type'));
|
||||||
const installCodeCache = new Map();
|
// in Firefox we have to use a content script to read file://
|
||||||
const clearInstallCode = url => installCodeCache.delete(url);
|
const fileLoader = !chrome.app && // not relying on navigator.ua which can be spoofed
|
||||||
const isPlainCssResponse = r => /^text\/(css|plain)(;.*?)?$/i.test(r.headers.get('content-type'));
|
(tabId => browser.tabs.executeScript(tabId, {file: '/content/install-hook-usercss.js'}).then(r => r[0]));
|
||||||
|
|
||||||
API_METHODS.installUsercss = installUsercss;
|
API_METHODS.installUsercss = installUsercss;
|
||||||
API_METHODS.editSaveUsercss = editSaveUsercss;
|
API_METHODS.editSaveUsercss = editSaveUsercss;
|
||||||
|
@ -19,10 +19,11 @@ const usercssHelper = (() => {
|
||||||
API_METHODS.findUsercss = find;
|
API_METHODS.findUsercss = find;
|
||||||
|
|
||||||
API_METHODS.getUsercssInstallCode = url => {
|
API_METHODS.getUsercssInstallCode = url => {
|
||||||
const {code, timer} = installCodeCache.get(url) || {};
|
// when the installer tab is reloaded after the cache is expired, this will throw intentionally
|
||||||
|
const {code, timer} = installCodeCache[url];
|
||||||
clearInstallCode(url);
|
clearInstallCode(url);
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
return code || '';
|
return code;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -30,35 +31,34 @@ const usercssHelper = (() => {
|
||||||
testUrl(url) {
|
testUrl(url) {
|
||||||
return url.includes('.user.') &&
|
return url.includes('.user.') &&
|
||||||
/^(https?|file|ftps?):/.test(url) &&
|
/^(https?|file|ftps?):/.test(url) &&
|
||||||
/\.user\.(css|styl)$/.test(url.split(/[#?]/, 1)[0]) &&
|
/\.user\.(css|styl)$/.test(url.split(/[#?]/, 1)[0]);
|
||||||
!url.startsWith(URLS.installUsercss);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
openInstallerPage(tabId, url) {
|
/** @return {Promise<{ code:string, inTab:boolean } | false>} */
|
||||||
|
testContents(tabId, url) {
|
||||||
const isFile = url.startsWith('file:');
|
const isFile = url.startsWith('file:');
|
||||||
const isFileFF = isFile && tabExec;
|
const inTab = isFile && Boolean(fileLoader);
|
||||||
return Promise.resolve(isFile || fetch(url, {method: 'HEAD'}).then(isPlainCssResponse))
|
return Promise.resolve(isFile || fetch(url, {method: 'HEAD'}).then(isResponseText))
|
||||||
.then(ok => ok && (isFileFF ? tabExec(tabId, downloadSelf) : download(url)))
|
.then(ok => ok && (inTab ? fileLoader(tabId) : download(url)))
|
||||||
.then(code => {
|
.then(code => /==userstyle==/i.test(code) && {code, inTab});
|
||||||
if (Array.isArray(code)) code = code[0];
|
},
|
||||||
if (!/==userstyle==/i.test(code)) return;
|
|
||||||
const newUrl = `${URLS.installUsercss}?updateUrl=${encodeURIComponent(url)}`;
|
openInstallerPage(tabId, url, {code, inTab} = {}) {
|
||||||
if (isFileFF) {
|
const newUrl = `${URLS.installUsercss}?updateUrl=${encodeURIComponent(url)}`;
|
||||||
getTab(tabId).then(tab =>
|
if (inTab) {
|
||||||
openURL({
|
getTab(tabId).then(tab =>
|
||||||
url: `${newUrl}&tabId=${tabId}`,
|
openURL({
|
||||||
active: tab.active,
|
url: `${newUrl}&tabId=${tabId}`,
|
||||||
index: tab.index + 1,
|
active: tab.active,
|
||||||
openerTabId: tabId,
|
index: tab.index + 1,
|
||||||
currentWindow: null,
|
openerTabId: tabId,
|
||||||
}));
|
currentWindow: null,
|
||||||
} else {
|
}));
|
||||||
const timer = setTimeout(clearInstallCode, 10e3, url);
|
} else {
|
||||||
installCodeCache.set(url, {code, timer});
|
const timer = setTimeout(clearInstallCode, 10e3, url);
|
||||||
chrome.tabs.update(tabId, {url: newUrl});
|
installCodeCache[url] = {code, timer};
|
||||||
return newUrl;
|
chrome.tabs.update(tabId, {url: newUrl});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// preventing reinjection by tabs.executeScript, just in case
|
|
||||||
typeof self.oldCode !== 'string' && // eslint-disable-line no-unused-expressions
|
|
||||||
chrome.runtime.onConnect.addListener(port => {
|
|
||||||
if (port.name !== 'downloadSelf') return;
|
|
||||||
const read = r => r.status === 200 ? r.text() : Promise.reject(r.status);
|
|
||||||
const wrapError = error => ({error});
|
|
||||||
const postBack = msg => {
|
|
||||||
port.postMessage(msg);
|
|
||||||
self.oldCode = msg.code;
|
|
||||||
};
|
|
||||||
port.onMessage.addListener(cmd => {
|
|
||||||
const oldCode = cmd === 'timer' ? self.oldCode : '';
|
|
||||||
fetch(location.href, {mode: 'same-origin'})
|
|
||||||
.then(read)
|
|
||||||
.then(code => ({code: code === oldCode ? '' : code}), wrapError)
|
|
||||||
.then(postBack);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// this assignment also passes the result to tabs.executeScript
|
|
||||||
self.oldCode = (document.querySelector('body > pre') || document.body).textContent;
|
|
22
content/install-hook-usercss.js
Normal file
22
content/install-hook-usercss.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// preventing reregistration if reinjected by tabs.executeScript for whatever reason, just in case
|
||||||
|
if (typeof self.oldCode !== 'string') {
|
||||||
|
self.oldCode = (document.querySelector('body > pre') || document.body).textContent;
|
||||||
|
chrome.runtime.onConnect.addListener(port => {
|
||||||
|
if (port.name !== 'downloadSelf') return;
|
||||||
|
port.onMessage.addListener(({id, timer}) => {
|
||||||
|
fetch(location.href, {mode: 'same-origin'})
|
||||||
|
.then(r => r.text())
|
||||||
|
.then(code => ({id, code: timer && code === self.oldCode ? null : code}))
|
||||||
|
.catch(error => ({id, error: error.message || `${error}`}))
|
||||||
|
.then(msg => {
|
||||||
|
port.postMessage(msg);
|
||||||
|
if (msg.code != null) self.oldCode = msg.code;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// passing the result to tabs.executeScript
|
||||||
|
self.oldCode; // eslint-disable-line no-unused-expressions
|
|
@ -58,8 +58,7 @@
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<h2 class="installed" i18n-text="installButtonInstalled"></h2>
|
<h2 class="installed" i18n-text="installButtonInstalled"></h2>
|
||||||
<button class="install" i18n-text="installButton"></button>
|
<button class="install" i18n-text="installButton"></button>
|
||||||
<p id="live-reload-install-hint" i18n-text="liveReloadInstallHint" hidden></p>
|
<p id="live-reload-install-hint" hidden></p>
|
||||||
<p id="live-reload-install-hint-ff" i18n-text="liveReloadInstallHintFF" hidden></p>
|
|
||||||
<label class="set-update-url">
|
<label class="set-update-url">
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
|
|
@ -7,19 +7,12 @@
|
||||||
const params = new URLSearchParams(location.search.replace(/^\?/, ''));
|
const params = new URLSearchParams(location.search.replace(/^\?/, ''));
|
||||||
const tabId = params.has('tabId') ? Number(params.get('tabId')) : -1;
|
const tabId = params.has('tabId') ? Number(params.get('tabId')) : -1;
|
||||||
const initialUrl = params.get('updateUrl');
|
const initialUrl = params.get('updateUrl');
|
||||||
if (!initialUrl) throw 'No updateUrl parameter';
|
|
||||||
|
|
||||||
let installed = null;
|
let installed = null;
|
||||||
let installedDup = null;
|
let installedDup = null;
|
||||||
let initialized = false;
|
|
||||||
let filePort;
|
|
||||||
|
|
||||||
const liveReload = initLiveReload();
|
const liveReload = initLiveReload();
|
||||||
|
liveReload.ready.then(initSourceCode, error => messageBox.alert(error, 'pre'));
|
||||||
// when this tab is reloaded, bg may no longer have the code as it's kept only for a few seconds
|
|
||||||
API.getUsercssInstallCode(initialUrl)
|
|
||||||
.then(code => code || !filePort && download(initialUrl))
|
|
||||||
.then(code => (code || !filePort) && initSourceCode(code));
|
|
||||||
|
|
||||||
const theme = prefs.get('editor.theme');
|
const theme = prefs.get('editor.theme');
|
||||||
const cm = CodeMirror($('.main'), {
|
const cm = CodeMirror($('.main'), {
|
||||||
|
@ -172,7 +165,7 @@
|
||||||
} else {
|
} else {
|
||||||
API.openEditor({id: style.id});
|
API.openEditor({id: style.id});
|
||||||
if (!liveReload.enabled) {
|
if (!liveReload.enabled) {
|
||||||
if (!filePort && history.length > 1) {
|
if (tabId < 0 && history.length > 1) {
|
||||||
history.back();
|
history.back();
|
||||||
} else {
|
} else {
|
||||||
closeCurrentTab();
|
closeCurrentTab();
|
||||||
|
@ -234,8 +227,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function init({style, dup}) {
|
function init({style, dup}) {
|
||||||
initialized = true;
|
|
||||||
|
|
||||||
const data = style.usercssData;
|
const data = style.usercssData;
|
||||||
const dupData = dup && dup.usercssData;
|
const dupData = dup && dup.usercssData;
|
||||||
const versionTest = dup && semverCompare(data.version, dupData.version);
|
const versionTest = dup && semverCompare(data.version, dupData.version);
|
||||||
|
@ -321,66 +312,55 @@
|
||||||
const DELAY = 500;
|
const DELAY = 500;
|
||||||
let isEnabled = false;
|
let isEnabled = false;
|
||||||
let timer = 0;
|
let timer = 0;
|
||||||
let sequence = Promise.resolve();
|
/** @type function(?options):Promise<string|null> */
|
||||||
if (tabId >= 0) {
|
let getData = null;
|
||||||
filePort = chrome.tabs.connect(tabId, {name: 'downloadSelf'});
|
/** @type Promise */
|
||||||
filePort.postMessage('init');
|
let sequence = null;
|
||||||
filePort.onMessage.addListener(onPortMessage);
|
if (tabId < 0) {
|
||||||
filePort.onDisconnect.addListener(onPortDisconnect);
|
getData = DirectDownloader();
|
||||||
|
sequence = API.getUsercssInstallCode(initialUrl).catch(getData);
|
||||||
|
} else {
|
||||||
|
getData = PortDownloader();
|
||||||
|
sequence = getData({timer: false});
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
get enabled() {
|
get enabled() {
|
||||||
return isEnabled;
|
return isEnabled;
|
||||||
},
|
},
|
||||||
|
ready: sequence,
|
||||||
onToggled(e) {
|
onToggled(e) {
|
||||||
if (e) isEnabled = e.target.checked;
|
if (e) isEnabled = e.target.checked;
|
||||||
if (installed || installedDup) {
|
if (installed || installedDup) {
|
||||||
(isEnabled ? start : stop)();
|
(isEnabled ? start : stop)();
|
||||||
$('.install').disabled = isEnabled;
|
$('.install').disabled = isEnabled;
|
||||||
$('#live-reload-install-hint').hidden = !isEnabled;
|
Object.assign($('#live-reload-install-hint'), {
|
||||||
$('#live-reload-install-hint-ff').hidden = !isEnabled || !filePort;
|
hidden: !isEnabled,
|
||||||
|
textContent: t(`liveReloadInstallHint${tabId >= 0 ? 'FF' : ''}`),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
function onPortMessage({code, error}) {
|
|
||||||
if (error) {
|
|
||||||
messageBox.alert(error, 'pre');
|
|
||||||
} else if (!initialized) {
|
|
||||||
initSourceCode(code);
|
|
||||||
} else {
|
|
||||||
update(code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function onPortDisconnect() {
|
|
||||||
chrome.tabs.get(tabId, tab => {
|
|
||||||
if (chrome.runtime.lastError) {
|
|
||||||
closeCurrentTab();
|
|
||||||
} else if (tab.url === initialUrl) {
|
|
||||||
location.reload();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function check() {
|
function check() {
|
||||||
start(true);
|
getData()
|
||||||
if (filePort) {
|
.then(update, logError)
|
||||||
filePort.postMessage('timer');
|
.then(() => {
|
||||||
} else {
|
timer = 0;
|
||||||
download(initialUrl).then(update, logError);
|
start();
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
function logError(error) {
|
function logError(error) {
|
||||||
console.warn(t('liveReloadError', error));
|
console.warn(t('liveReloadError', error));
|
||||||
}
|
}
|
||||||
function start(reset) {
|
function start() {
|
||||||
timer = !reset && timer || setTimeout(check, DELAY);
|
timer = timer || setTimeout(check, DELAY);
|
||||||
}
|
}
|
||||||
function stop() {
|
function stop() {
|
||||||
clearTimeout(check);
|
clearTimeout(timer);
|
||||||
timer = 0;
|
timer = 0;
|
||||||
}
|
}
|
||||||
function update(code) {
|
function update(code) {
|
||||||
if (!code) return logError('EMPTY');
|
if (code == null) return;
|
||||||
sequence = sequence.then(() => {
|
sequence = sequence.catch(console.error).then(() => {
|
||||||
const {id} = installed || installedDup;
|
const {id} = installed || installedDup;
|
||||||
const scrollInfo = cm.getScrollInfo();
|
const scrollInfo = cm.getScrollInfo();
|
||||||
const cursor = cm.getCursor();
|
const cursor = cm.getCursor();
|
||||||
|
@ -392,5 +372,41 @@
|
||||||
.catch(showError);
|
.catch(showError);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function DirectDownloader() {
|
||||||
|
let oldCode = null;
|
||||||
|
const passChangedCode = code => {
|
||||||
|
const isSame = code === oldCode;
|
||||||
|
oldCode = code;
|
||||||
|
return isSame ? null : code;
|
||||||
|
};
|
||||||
|
return () => download(initialUrl).then(passChangedCode);
|
||||||
|
}
|
||||||
|
function PortDownloader() {
|
||||||
|
const resolvers = new Map();
|
||||||
|
const port = chrome.tabs.connect(tabId, {name: 'downloadSelf'});
|
||||||
|
port.onMessage.addListener(({id, code, error}) => {
|
||||||
|
const r = resolvers.get(id);
|
||||||
|
resolvers.delete(id);
|
||||||
|
if (error) {
|
||||||
|
r.reject(error);
|
||||||
|
} else {
|
||||||
|
r.resolve(code);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
port.onDisconnect.addListener(() => {
|
||||||
|
chrome.tabs.get(tabId, tab => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
closeCurrentTab();
|
||||||
|
} else if (tab.url === initialUrl) {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return ({timer = true} = {}) => new Promise((resolve, reject) => {
|
||||||
|
const id = performance.now();
|
||||||
|
resolvers.set(id, {resolve, reject});
|
||||||
|
port.postMessage({id, timer});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -242,7 +242,6 @@ self.API = self.INJECTED === 1 ? self.API : new Proxy({
|
||||||
// Handlers for these methods need sender.tab.id which is set by `send` as it uses messaging,
|
// Handlers for these methods need sender.tab.id which is set by `send` as it uses messaging,
|
||||||
// unlike `sendBg` which invokes the background page directly in our own extension tabs
|
// unlike `sendBg` which invokes the background page directly in our own extension tabs
|
||||||
getTabUrlPrefix: true,
|
getTabUrlPrefix: true,
|
||||||
getUsercssInstallCode: true,
|
|
||||||
updateIconBadge: true,
|
updateIconBadge: true,
|
||||||
styleViaAPI: true,
|
styleViaAPI: true,
|
||||||
}, {
|
}, {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user