stylus/popup/preinit.js
tophf 922c66a141 use executeScript for early injection + split/async'ify
* split, regroup, and async'ify files
* consistent window scrolling in scrollToEditor and jumpToPos
* rework waitForSelector and collapsible <details>
* parserlib: fast section extraction, tweaks and speedups
* csslint: "simple-not" rule
* csslint: enable and fix "selector-newline" rule
* blank paint frame workaround for new Chrome
* extract stuff from edit.js and load on demand
* simplify regexpTester::isShown
* move MozDocMapper to sections-util.js
* extract fitSelectBox()
* initialize router earlier
* use helpPopup.close()
* fix autofocus in popups, follow-up to 5bb1b5ef
* clone objects in prefs.get() + cosmetics
* reuse getAll result for INC
2021-01-01 17:22:28 +03:00

78 lines
2.6 KiB
JavaScript

/* global API */// msg.js
/* global URLS */// toolbox.js
'use strict';
const ABOUT_BLANK = 'about:blank';
/* exported preinit */
const preinit = (async () => {
let [tab] = await browser.tabs.query({currentWindow: true, active: true});
if (!chrome.app && tab.status === 'loading' && tab.url === ABOUT_BLANK) {
tab = await waitForTabUrlFF(tab);
}
const frames = sortTabFrames(await browser.webNavigation.getAllFrames({tabId: tab.id}));
let url = tab.pendingUrl || tab.url || ''; // new Chrome uses pendingUrl while connecting
if (url === 'chrome://newtab/' && !URLS.chromeProtectsNTP) {
url = frames[0].url || '';
}
if (!URLS.supported(url)) {
url = '';
frames.length = 1;
}
frames[0].url = url;
const uniqFrames = frames.filter(f => f.url && !f.isDupe);
const styles = await Promise.all(uniqFrames.map(async ({url}) => ({
url,
styles: await getStyleDataMerged(url),
})));
return {frames, styles, url};
})();
/* Merges the extra props from API into style data.
* When `id` is specified returns a single object otherwise an array */
async function getStyleDataMerged(url, id) {
const styles = (await API.styles.getByUrl(url, id))
.map(r => Object.assign(r.style, r));
return id ? styles[0] : styles;
}
/** @param {browser.webNavigation._GetAllFramesReturnDetails[]} frames */
function sortTabFrames(frames) {
const unknown = new Map(frames.map(f => [f.frameId, f]));
const known = new Map([[0, unknown.get(0) || {frameId: 0, url: ''}]]);
unknown.delete(0);
let lastSize = 0;
while (unknown.size !== lastSize) {
for (const [frameId, f] of unknown) {
if (known.has(f.parentFrameId)) {
unknown.delete(frameId);
if (!f.errorOccurred) known.set(frameId, f);
if (f.url === ABOUT_BLANK) f.url = known.get(f.parentFrameId).url;
}
}
lastSize = unknown.size; // guard against an infinite loop due to a weird frame structure
}
const sortedFrames = [...known.values(), ...unknown.values()];
const urls = new Set([ABOUT_BLANK]);
for (const f of sortedFrames) {
if (!f.url) f.url = '';
f.isDupe = urls.has(f.url);
urls.add(f.url);
}
return sortedFrames;
}
function waitForTabUrlFF(tab) {
return new Promise(resolve => {
browser.tabs.onUpdated.addListener(...[
function onUpdated(tabId, info, updatedTab) {
if (info.url && tabId === tab.id) {
browser.tabs.onUpdated.removeListener(onUpdated);
resolve(updatedTab);
}
},
...'UpdateFilter' in browser.tabs ? [{tabId: tab.id}] : [],
// TODO: remove both spreads and tabId check when strict_min_version >= 61
]);
});
}